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.285 2008/10/04 21:56:54 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.
96 * For deparsing plan trees, we provide for outer and inner subplan nodes.
97 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
101 List *rtable; /* List of RangeTblEntry nodes */
102 Plan *outer_plan; /* OUTER subplan, or NULL if none */
103 Plan *inner_plan; /* INNER subplan, or NULL if none */
111 static SPIPlanPtr plan_getrulebyoid = NULL;
112 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
113 static SPIPlanPtr plan_getviewrule = NULL;
114 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
120 * Most of these functions used to use fixed-size buffers to build their
121 * results. Now, they take an (already initialized) StringInfo object
122 * as a parameter, and append their text output to its contents.
125 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
126 bool forceprefix, bool showimplicit,
127 int prettyFlags, int startIndent);
128 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
129 static void decompile_column_index_array(Datum column_index_array, Oid relId,
131 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
132 static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
134 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
136 static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
138 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
139 bool print_table_args);
140 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
141 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
143 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
145 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
146 TupleDesc resultDesc, int prettyFlags, int startIndent);
147 static void get_values_def(List *values_lists, deparse_context *context);
148 static void get_with_clause(Query *query, deparse_context *context);
149 static void get_select_query_def(Query *query, deparse_context *context,
150 TupleDesc resultDesc);
151 static void get_insert_query_def(Query *query, deparse_context *context);
152 static void get_update_query_def(Query *query, deparse_context *context);
153 static void get_delete_query_def(Query *query, deparse_context *context);
154 static void get_utility_query_def(Query *query, deparse_context *context);
155 static void get_basic_select_query(Query *query, deparse_context *context,
156 TupleDesc resultDesc);
157 static void get_target_list(List *targetList, deparse_context *context,
158 TupleDesc resultDesc);
159 static void get_setop_query(Node *setOp, Query *query,
160 deparse_context *context,
161 TupleDesc resultDesc);
162 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
164 deparse_context *context);
165 static char *get_variable(Var *var, int levelsup, bool showstar,
166 deparse_context *context);
167 static RangeTblEntry *find_rte_by_refname(const char *refname,
168 deparse_context *context);
169 static const char *get_simple_binary_op_name(OpExpr *expr);
170 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
171 static void appendStringInfoSpaces(StringInfo buf, int count);
172 static void appendContextKeyword(deparse_context *context, const char *str,
173 int indentBefore, int indentAfter, int indentPlus);
174 static void get_rule_expr(Node *node, deparse_context *context,
176 static void get_oper_expr(OpExpr *expr, deparse_context *context);
177 static void get_func_expr(FuncExpr *expr, deparse_context *context,
179 static void get_agg_expr(Aggref *aggref, deparse_context *context);
180 static void get_coercion_expr(Node *arg, deparse_context *context,
181 Oid resulttype, int32 resulttypmod,
183 static void get_const_expr(Const *constval, deparse_context *context,
185 static void simple_quote_literal(StringInfo buf, const char *val);
186 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
187 static void get_from_clause(Query *query, const char *prefix,
188 deparse_context *context);
189 static void get_from_clause_item(Node *jtnode, Query *query,
190 deparse_context *context);
191 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
192 deparse_context *context);
193 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
194 deparse_context *context);
195 static void get_opclass_name(Oid opclass, Oid actual_datatype,
197 static Node *processIndirection(Node *node, deparse_context *context,
199 static void printSubscripts(ArrayRef *aref, deparse_context *context);
200 static char *generate_relation_name(Oid relid);
201 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes,
203 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
204 static text *string_to_text(char *str);
205 static char *flatten_reloptions(Oid relid);
207 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
211 * get_ruledef - Do it all and return a text
212 * that could be used as a statement
213 * to recreate the rule
217 pg_get_ruledef(PG_FUNCTION_ARGS)
219 Oid ruleoid = PG_GETARG_OID(0);
221 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
226 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
228 Oid ruleoid = PG_GETARG_OID(0);
229 bool pretty = PG_GETARG_BOOL(1);
232 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
233 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
238 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
248 * Do this first so that string is alloc'd in outer context not SPI's.
250 initStringInfo(&buf);
253 * Connect to SPI manager
255 if (SPI_connect() != SPI_OK_CONNECT)
256 elog(ERROR, "SPI_connect failed");
259 * On the first call prepare the plan to lookup pg_rewrite. We read
260 * pg_rewrite over the SPI manager instead of using the syscache to be
261 * checked for read access on pg_rewrite.
263 if (plan_getrulebyoid == NULL)
268 argtypes[0] = OIDOID;
269 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
271 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
272 plan_getrulebyoid = SPI_saveplan(plan);
276 * Get the pg_rewrite tuple for this rule
278 args[0] = ObjectIdGetDatum(ruleoid);
280 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
281 if (spirc != SPI_OK_SELECT)
282 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
283 if (SPI_processed != 1)
284 appendStringInfo(&buf, "-");
288 * Get the rule's definition and put it into executor's memory
290 ruletup = SPI_tuptable->vals[0];
291 rulettc = SPI_tuptable->tupdesc;
292 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
296 * Disconnect from SPI manager
298 if (SPI_finish() != SPI_OK_FINISH)
299 elog(ERROR, "SPI_finish failed");
306 * get_viewdef - Mainly the same thing, but we
307 * only return the SELECT part of a view
311 pg_get_viewdef(PG_FUNCTION_ARGS)
314 Oid viewoid = PG_GETARG_OID(0);
316 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
321 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
324 Oid viewoid = PG_GETARG_OID(0);
325 bool pretty = PG_GETARG_BOOL(1);
328 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
329 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
333 pg_get_viewdef_name(PG_FUNCTION_ARGS)
335 /* By qualified name */
336 text *viewname = PG_GETARG_TEXT_P(0);
340 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
341 viewoid = RangeVarGetRelid(viewrel, false);
343 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
348 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
350 /* By qualified name */
351 text *viewname = PG_GETARG_TEXT_P(0);
352 bool pretty = PG_GETARG_BOOL(1);
357 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
358 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
359 viewoid = RangeVarGetRelid(viewrel, false);
361 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
365 * Common code for by-OID and by-name variants of pg_get_viewdef
368 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
378 * Do this first so that string is alloc'd in outer context not SPI's.
380 initStringInfo(&buf);
383 * Connect to SPI manager
385 if (SPI_connect() != SPI_OK_CONNECT)
386 elog(ERROR, "SPI_connect failed");
389 * On the first call prepare the plan to lookup pg_rewrite. We read
390 * pg_rewrite over the SPI manager instead of using the syscache to be
391 * checked for read access on pg_rewrite.
393 if (plan_getviewrule == NULL)
398 argtypes[0] = OIDOID;
399 argtypes[1] = NAMEOID;
400 plan = SPI_prepare(query_getviewrule, 2, argtypes);
402 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
403 plan_getviewrule = SPI_saveplan(plan);
407 * Get the pg_rewrite tuple for the view's SELECT rule
409 args[0] = ObjectIdGetDatum(viewoid);
410 args[1] = PointerGetDatum(ViewSelectRuleName);
413 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
414 if (spirc != SPI_OK_SELECT)
415 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
416 if (SPI_processed != 1)
417 appendStringInfo(&buf, "Not a view");
421 * Get the rule's definition and put it into executor's memory
423 ruletup = SPI_tuptable->vals[0];
424 rulettc = SPI_tuptable->tupdesc;
425 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
429 * Disconnect from SPI manager
431 if (SPI_finish() != SPI_OK_FINISH)
432 elog(ERROR, "SPI_finish failed");
438 * get_triggerdef - Get the definition of a trigger
442 pg_get_triggerdef(PG_FUNCTION_ARGS)
444 Oid trigid = PG_GETARG_OID(0);
446 Form_pg_trigger trigrec;
455 * Fetch the pg_trigger tuple by the Oid of the trigger
457 tgrel = heap_open(TriggerRelationId, AccessShareLock);
459 ScanKeyInit(&skey[0],
460 ObjectIdAttributeNumber,
461 BTEqualStrategyNumber, F_OIDEQ,
462 ObjectIdGetDatum(trigid));
464 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
465 SnapshotNow, 1, skey);
467 ht_trig = systable_getnext(tgscan);
469 if (!HeapTupleIsValid(ht_trig))
470 elog(ERROR, "could not find tuple for trigger %u", trigid);
472 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
475 * Start the trigger definition. Note that the trigger's name should never
476 * be schema-qualified, but the trigger rel's name may be.
478 initStringInfo(&buf);
480 tgname = NameStr(trigrec->tgname);
481 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
482 trigrec->tgisconstraint ? "CONSTRAINT " : "",
483 quote_identifier(tgname));
485 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
486 appendStringInfo(&buf, "BEFORE");
488 appendStringInfo(&buf, "AFTER");
489 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
491 appendStringInfo(&buf, " INSERT");
494 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
497 appendStringInfo(&buf, " OR DELETE");
499 appendStringInfo(&buf, " DELETE");
502 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
505 appendStringInfo(&buf, " OR UPDATE");
507 appendStringInfo(&buf, " UPDATE");
509 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
512 appendStringInfo(&buf, " OR TRUNCATE");
514 appendStringInfo(&buf, " TRUNCATE");
516 appendStringInfo(&buf, " ON %s ",
517 generate_relation_name(trigrec->tgrelid));
519 if (trigrec->tgisconstraint)
521 if (trigrec->tgconstrrelid != InvalidOid)
522 appendStringInfo(&buf, "FROM %s ",
523 generate_relation_name(trigrec->tgconstrrelid));
524 if (!trigrec->tgdeferrable)
525 appendStringInfo(&buf, "NOT ");
526 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
527 if (trigrec->tginitdeferred)
528 appendStringInfo(&buf, "DEFERRED ");
530 appendStringInfo(&buf, "IMMEDIATE ");
534 if (TRIGGER_FOR_ROW(trigrec->tgtype))
535 appendStringInfo(&buf, "FOR EACH ROW ");
537 appendStringInfo(&buf, "FOR EACH STATEMENT ");
539 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
540 generate_function_name(trigrec->tgfoid, 0, NULL, NULL));
542 if (trigrec->tgnargs > 0)
549 val = DatumGetByteaP(fastgetattr(ht_trig,
550 Anum_pg_trigger_tgargs,
551 tgrel->rd_att, &isnull));
553 elog(ERROR, "tgargs is null for trigger %u", trigid);
554 p = (char *) VARDATA(val);
555 for (i = 0; i < trigrec->tgnargs; i++)
558 appendStringInfo(&buf, ", ");
559 simple_quote_literal(&buf, p);
560 /* advance p to next string embedded in tgargs */
567 /* We deliberately do not put semi-colon at end */
568 appendStringInfo(&buf, ")");
571 systable_endscan(tgscan);
573 heap_close(tgrel, AccessShareLock);
575 PG_RETURN_TEXT_P(string_to_text(buf.data));
579 * get_indexdef - Get the definition of an index
581 * In the extended version, there is a colno argument as well as pretty bool.
582 * if colno == 0, we want a complete index definition.
583 * if colno > 0, we only want the Nth index key's variable or expression.
585 * Note that the SQL-function versions of this omit any info about the
586 * index tablespace; this is intentional because pg_dump wants it that way.
587 * However pg_get_indexdef_string() includes index tablespace if not default.
591 pg_get_indexdef(PG_FUNCTION_ARGS)
593 Oid indexrelid = PG_GETARG_OID(0);
595 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
600 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
602 Oid indexrelid = PG_GETARG_OID(0);
603 int32 colno = PG_GETARG_INT32(1);
604 bool pretty = PG_GETARG_BOOL(2);
607 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
608 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
609 false, prettyFlags)));
612 /* Internal version that returns a palloc'd C string */
614 pg_get_indexdef_string(Oid indexrelid)
616 return pg_get_indexdef_worker(indexrelid, 0, true, 0);
620 pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
626 Form_pg_index idxrec;
627 Form_pg_class idxrelrec;
630 ListCell *indexpr_item;
636 Datum indoptionDatum;
639 int2vector *indoption;
645 * Fetch the pg_index tuple by the Oid of the index
647 ht_idx = SearchSysCache(INDEXRELID,
648 ObjectIdGetDatum(indexrelid),
650 if (!HeapTupleIsValid(ht_idx))
651 elog(ERROR, "cache lookup failed for index %u", indexrelid);
652 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
654 indrelid = idxrec->indrelid;
655 Assert(indexrelid == idxrec->indexrelid);
657 /* Must get indclass and indoption the hard way */
658 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
659 Anum_pg_index_indclass, &isnull);
661 indclass = (oidvector *) DatumGetPointer(indclassDatum);
662 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
663 Anum_pg_index_indoption, &isnull);
665 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
668 * Fetch the pg_class tuple of the index relation
670 ht_idxrel = SearchSysCache(RELOID,
671 ObjectIdGetDatum(indexrelid),
673 if (!HeapTupleIsValid(ht_idxrel))
674 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
675 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
678 * Fetch the pg_am tuple of the index' access method
680 ht_am = SearchSysCache(AMOID,
681 ObjectIdGetDatum(idxrelrec->relam),
683 if (!HeapTupleIsValid(ht_am))
684 elog(ERROR, "cache lookup failed for access method %u",
686 amrec = (Form_pg_am) GETSTRUCT(ht_am);
689 * Get the index expressions, if any. (NOTE: we do not use the relcache
690 * versions of the expressions and predicate, because we want to display
691 * non-const-folded expressions.)
693 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
699 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
700 Anum_pg_index_indexprs, &isnull);
702 exprsString = TextDatumGetCString(exprsDatum);
703 indexprs = (List *) stringToNode(exprsString);
709 indexpr_item = list_head(indexprs);
711 context = deparse_context_for(get_rel_name(indrelid), indrelid);
714 * Start the index definition. Note that the index's name should never be
715 * schema-qualified, but the indexed rel's name may be.
717 initStringInfo(&buf);
720 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
721 idxrec->indisunique ? "UNIQUE " : "",
722 quote_identifier(NameStr(idxrelrec->relname)),
723 generate_relation_name(indrelid),
724 quote_identifier(NameStr(amrec->amname)));
727 * Report the indexed attributes
730 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
732 AttrNumber attnum = idxrec->indkey.values[keyno];
733 int16 opt = indoption->values[keyno];
736 appendStringInfoString(&buf, sep);
741 /* Simple index column */
744 attname = get_relid_attribute_name(indrelid, attnum);
745 if (!colno || colno == keyno + 1)
746 appendStringInfoString(&buf, quote_identifier(attname));
747 keycoltype = get_atttype(indrelid, attnum);
751 /* expressional index */
754 if (indexpr_item == NULL)
755 elog(ERROR, "too few entries in indexprs list");
756 indexkey = (Node *) lfirst(indexpr_item);
757 indexpr_item = lnext(indexpr_item);
759 str = deparse_expression_pretty(indexkey, context, false, false,
761 if (!colno || colno == keyno + 1)
763 /* Need parens if it's not a bare function call */
764 if (indexkey && IsA(indexkey, FuncExpr) &&
765 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
766 appendStringInfoString(&buf, str);
768 appendStringInfo(&buf, "(%s)", str);
770 keycoltype = exprType(indexkey);
773 /* Provide decoration only in the colno=0 case */
776 /* Add the operator class name, if not default */
777 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
779 /* Add options if relevant */
780 if (amrec->amcanorder)
782 /* if it supports sort ordering, report DESC and NULLS opts */
783 if (opt & INDOPTION_DESC)
785 appendStringInfo(&buf, " DESC");
786 /* NULLS FIRST is the default in this case */
787 if (!(opt & INDOPTION_NULLS_FIRST))
788 appendStringInfo(&buf, " NULLS LAST");
792 if (opt & INDOPTION_NULLS_FIRST)
793 appendStringInfo(&buf, " NULLS FIRST");
801 appendStringInfoChar(&buf, ')');
804 * If it has options, append "WITH (options)"
806 str = flatten_reloptions(indexrelid);
809 appendStringInfo(&buf, " WITH (%s)", str);
814 * If it's in a nondefault tablespace, say so, but only if requested
820 tblspc = get_rel_tablespace(indexrelid);
821 if (OidIsValid(tblspc))
822 appendStringInfo(&buf, " TABLESPACE %s",
823 quote_identifier(get_tablespace_name(tblspc)));
827 * If it's a partial index, decompile and append the predicate
829 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
836 /* Convert text string to node tree */
837 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
838 Anum_pg_index_indpred, &isnull);
840 predString = TextDatumGetCString(predDatum);
841 node = (Node *) stringToNode(predString);
845 str = deparse_expression_pretty(node, context, false, false,
847 appendStringInfo(&buf, " WHERE %s", str);
852 ReleaseSysCache(ht_idx);
853 ReleaseSysCache(ht_idxrel);
854 ReleaseSysCache(ht_am);
861 * pg_get_constraintdef
863 * Returns the definition for the constraint, ie, everything that needs to
864 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
867 pg_get_constraintdef(PG_FUNCTION_ARGS)
869 Oid constraintId = PG_GETARG_OID(0);
871 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
876 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
878 Oid constraintId = PG_GETARG_OID(0);
879 bool pretty = PG_GETARG_BOOL(1);
882 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
883 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
884 false, prettyFlags)));
887 /* Internal version that returns a palloc'd C string */
889 pg_get_constraintdef_string(Oid constraintId)
891 return pg_get_constraintdef_worker(constraintId, true, 0);
895 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
899 Form_pg_constraint conForm;
902 tup = SearchSysCache(CONSTROID,
903 ObjectIdGetDatum(constraintId),
905 if (!HeapTupleIsValid(tup)) /* should not happen */
906 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
907 conForm = (Form_pg_constraint) GETSTRUCT(tup);
909 initStringInfo(&buf);
911 if (fullCommand && OidIsValid(conForm->conrelid))
913 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
914 generate_relation_name(conForm->conrelid),
915 quote_identifier(NameStr(conForm->conname)));
918 switch (conForm->contype)
920 case CONSTRAINT_FOREIGN:
926 /* Start off the constraint definition */
927 appendStringInfo(&buf, "FOREIGN KEY (");
929 /* Fetch and build referencing-column list */
930 val = SysCacheGetAttr(CONSTROID, tup,
931 Anum_pg_constraint_conkey, &isnull);
933 elog(ERROR, "null conkey for constraint %u",
936 decompile_column_index_array(val, conForm->conrelid, &buf);
938 /* add foreign relation name */
939 appendStringInfo(&buf, ") REFERENCES %s(",
940 generate_relation_name(conForm->confrelid));
942 /* Fetch and build referenced-column list */
943 val = SysCacheGetAttr(CONSTROID, tup,
944 Anum_pg_constraint_confkey, &isnull);
946 elog(ERROR, "null confkey for constraint %u",
949 decompile_column_index_array(val, conForm->confrelid, &buf);
951 appendStringInfo(&buf, ")");
954 switch (conForm->confmatchtype)
956 case FKCONSTR_MATCH_FULL:
957 string = " MATCH FULL";
959 case FKCONSTR_MATCH_PARTIAL:
960 string = " MATCH PARTIAL";
962 case FKCONSTR_MATCH_UNSPECIFIED:
966 elog(ERROR, "unrecognized confmatchtype: %d",
967 conForm->confmatchtype);
968 string = ""; /* keep compiler quiet */
971 appendStringInfoString(&buf, string);
973 /* Add ON UPDATE and ON DELETE clauses, if needed */
974 switch (conForm->confupdtype)
976 case FKCONSTR_ACTION_NOACTION:
977 string = NULL; /* suppress default */
979 case FKCONSTR_ACTION_RESTRICT:
982 case FKCONSTR_ACTION_CASCADE:
985 case FKCONSTR_ACTION_SETNULL:
988 case FKCONSTR_ACTION_SETDEFAULT:
989 string = "SET DEFAULT";
992 elog(ERROR, "unrecognized confupdtype: %d",
993 conForm->confupdtype);
994 string = NULL; /* keep compiler quiet */
998 appendStringInfo(&buf, " ON UPDATE %s", string);
1000 switch (conForm->confdeltype)
1002 case FKCONSTR_ACTION_NOACTION:
1003 string = NULL; /* suppress default */
1005 case FKCONSTR_ACTION_RESTRICT:
1006 string = "RESTRICT";
1008 case FKCONSTR_ACTION_CASCADE:
1011 case FKCONSTR_ACTION_SETNULL:
1012 string = "SET NULL";
1014 case FKCONSTR_ACTION_SETDEFAULT:
1015 string = "SET DEFAULT";
1018 elog(ERROR, "unrecognized confdeltype: %d",
1019 conForm->confdeltype);
1020 string = NULL; /* keep compiler quiet */
1024 appendStringInfo(&buf, " ON DELETE %s", string);
1026 if (conForm->condeferrable)
1027 appendStringInfo(&buf, " DEFERRABLE");
1028 if (conForm->condeferred)
1029 appendStringInfo(&buf, " INITIALLY DEFERRED");
1033 case CONSTRAINT_PRIMARY:
1034 case CONSTRAINT_UNIQUE:
1040 /* Start off the constraint definition */
1041 if (conForm->contype == CONSTRAINT_PRIMARY)
1042 appendStringInfo(&buf, "PRIMARY KEY (");
1044 appendStringInfo(&buf, "UNIQUE (");
1046 /* Fetch and build target column list */
1047 val = SysCacheGetAttr(CONSTROID, tup,
1048 Anum_pg_constraint_conkey, &isnull);
1050 elog(ERROR, "null conkey for constraint %u",
1053 decompile_column_index_array(val, conForm->conrelid, &buf);
1055 appendStringInfo(&buf, ")");
1057 indexId = get_constraint_index(constraintId);
1059 /* XXX why do we only print these bits if fullCommand? */
1060 if (fullCommand && OidIsValid(indexId))
1062 char *options = flatten_reloptions(indexId);
1067 appendStringInfo(&buf, " WITH (%s)", options);
1071 tblspc = get_rel_tablespace(indexId);
1072 if (OidIsValid(tblspc))
1073 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1074 quote_identifier(get_tablespace_name(tblspc)));
1079 case CONSTRAINT_CHECK:
1088 /* Fetch constraint expression in parsetree form */
1089 val = SysCacheGetAttr(CONSTROID, tup,
1090 Anum_pg_constraint_conbin, &isnull);
1092 elog(ERROR, "null conbin for constraint %u",
1095 conbin = TextDatumGetCString(val);
1096 expr = stringToNode(conbin);
1098 /* Set up deparsing context for Var nodes in constraint */
1099 if (conForm->conrelid != InvalidOid)
1101 /* relation constraint */
1102 context = deparse_context_for(get_rel_name(conForm->conrelid),
1107 /* domain constraint --- can't have Vars */
1111 consrc = deparse_expression_pretty(expr, context, false, false,
1115 * Now emit the constraint definition. There are cases where
1116 * the constraint expression will be fully parenthesized and
1117 * we don't need the outer parens ... but there are other
1118 * cases where we do need 'em. Be conservative for now.
1120 * Note that simply checking for leading '(' and trailing ')'
1121 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1123 appendStringInfo(&buf, "CHECK (%s)", consrc);
1128 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1133 ReleaseSysCache(tup);
1140 * Convert an int16[] Datum into a comma-separated list of column names
1141 * for the indicated relation; append the list to buf.
1144 decompile_column_index_array(Datum column_index_array, Oid relId,
1151 /* Extract data from array of int16 */
1152 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1153 INT2OID, 2, true, 's',
1154 &keys, NULL, &nKeys);
1156 for (j = 0; j < nKeys; j++)
1160 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1163 appendStringInfoString(buf, quote_identifier(colName));
1165 appendStringInfo(buf, ", %s", quote_identifier(colName));
1171 * get_expr - Decompile an expression tree
1173 * Input: an expression tree in nodeToString form, and a relation OID
1175 * Output: reverse-listed expression
1177 * Currently, the expression can only refer to a single relation, namely
1178 * the one specified by the second parameter. This is sufficient for
1179 * partial indexes, column default expressions, etc.
1183 pg_get_expr(PG_FUNCTION_ARGS)
1185 text *expr = PG_GETARG_TEXT_P(0);
1186 Oid relid = PG_GETARG_OID(1);
1189 /* Get the name for the relation */
1190 relname = get_rel_name(relid);
1191 if (relname == NULL)
1192 PG_RETURN_NULL(); /* should we raise an error? */
1194 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1198 pg_get_expr_ext(PG_FUNCTION_ARGS)
1200 text *expr = PG_GETARG_TEXT_P(0);
1201 Oid relid = PG_GETARG_OID(1);
1202 bool pretty = PG_GETARG_BOOL(2);
1206 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1208 /* Get the name for the relation */
1209 relname = get_rel_name(relid);
1210 if (relname == NULL)
1211 PG_RETURN_NULL(); /* should we raise an error? */
1213 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1217 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1224 /* Convert input TEXT object to C string */
1225 exprstr = text_to_cstring(expr);
1227 /* Convert expression to node tree */
1228 node = (Node *) stringToNode(exprstr);
1231 context = deparse_context_for(relname, relid);
1232 str = deparse_expression_pretty(node, context, false, false,
1242 * get_userbyid - Get a user name by roleid and
1243 * fallback to 'unknown (OID=n)'
1247 pg_get_userbyid(PG_FUNCTION_ARGS)
1249 Oid roleid = PG_GETARG_OID(0);
1252 Form_pg_authid role_rec;
1255 * Allocate space for the result
1257 result = (Name) palloc(NAMEDATALEN);
1258 memset(NameStr(*result), 0, NAMEDATALEN);
1261 * Get the pg_authid entry and print the result
1263 roletup = SearchSysCache(AUTHOID,
1264 ObjectIdGetDatum(roleid),
1266 if (HeapTupleIsValid(roletup))
1268 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1269 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1270 ReleaseSysCache(roletup);
1273 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1275 PG_RETURN_NAME(result);
1280 * pg_get_serial_sequence
1281 * Get the name of the sequence used by a serial column,
1282 * formatted suitably for passing to setval, nextval or currval.
1283 * First parameter is not treated as double-quoted, second parameter
1284 * is --- see documentation for reason.
1287 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1289 text *tablename = PG_GETARG_TEXT_P(0);
1290 text *columnname = PG_GETARG_TEXT_PP(1);
1295 Oid sequenceId = InvalidOid;
1301 /* Get the OID of the table */
1302 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1303 tableOid = RangeVarGetRelid(tablerv, false);
1305 /* Get the number of the column */
1306 column = text_to_cstring(columnname);
1308 attnum = get_attnum(tableOid, column);
1309 if (attnum == InvalidAttrNumber)
1311 (errcode(ERRCODE_UNDEFINED_COLUMN),
1312 errmsg("column \"%s\" of relation \"%s\" does not exist",
1313 column, tablerv->relname)));
1315 /* Search the dependency table for the dependent sequence */
1316 depRel = heap_open(DependRelationId, AccessShareLock);
1318 ScanKeyInit(&key[0],
1319 Anum_pg_depend_refclassid,
1320 BTEqualStrategyNumber, F_OIDEQ,
1321 ObjectIdGetDatum(RelationRelationId));
1322 ScanKeyInit(&key[1],
1323 Anum_pg_depend_refobjid,
1324 BTEqualStrategyNumber, F_OIDEQ,
1325 ObjectIdGetDatum(tableOid));
1326 ScanKeyInit(&key[2],
1327 Anum_pg_depend_refobjsubid,
1328 BTEqualStrategyNumber, F_INT4EQ,
1329 Int32GetDatum(attnum));
1331 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1332 SnapshotNow, 3, key);
1334 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1336 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1339 * We assume any auto dependency of a sequence on a column must be
1340 * what we are looking for. (We need the relkind test because indexes
1341 * can also have auto dependencies on columns.)
1343 if (deprec->classid == RelationRelationId &&
1344 deprec->objsubid == 0 &&
1345 deprec->deptype == DEPENDENCY_AUTO &&
1346 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1348 sequenceId = deprec->objid;
1353 systable_endscan(scan);
1354 heap_close(depRel, AccessShareLock);
1356 if (OidIsValid(sequenceId))
1359 Form_pg_class classtuple;
1363 /* Get the sequence's pg_class entry */
1364 classtup = SearchSysCache(RELOID,
1365 ObjectIdGetDatum(sequenceId),
1367 if (!HeapTupleIsValid(classtup))
1368 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1369 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1371 /* Get the namespace */
1372 nspname = get_namespace_name(classtuple->relnamespace);
1374 elog(ERROR, "cache lookup failed for namespace %u",
1375 classtuple->relnamespace);
1377 /* And construct the result string */
1378 result = quote_qualified_identifier(nspname,
1379 NameStr(classtuple->relname));
1381 ReleaseSysCache(classtup);
1383 PG_RETURN_TEXT_P(string_to_text(result));
1391 * pg_get_functiondef
1392 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1393 * the specified function.
1396 pg_get_functiondef(PG_FUNCTION_ARGS)
1398 Oid funcid = PG_GETARG_OID(0);
1404 Form_pg_language lang;
1413 initStringInfo(&buf);
1415 /* Look up the function */
1416 proctup = SearchSysCache(PROCOID,
1417 ObjectIdGetDatum(funcid),
1419 if (!HeapTupleIsValid(proctup))
1420 elog(ERROR, "cache lookup failed for function %u", funcid);
1421 proc = (Form_pg_proc) GETSTRUCT(proctup);
1422 name = NameStr(proc->proname);
1426 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1427 errmsg("\"%s\" is an aggregate function", name)));
1429 /* Need its pg_language tuple for the language name */
1430 langtup = SearchSysCache(LANGOID,
1431 ObjectIdGetDatum(proc->prolang),
1433 if (!HeapTupleIsValid(langtup))
1434 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1435 lang = (Form_pg_language) GETSTRUCT(langtup);
1438 * We always qualify the function name, to ensure the right function
1441 nsp = get_namespace_name(proc->pronamespace);
1442 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1443 quote_qualified_identifier(nsp, name));
1444 (void) print_function_arguments(&buf, proctup, false);
1445 appendStringInfoString(&buf, ")\n RETURNS ");
1446 print_function_rettype(&buf, proctup);
1447 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1448 quote_identifier(NameStr(lang->lanname)));
1450 /* Emit some miscellaneous options on one line */
1453 switch (proc->provolatile)
1455 case PROVOLATILE_IMMUTABLE:
1456 appendStringInfoString(&buf, " IMMUTABLE");
1458 case PROVOLATILE_STABLE:
1459 appendStringInfoString(&buf, " STABLE");
1461 case PROVOLATILE_VOLATILE:
1464 if (proc->proisstrict)
1465 appendStringInfoString(&buf, " STRICT");
1466 if (proc->prosecdef)
1467 appendStringInfoString(&buf, " SECURITY DEFINER");
1469 /* This code for the default cost and rows should match functioncmds.c */
1470 if (proc->prolang == INTERNALlanguageId ||
1471 proc->prolang == ClanguageId)
1475 if (proc->procost != procost)
1476 appendStringInfo(&buf, " COST %g", proc->procost);
1478 if (proc->prorows > 0 && proc->prorows != 1000)
1479 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1481 if (oldlen != buf.len)
1482 appendStringInfoChar(&buf, '\n');
1484 /* Emit any proconfig options, one per line */
1485 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1488 ArrayType *a = DatumGetArrayTypeP(tmp);
1491 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1492 Assert(ARR_NDIM(a) == 1);
1493 Assert(ARR_LBOUND(a)[0] == 1);
1495 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1499 d = array_ref(a, 1, &i,
1500 -1 /* varlenarray */ ,
1501 -1 /* TEXT's typlen */ ,
1502 false /* TEXT's typbyval */ ,
1503 'i' /* TEXT's typalign */ ,
1507 char *configitem = TextDatumGetCString(d);
1510 pos = strchr(configitem, '=');
1515 appendStringInfo(&buf, " SET %s TO ",
1516 quote_identifier(configitem));
1519 * Some GUC variable names are 'LIST' type and hence must not
1522 if (pg_strcasecmp(configitem, "DateStyle") == 0
1523 || pg_strcasecmp(configitem, "search_path") == 0)
1524 appendStringInfoString(&buf, pos);
1526 simple_quote_literal(&buf, pos);
1527 appendStringInfoChar(&buf, '\n');
1532 /* And finally the function definition ... */
1533 appendStringInfoString(&buf, "AS ");
1535 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1538 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1539 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1542 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1544 elog(ERROR, "null prosrc");
1545 prosrc = TextDatumGetCString(tmp);
1548 * We always use dollar quoting. Figure out a suitable delimiter.
1550 * Since the user is likely to be editing the function body string,
1551 * we shouldn't use a short delimiter that he might easily create a
1552 * conflict with. Hence prefer "$function$", but extend if needed.
1554 initStringInfo(&dq);
1555 appendStringInfoString(&dq, "$function");
1556 while (strstr(prosrc, dq.data) != NULL)
1557 appendStringInfoChar(&dq, 'x');
1558 appendStringInfoChar(&dq, '$');
1560 appendStringInfoString(&buf, dq.data);
1561 appendStringInfoString(&buf, prosrc);
1562 appendStringInfoString(&buf, dq.data);
1564 appendStringInfoString(&buf, "\n");
1566 ReleaseSysCache(langtup);
1567 ReleaseSysCache(proctup);
1569 PG_RETURN_TEXT_P(string_to_text(buf.data));
1573 * pg_get_function_arguments
1574 * Get a nicely-formatted list of arguments for a function.
1575 * This is everything that would go between the parentheses in
1579 pg_get_function_arguments(PG_FUNCTION_ARGS)
1581 Oid funcid = PG_GETARG_OID(0);
1585 initStringInfo(&buf);
1587 proctup = SearchSysCache(PROCOID,
1588 ObjectIdGetDatum(funcid),
1590 if (!HeapTupleIsValid(proctup))
1591 elog(ERROR, "cache lookup failed for function %u", funcid);
1593 (void) print_function_arguments(&buf, proctup, false);
1595 ReleaseSysCache(proctup);
1597 PG_RETURN_TEXT_P(string_to_text(buf.data));
1601 * pg_get_function_result
1602 * Get a nicely-formatted version of the result type of a function.
1603 * This is what would appear after RETURNS in CREATE FUNCTION.
1606 pg_get_function_result(PG_FUNCTION_ARGS)
1608 Oid funcid = PG_GETARG_OID(0);
1612 initStringInfo(&buf);
1614 proctup = SearchSysCache(PROCOID,
1615 ObjectIdGetDatum(funcid),
1617 if (!HeapTupleIsValid(proctup))
1618 elog(ERROR, "cache lookup failed for function %u", funcid);
1620 print_function_rettype(&buf, proctup);
1622 ReleaseSysCache(proctup);
1624 PG_RETURN_TEXT_P(string_to_text(buf.data));
1628 * Guts of pg_get_function_result: append the function's return type
1629 * to the specified buffer.
1632 print_function_rettype(StringInfo buf, HeapTuple proctup)
1634 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1636 StringInfoData rbuf;
1638 initStringInfo(&rbuf);
1640 if (proc->proretset)
1642 /* It might be a table function; try to print the arguments */
1643 appendStringInfoString(&rbuf, "TABLE(");
1644 ntabargs = print_function_arguments(&rbuf, proctup, true);
1646 appendStringInfoString(&rbuf, ")");
1648 resetStringInfo(&rbuf);
1653 /* Not a table function, so do the normal thing */
1654 if (proc->proretset)
1655 appendStringInfoString(&rbuf, "SETOF ");
1656 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1659 appendStringInfoString(buf, rbuf.data);
1663 * Common code for pg_get_function_arguments and pg_get_function_result:
1664 * append the desired subset of arguments to buf. We print only TABLE
1665 * arguments when print_table_args is true, and all the others when it's false.
1666 * Function return value is the number of arguments printed.
1669 print_function_arguments(StringInfo buf, HeapTuple proctup,
1670 bool print_table_args)
1679 numargs = get_func_arg_info(proctup,
1680 &argtypes, &argnames, &argmodes);
1683 for (i = 0; i < numargs; i++)
1685 Oid argtype = argtypes[i];
1686 char *argname = argnames ? argnames[i] : NULL;
1687 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1688 const char *modename;
1690 if (print_table_args != (argmode == PROARGMODE_TABLE))
1698 case PROARGMODE_INOUT:
1699 modename = "INOUT ";
1701 case PROARGMODE_OUT:
1704 case PROARGMODE_VARIADIC:
1705 modename = "VARIADIC ";
1707 case PROARGMODE_TABLE:
1711 elog(ERROR, "invalid parameter mode '%c'", argmode);
1712 modename = NULL; /* keep compiler quiet */
1716 appendStringInfoString(buf, ", ");
1717 appendStringInfoString(buf, modename);
1718 if (argname && argname[0])
1719 appendStringInfo(buf, "%s ", argname);
1720 appendStringInfoString(buf, format_type_be(argtype));
1729 * deparse_expression - General utility for deparsing expressions
1731 * calls deparse_expression_pretty with all prettyPrinting disabled
1734 deparse_expression(Node *expr, List *dpcontext,
1735 bool forceprefix, bool showimplicit)
1737 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1738 showimplicit, 0, 0);
1742 * deparse_expression_pretty - General utility for deparsing expressions
1744 * expr is the node tree to be deparsed. It must be a transformed expression
1745 * tree (ie, not the raw output of gram.y).
1747 * dpcontext is a list of deparse_namespace nodes representing the context
1748 * for interpreting Vars in the node tree.
1750 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1752 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1754 * tries to pretty up the output according to prettyFlags and startIndent.
1756 * The result is a palloc'd string.
1760 deparse_expression_pretty(Node *expr, List *dpcontext,
1761 bool forceprefix, bool showimplicit,
1762 int prettyFlags, int startIndent)
1765 deparse_context context;
1767 initStringInfo(&buf);
1769 context.namespaces = dpcontext;
1770 context.varprefix = forceprefix;
1771 context.prettyFlags = prettyFlags;
1772 context.indentLevel = startIndent;
1774 get_rule_expr(expr, &context, showimplicit);
1780 * deparse_context_for - Build deparse context for a single relation
1782 * Given the reference name (alias) and OID of a relation, build deparsing
1783 * context for an expression referencing only that relation (as varno 1,
1784 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1788 deparse_context_for(const char *aliasname, Oid relid)
1790 deparse_namespace *dpns;
1793 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1795 /* Build a minimal RTE for the rel */
1796 rte = makeNode(RangeTblEntry);
1797 rte->rtekind = RTE_RELATION;
1799 rte->eref = makeAlias(aliasname, NIL);
1801 rte->inFromCl = true;
1803 /* Build one-element rtable */
1804 dpns->rtable = list_make1(rte);
1805 dpns->outer_plan = dpns->inner_plan = NULL;
1807 /* Return a one-deep namespace stack */
1808 return list_make1(dpns);
1812 * deparse_context_for_plan - Build deparse context for a plan node
1814 * When deparsing an expression in a Plan tree, we might have to resolve
1815 * OUTER or INNER references. Pass the plan nodes whose targetlists define
1816 * such references, or NULL when none are expected. (outer_plan and
1817 * inner_plan really ought to be declared as "Plan *", but we use "Node *"
1818 * to avoid having to include plannodes.h in builtins.h.)
1820 * As a special case, when deparsing a SubqueryScan plan, pass the subplan
1821 * as inner_plan (there won't be any regular innerPlan() in this case).
1823 * The plan's rangetable list must also be passed. We actually prefer to use
1824 * the rangetable to resolve simple Vars, but the subplan inputs are needed
1825 * for Vars that reference expressions computed in subplan target lists.
1828 deparse_context_for_plan(Node *outer_plan, Node *inner_plan,
1831 deparse_namespace *dpns;
1833 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1835 dpns->rtable = rtable;
1836 dpns->outer_plan = (Plan *) outer_plan;
1837 dpns->inner_plan = (Plan *) inner_plan;
1839 /* Return a one-deep namespace stack */
1840 return list_make1(dpns);
1844 * make_ruledef - reconstruct the CREATE RULE command
1845 * for a given pg_rewrite tuple
1849 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1859 List *actions = NIL;
1865 * Get the attribute values from the rules tuple
1867 fno = SPI_fnumber(rulettc, "rulename");
1868 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1870 rulename = NameStr(*(DatumGetName(dat)));
1872 fno = SPI_fnumber(rulettc, "ev_type");
1873 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1875 ev_type = DatumGetChar(dat);
1877 fno = SPI_fnumber(rulettc, "ev_class");
1878 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1880 ev_class = DatumGetObjectId(dat);
1882 fno = SPI_fnumber(rulettc, "ev_attr");
1883 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1885 ev_attr = DatumGetInt16(dat);
1887 fno = SPI_fnumber(rulettc, "is_instead");
1888 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1890 is_instead = DatumGetBool(dat);
1892 /* these could be nulls */
1893 fno = SPI_fnumber(rulettc, "ev_qual");
1894 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1896 fno = SPI_fnumber(rulettc, "ev_action");
1897 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1898 if (ev_action != NULL)
1899 actions = (List *) stringToNode(ev_action);
1902 * Build the rules definition text
1904 appendStringInfo(buf, "CREATE RULE %s AS",
1905 quote_identifier(rulename));
1907 if (prettyFlags & PRETTYFLAG_INDENT)
1908 appendStringInfoString(buf, "\n ON ");
1910 appendStringInfoString(buf, " ON ");
1912 /* The event the rule is fired for */
1916 appendStringInfo(buf, "SELECT");
1920 appendStringInfo(buf, "UPDATE");
1924 appendStringInfo(buf, "INSERT");
1928 appendStringInfo(buf, "DELETE");
1933 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1934 errmsg("rule \"%s\" has unsupported event type %d",
1935 rulename, ev_type)));
1939 /* The relation the rule is fired on */
1940 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class));
1942 appendStringInfo(buf, ".%s",
1943 quote_identifier(get_relid_attribute_name(ev_class,
1946 /* If the rule has an event qualification, add it */
1947 if (ev_qual == NULL)
1949 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
1953 deparse_context context;
1954 deparse_namespace dpns;
1956 if (prettyFlags & PRETTYFLAG_INDENT)
1957 appendStringInfoString(buf, "\n ");
1958 appendStringInfo(buf, " WHERE ");
1960 qual = stringToNode(ev_qual);
1963 * We need to make a context for recognizing any Vars in the qual
1964 * (which can only be references to OLD and NEW). Use the rtable of
1965 * the first query in the action list for this purpose.
1967 query = (Query *) linitial(actions);
1970 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
1971 * into the SELECT, and that's what we need to look at. (Ugly kluge
1972 * ... try to fix this when we redesign querytrees.)
1974 query = getInsertSelectQuery(query, NULL);
1976 /* Must acquire locks right away; see notes in get_query_def() */
1977 AcquireRewriteLocks(query);
1980 context.namespaces = list_make1(&dpns);
1981 context.varprefix = (list_length(query->rtable) != 1);
1982 context.prettyFlags = prettyFlags;
1983 context.indentLevel = PRETTYINDENT_STD;
1984 dpns.rtable = query->rtable;
1985 dpns.outer_plan = dpns.inner_plan = NULL;
1987 get_rule_expr(qual, &context, false);
1990 appendStringInfo(buf, " DO ");
1992 /* The INSTEAD keyword (if so) */
1994 appendStringInfo(buf, "INSTEAD ");
1996 /* Finally the rules actions */
1997 if (list_length(actions) > 1)
2002 appendStringInfo(buf, "(");
2003 foreach(action, actions)
2005 query = (Query *) lfirst(action);
2006 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2008 appendStringInfo(buf, ";\n");
2010 appendStringInfo(buf, "; ");
2012 appendStringInfo(buf, ");");
2014 else if (list_length(actions) == 0)
2016 appendStringInfo(buf, "NOTHING;");
2022 query = (Query *) linitial(actions);
2023 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2024 appendStringInfo(buf, ";");
2030 * make_viewdef - reconstruct the SELECT part of a
2035 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2045 List *actions = NIL;
2046 Relation ev_relation;
2051 * Get the attribute values from the rules tuple
2053 fno = SPI_fnumber(rulettc, "ev_type");
2054 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2056 fno = SPI_fnumber(rulettc, "ev_class");
2057 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2059 fno = SPI_fnumber(rulettc, "ev_attr");
2060 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2062 fno = SPI_fnumber(rulettc, "is_instead");
2063 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2065 fno = SPI_fnumber(rulettc, "ev_qual");
2066 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2068 fno = SPI_fnumber(rulettc, "ev_action");
2069 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2070 if (ev_action != NULL)
2071 actions = (List *) stringToNode(ev_action);
2073 if (list_length(actions) != 1)
2075 appendStringInfo(buf, "Not a view");
2079 query = (Query *) linitial(actions);
2081 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2082 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2084 appendStringInfo(buf, "Not a view");
2088 ev_relation = heap_open(ev_class, AccessShareLock);
2090 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2092 appendStringInfo(buf, ";");
2094 heap_close(ev_relation, AccessShareLock);
2099 * get_query_def - Parse back one query parsetree
2101 * If resultDesc is not NULL, then it is the output tuple descriptor for
2102 * the view represented by a SELECT query.
2106 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2107 TupleDesc resultDesc, int prettyFlags, int startIndent)
2109 deparse_context context;
2110 deparse_namespace dpns;
2113 * Before we begin to examine the query, acquire locks on referenced
2114 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2115 * consistent results. Note we assume it's OK to scribble on the passed
2118 AcquireRewriteLocks(query);
2121 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2122 context.varprefix = (parentnamespace != NIL ||
2123 list_length(query->rtable) != 1);
2124 context.prettyFlags = prettyFlags;
2125 context.indentLevel = startIndent;
2127 dpns.rtable = query->rtable;
2128 dpns.outer_plan = dpns.inner_plan = NULL;
2130 switch (query->commandType)
2133 get_select_query_def(query, &context, resultDesc);
2137 get_update_query_def(query, &context);
2141 get_insert_query_def(query, &context);
2145 get_delete_query_def(query, &context);
2149 appendStringInfo(buf, "NOTHING");
2153 get_utility_query_def(query, &context);
2157 elog(ERROR, "unrecognized query command type: %d",
2158 query->commandType);
2164 * get_values_def - Parse back a VALUES list
2168 get_values_def(List *values_lists, deparse_context *context)
2170 StringInfo buf = context->buf;
2171 bool first_list = true;
2174 appendStringInfoString(buf, "VALUES ");
2176 foreach(vtl, values_lists)
2178 List *sublist = (List *) lfirst(vtl);
2179 bool first_col = true;
2185 appendStringInfoString(buf, ", ");
2187 appendStringInfoChar(buf, '(');
2188 foreach(lc, sublist)
2190 Node *col = (Node *) lfirst(lc);
2195 appendStringInfoChar(buf, ',');
2198 * Strip any top-level nodes representing indirection assignments,
2199 * then print the result.
2201 get_rule_expr(processIndirection(col, context, false),
2204 appendStringInfoChar(buf, ')');
2209 * get_with_clause - Parse back a WITH clause
2213 get_with_clause(Query *query, deparse_context *context)
2215 StringInfo buf = context->buf;
2219 if (query->cteList == NIL)
2222 if (PRETTY_INDENT(context))
2224 context->indentLevel += PRETTYINDENT_STD;
2225 appendStringInfoChar(buf, ' ');
2228 if (query->hasRecursive)
2229 sep = "WITH RECURSIVE ";
2232 foreach(l, query->cteList)
2234 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2236 appendStringInfoString(buf, sep);
2237 appendStringInfoString(buf, quote_identifier(cte->ctename));
2238 if (cte->aliascolnames)
2243 appendStringInfoChar(buf, '(');
2244 foreach(col, cte->aliascolnames)
2249 appendStringInfoString(buf, ", ");
2250 appendStringInfoString(buf,
2251 quote_identifier(strVal(lfirst(col))));
2253 appendStringInfoChar(buf, ')');
2255 appendStringInfoString(buf, " AS (");
2256 if (PRETTY_INDENT(context))
2257 appendContextKeyword(context, "", 0, 0, 0);
2258 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2259 context->prettyFlags, context->indentLevel);
2260 if (PRETTY_INDENT(context))
2261 appendContextKeyword(context, "", 0, 0, 0);
2262 appendStringInfoChar(buf, ')');
2266 if (PRETTY_INDENT(context))
2268 context->indentLevel -= PRETTYINDENT_STD;
2269 appendContextKeyword(context, "", 0, 0, 0);
2272 appendStringInfoChar(buf, ' ');
2276 * get_select_query_def - Parse back a SELECT parsetree
2280 get_select_query_def(Query *query, deparse_context *context,
2281 TupleDesc resultDesc)
2283 StringInfo buf = context->buf;
2288 /* Insert the WITH clause if given */
2289 get_with_clause(query, context);
2292 * If the Query node has a setOperations tree, then it's the top level of
2293 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2294 * fields are interesting in the top query itself.
2296 if (query->setOperations)
2298 get_setop_query(query->setOperations, query, context, resultDesc);
2299 /* ORDER BY clauses must be simple in this case */
2304 get_basic_select_query(query, context, resultDesc);
2305 force_colno = false;
2308 /* Add the ORDER BY clause if given */
2309 if (query->sortClause != NIL)
2311 appendContextKeyword(context, " ORDER BY ",
2312 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2314 foreach(l, query->sortClause)
2316 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2319 TypeCacheEntry *typentry;
2321 appendStringInfoString(buf, sep);
2322 sortexpr = get_rule_sortgroupclause(srt, query->targetList,
2323 force_colno, context);
2324 sortcoltype = exprType(sortexpr);
2325 /* See whether operator is default < or > for datatype */
2326 typentry = lookup_type_cache(sortcoltype,
2327 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
2328 if (srt->sortop == typentry->lt_opr)
2330 /* ASC is default, so emit nothing for it */
2331 if (srt->nulls_first)
2332 appendStringInfo(buf, " NULLS FIRST");
2334 else if (srt->sortop == typentry->gt_opr)
2336 appendStringInfo(buf, " DESC");
2337 /* DESC defaults to NULLS FIRST */
2338 if (!srt->nulls_first)
2339 appendStringInfo(buf, " NULLS LAST");
2343 appendStringInfo(buf, " USING %s",
2344 generate_operator_name(srt->sortop,
2347 /* be specific to eliminate ambiguity */
2348 if (srt->nulls_first)
2349 appendStringInfo(buf, " NULLS FIRST");
2351 appendStringInfo(buf, " NULLS LAST");
2357 /* Add the LIMIT clause if given */
2358 if (query->limitOffset != NULL)
2360 appendContextKeyword(context, " OFFSET ",
2361 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2362 get_rule_expr(query->limitOffset, context, false);
2364 if (query->limitCount != NULL)
2366 appendContextKeyword(context, " LIMIT ",
2367 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2368 if (IsA(query->limitCount, Const) &&
2369 ((Const *) query->limitCount)->constisnull)
2370 appendStringInfo(buf, "ALL");
2372 get_rule_expr(query->limitCount, context, false);
2375 /* Add FOR UPDATE/SHARE clauses if present */
2376 foreach(l, query->rowMarks)
2378 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2379 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2382 appendContextKeyword(context, " FOR UPDATE",
2383 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2385 appendContextKeyword(context, " FOR SHARE",
2386 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2387 appendStringInfo(buf, " OF %s",
2388 quote_identifier(rte->eref->aliasname));
2390 appendStringInfo(buf, " NOWAIT");
2395 get_basic_select_query(Query *query, deparse_context *context,
2396 TupleDesc resultDesc)
2398 StringInfo buf = context->buf;
2402 if (PRETTY_INDENT(context))
2404 context->indentLevel += PRETTYINDENT_STD;
2405 appendStringInfoChar(buf, ' ');
2409 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2410 * VALUES part. This reverses what transformValuesClause() did at parse
2411 * time. If the jointree contains just a single VALUES RTE, we assume
2412 * this case applies (without looking at the targetlist...)
2414 if (list_length(query->jointree->fromlist) == 1)
2416 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2418 if (IsA(rtr, RangeTblRef))
2420 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2422 if (rte->rtekind == RTE_VALUES)
2424 get_values_def(rte->values_lists, context);
2431 * Build up the query string - first we say SELECT
2433 appendStringInfo(buf, "SELECT");
2435 /* Add the DISTINCT clause if given */
2436 if (query->distinctClause != NIL)
2438 if (query->hasDistinctOn)
2440 appendStringInfo(buf, " DISTINCT ON (");
2442 foreach(l, query->distinctClause)
2444 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2446 appendStringInfoString(buf, sep);
2447 get_rule_sortgroupclause(srt, query->targetList,
2451 appendStringInfo(buf, ")");
2454 appendStringInfo(buf, " DISTINCT");
2457 /* Then we tell what to select (the targetlist) */
2458 get_target_list(query->targetList, context, resultDesc);
2460 /* Add the FROM clause if needed */
2461 get_from_clause(query, " FROM ", context);
2463 /* Add the WHERE clause if given */
2464 if (query->jointree->quals != NULL)
2466 appendContextKeyword(context, " WHERE ",
2467 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2468 get_rule_expr(query->jointree->quals, context, false);
2471 /* Add the GROUP BY clause if given */
2472 if (query->groupClause != NULL)
2474 appendContextKeyword(context, " GROUP BY ",
2475 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2477 foreach(l, query->groupClause)
2479 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2481 appendStringInfoString(buf, sep);
2482 get_rule_sortgroupclause(grp, query->targetList,
2488 /* Add the HAVING clause if given */
2489 if (query->havingQual != NULL)
2491 appendContextKeyword(context, " HAVING ",
2492 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2493 get_rule_expr(query->havingQual, context, false);
2498 * get_target_list - Parse back a SELECT target list
2500 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2504 get_target_list(List *targetList, deparse_context *context,
2505 TupleDesc resultDesc)
2507 StringInfo buf = context->buf;
2514 foreach(l, targetList)
2516 TargetEntry *tle = (TargetEntry *) lfirst(l);
2521 continue; /* ignore junk entries */
2523 appendStringInfoString(buf, sep);
2528 * We special-case Var nodes rather than using get_rule_expr. This is
2529 * needed because get_rule_expr will display a whole-row Var as
2530 * "foo.*", which is the preferred notation in most contexts, but at
2531 * the top level of a SELECT list it's not right (the parser will
2532 * expand that notation into multiple columns, yielding behavior
2533 * different from a whole-row Var). We want just "foo", instead.
2535 if (tle->expr && IsA(tle->expr, Var))
2537 attname = get_variable((Var *) tle->expr, 0, false, context);
2541 get_rule_expr((Node *) tle->expr, context, true);
2542 /* We'll show the AS name unless it's this: */
2543 attname = "?column?";
2547 * Figure out what the result column should be called. In the context
2548 * of a view, use the view's tuple descriptor (so as to pick up the
2549 * effects of any column RENAME that's been done on the view).
2550 * Otherwise, just use what we can find in the TLE.
2552 if (resultDesc && colno <= resultDesc->natts)
2553 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2555 colname = tle->resname;
2557 /* Show AS unless the column's name is correct as-is */
2558 if (colname) /* resname could be NULL */
2560 if (attname == NULL || strcmp(attname, colname) != 0)
2561 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2567 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2568 TupleDesc resultDesc)
2570 StringInfo buf = context->buf;
2573 if (IsA(setOp, RangeTblRef))
2575 RangeTblRef *rtr = (RangeTblRef *) setOp;
2576 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2577 Query *subquery = rte->subquery;
2579 Assert(subquery != NULL);
2580 Assert(subquery->setOperations == NULL);
2581 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2582 need_paren = (subquery->cteList ||
2583 subquery->sortClause ||
2584 subquery->rowMarks ||
2585 subquery->limitOffset ||
2586 subquery->limitCount);
2588 appendStringInfoChar(buf, '(');
2589 get_query_def(subquery, buf, context->namespaces, resultDesc,
2590 context->prettyFlags, context->indentLevel);
2592 appendStringInfoChar(buf, ')');
2594 else if (IsA(setOp, SetOperationStmt))
2596 SetOperationStmt *op = (SetOperationStmt *) setOp;
2598 if (PRETTY_INDENT(context))
2600 context->indentLevel += PRETTYINDENT_STD;
2601 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
2605 * We force parens whenever nesting two SetOperationStmts. There are
2606 * some cases in which parens are needed around a leaf query too, but
2607 * those are more easily handled at the next level down (see code
2610 need_paren = !IsA(op->larg, RangeTblRef);
2613 appendStringInfoChar(buf, '(');
2614 get_setop_query(op->larg, query, context, resultDesc);
2616 appendStringInfoChar(buf, ')');
2618 if (!PRETTY_INDENT(context))
2619 appendStringInfoChar(buf, ' ');
2623 appendContextKeyword(context, "UNION ",
2624 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2626 case SETOP_INTERSECT:
2627 appendContextKeyword(context, "INTERSECT ",
2628 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2631 appendContextKeyword(context, "EXCEPT ",
2632 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2635 elog(ERROR, "unrecognized set op: %d",
2639 appendStringInfo(buf, "ALL ");
2641 if (PRETTY_INDENT(context))
2642 appendContextKeyword(context, "", 0, 0, 0);
2644 need_paren = !IsA(op->rarg, RangeTblRef);
2647 appendStringInfoChar(buf, '(');
2648 get_setop_query(op->rarg, query, context, resultDesc);
2650 appendStringInfoChar(buf, ')');
2652 if (PRETTY_INDENT(context))
2653 context->indentLevel -= PRETTYINDENT_STD;
2657 elog(ERROR, "unrecognized node type: %d",
2658 (int) nodeTag(setOp));
2663 * Display a sort/group clause.
2665 * Also returns the expression tree, so caller need not find it again.
2668 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2669 deparse_context *context)
2671 StringInfo buf = context->buf;
2675 tle = get_sortgroupclause_tle(srt, tlist);
2676 expr = (Node *) tle->expr;
2679 * Use column-number form if requested by caller. Otherwise, if
2680 * expression is a constant, force it to be dumped with an explicit
2681 * cast as decoration --- this is because a simple integer constant
2682 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2683 * if we dump it without any decoration. Otherwise, just dump the
2684 * expression normally.
2688 Assert(!tle->resjunk);
2689 appendStringInfo(buf, "%d", tle->resno);
2691 else if (expr && IsA(expr, Const))
2692 get_const_expr((Const *) expr, context, 1);
2694 get_rule_expr(expr, context, true);
2700 * get_insert_query_def - Parse back an INSERT parsetree
2704 get_insert_query_def(Query *query, deparse_context *context)
2706 StringInfo buf = context->buf;
2707 RangeTblEntry *select_rte = NULL;
2708 RangeTblEntry *values_rte = NULL;
2711 ListCell *values_cell;
2713 List *strippedexprs;
2716 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
2717 * a single RTE for the SELECT or VALUES.
2719 foreach(l, query->rtable)
2721 rte = (RangeTblEntry *) lfirst(l);
2723 if (rte->rtekind == RTE_SUBQUERY)
2726 elog(ERROR, "too many subquery RTEs in INSERT");
2730 if (rte->rtekind == RTE_VALUES)
2733 elog(ERROR, "too many values RTEs in INSERT");
2737 if (select_rte && values_rte)
2738 elog(ERROR, "both subquery and values RTEs in INSERT");
2741 * Start the query with INSERT INTO relname
2743 rte = rt_fetch(query->resultRelation, query->rtable);
2744 Assert(rte->rtekind == RTE_RELATION);
2746 if (PRETTY_INDENT(context))
2748 context->indentLevel += PRETTYINDENT_STD;
2749 appendStringInfoChar(buf, ' ');
2751 appendStringInfo(buf, "INSERT INTO %s (",
2752 generate_relation_name(rte->relid));
2755 * Add the insert-column-names list. To handle indirection properly, we
2756 * need to look for indirection nodes in the top targetlist (if it's
2757 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
2758 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
2759 * assume that all the expression lists will have similar indirection in
2763 values_cell = list_head((List *) linitial(values_rte->values_lists));
2766 strippedexprs = NIL;
2768 foreach(l, query->targetList)
2770 TargetEntry *tle = (TargetEntry *) lfirst(l);
2773 continue; /* ignore junk entries */
2775 appendStringInfoString(buf, sep);
2779 * Put out name of target column; look in the catalogs, not at
2780 * tle->resname, since resname will fail to track RENAME.
2782 appendStringInfoString(buf,
2783 quote_identifier(get_relid_attribute_name(rte->relid,
2787 * Print any indirection needed (subfields or subscripts), and strip
2788 * off the top-level nodes representing the indirection assignments.
2792 /* we discard the stripped expression in this case */
2793 processIndirection((Node *) lfirst(values_cell), context, true);
2794 values_cell = lnext(values_cell);
2798 /* we keep a list of the stripped expressions in this case */
2799 strippedexprs = lappend(strippedexprs,
2800 processIndirection((Node *) tle->expr,
2804 appendStringInfo(buf, ") ");
2808 /* Add the SELECT */
2809 get_query_def(select_rte->subquery, buf, NIL, NULL,
2810 context->prettyFlags, context->indentLevel);
2812 else if (values_rte)
2814 /* A WITH clause is possible here */
2815 get_with_clause(query, context);
2816 /* Add the multi-VALUES expression lists */
2817 get_values_def(values_rte->values_lists, context);
2821 /* A WITH clause is possible here */
2822 get_with_clause(query, context);
2823 /* Add the single-VALUES expression list */
2824 appendContextKeyword(context, "VALUES (",
2825 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
2826 get_rule_expr((Node *) strippedexprs, context, false);
2827 appendStringInfoChar(buf, ')');
2830 /* Add RETURNING if present */
2831 if (query->returningList)
2833 appendContextKeyword(context, " RETURNING",
2834 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2835 get_target_list(query->returningList, context, NULL);
2841 * get_update_query_def - Parse back an UPDATE parsetree
2845 get_update_query_def(Query *query, deparse_context *context)
2847 StringInfo buf = context->buf;
2853 * Start the query with UPDATE relname SET
2855 rte = rt_fetch(query->resultRelation, query->rtable);
2856 Assert(rte->rtekind == RTE_RELATION);
2857 if (PRETTY_INDENT(context))
2859 appendStringInfoChar(buf, ' ');
2860 context->indentLevel += PRETTYINDENT_STD;
2862 appendStringInfo(buf, "UPDATE %s%s",
2864 generate_relation_name(rte->relid));
2865 if (rte->alias != NULL)
2866 appendStringInfo(buf, " %s",
2867 quote_identifier(rte->alias->aliasname));
2868 appendStringInfoString(buf, " SET ");
2870 /* Add the comma separated list of 'attname = value' */
2872 foreach(l, query->targetList)
2874 TargetEntry *tle = (TargetEntry *) lfirst(l);
2878 continue; /* ignore junk entries */
2880 appendStringInfoString(buf, sep);
2884 * Put out name of target column; look in the catalogs, not at
2885 * tle->resname, since resname will fail to track RENAME.
2887 appendStringInfoString(buf,
2888 quote_identifier(get_relid_attribute_name(rte->relid,
2892 * Print any indirection needed (subfields or subscripts), and strip
2893 * off the top-level nodes representing the indirection assignments.
2895 expr = processIndirection((Node *) tle->expr, context, true);
2897 appendStringInfo(buf, " = ");
2899 get_rule_expr(expr, context, false);
2902 /* Add the FROM clause if needed */
2903 get_from_clause(query, " FROM ", context);
2905 /* Add a WHERE clause if given */
2906 if (query->jointree->quals != NULL)
2908 appendContextKeyword(context, " WHERE ",
2909 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2910 get_rule_expr(query->jointree->quals, context, false);
2913 /* Add RETURNING if present */
2914 if (query->returningList)
2916 appendContextKeyword(context, " RETURNING",
2917 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2918 get_target_list(query->returningList, context, NULL);
2924 * get_delete_query_def - Parse back a DELETE parsetree
2928 get_delete_query_def(Query *query, deparse_context *context)
2930 StringInfo buf = context->buf;
2934 * Start the query with DELETE FROM relname
2936 rte = rt_fetch(query->resultRelation, query->rtable);
2937 Assert(rte->rtekind == RTE_RELATION);
2938 if (PRETTY_INDENT(context))
2940 appendStringInfoChar(buf, ' ');
2941 context->indentLevel += PRETTYINDENT_STD;
2943 appendStringInfo(buf, "DELETE FROM %s%s",
2945 generate_relation_name(rte->relid));
2946 if (rte->alias != NULL)
2947 appendStringInfo(buf, " %s",
2948 quote_identifier(rte->alias->aliasname));
2950 /* Add the USING clause if given */
2951 get_from_clause(query, " USING ", context);
2953 /* Add a WHERE clause if given */
2954 if (query->jointree->quals != NULL)
2956 appendContextKeyword(context, " WHERE ",
2957 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2958 get_rule_expr(query->jointree->quals, context, false);
2961 /* Add RETURNING if present */
2962 if (query->returningList)
2964 appendContextKeyword(context, " RETURNING",
2965 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2966 get_target_list(query->returningList, context, NULL);
2972 * get_utility_query_def - Parse back a UTILITY parsetree
2976 get_utility_query_def(Query *query, deparse_context *context)
2978 StringInfo buf = context->buf;
2980 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
2982 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
2984 appendContextKeyword(context, "",
2985 0, PRETTYINDENT_STD, 1);
2986 appendStringInfo(buf, "NOTIFY %s",
2987 quote_identifier(stmt->conditionname));
2991 /* Currently only NOTIFY utility commands can appear in rules */
2992 elog(ERROR, "unexpected utility statement type");
2998 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3000 * When expanding an OUTER or INNER reference, we must push new outer/inner
3001 * subplans in case the referenced expression itself uses OUTER/INNER. We
3002 * modify the top stack entry in-place to avoid affecting levelsup issues
3003 * (although in a Plan tree there really shouldn't be any).
3005 * Caller must save and restore outer_plan and inner_plan around this.
3008 push_plan(deparse_namespace *dpns, Plan *subplan)
3011 * We special-case Append to pretend that the first child plan is the
3012 * OUTER referent; otherwise normal.
3014 if (IsA(subplan, Append))
3015 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
3017 dpns->outer_plan = outerPlan(subplan);
3020 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3021 * use OUTER because that could someday conflict with the normal meaning.)
3023 if (IsA(subplan, SubqueryScan))
3024 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
3026 dpns->inner_plan = innerPlan(subplan);
3031 * Display a Var appropriately.
3033 * In some cases (currently only when recursing into an unnamed join)
3034 * the Var's varlevelsup has to be interpreted with respect to a context
3035 * above the current one; levelsup indicates the offset.
3037 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3038 * if FALSE, merely as "foo".
3040 * Returns the attname of the Var, or NULL if not determinable.
3043 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3045 StringInfo buf = context->buf;
3049 deparse_namespace *dpns;
3054 /* Find appropriate nesting depth */
3055 netlevelsup = var->varlevelsup + levelsup;
3056 if (netlevelsup >= list_length(context->namespaces))
3057 elog(ERROR, "bogus varlevelsup: %d offset %d",
3058 var->varlevelsup, levelsup);
3059 dpns = (deparse_namespace *) list_nth(context->namespaces,
3063 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3064 * likely that varno is OUTER or INNER, in which case we must dig down
3065 * into the subplans.
3067 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3069 rte = rt_fetch(var->varno, dpns->rtable);
3070 attnum = var->varattno;
3072 else if (var->varno == OUTER && dpns->outer_plan)
3078 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3080 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3082 Assert(netlevelsup == 0);
3083 save_outer = dpns->outer_plan;
3084 save_inner = dpns->inner_plan;
3085 push_plan(dpns, dpns->outer_plan);
3088 * Force parentheses because our caller probably assumed a Var is a
3089 * simple expression.
3091 if (!IsA(tle->expr, Var))
3092 appendStringInfoChar(buf, '(');
3093 get_rule_expr((Node *) tle->expr, context, true);
3094 if (!IsA(tle->expr, Var))
3095 appendStringInfoChar(buf, ')');
3097 dpns->outer_plan = save_outer;
3098 dpns->inner_plan = save_inner;
3101 else if (var->varno == INNER && dpns->inner_plan)
3107 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3109 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3111 Assert(netlevelsup == 0);
3112 save_outer = dpns->outer_plan;
3113 save_inner = dpns->inner_plan;
3114 push_plan(dpns, dpns->inner_plan);
3117 * Force parentheses because our caller probably assumed a Var is a
3118 * simple expression.
3120 if (!IsA(tle->expr, Var))
3121 appendStringInfoChar(buf, '(');
3122 get_rule_expr((Node *) tle->expr, context, true);
3123 if (!IsA(tle->expr, Var))
3124 appendStringInfoChar(buf, ')');
3126 dpns->outer_plan = save_outer;
3127 dpns->inner_plan = save_inner;
3132 elog(ERROR, "bogus varno: %d", var->varno);
3133 return NULL; /* keep compiler quiet */
3136 /* Identify names to use */
3137 schemaname = NULL; /* default assumptions */
3138 refname = rte->eref->aliasname;
3140 /* Exceptions occur only if the RTE is alias-less */
3141 if (rte->alias == NULL)
3143 if (rte->rtekind == RTE_RELATION)
3146 * It's possible that use of the bare refname would find another
3147 * more-closely-nested RTE, or be ambiguous, in which case we need
3148 * to specify the schemaname to avoid these errors.
3150 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3151 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3153 else if (rte->rtekind == RTE_JOIN)
3156 * If it's an unnamed join, look at the expansion of the alias
3157 * variable. If it's a simple reference to one of the input vars
3158 * then recursively print the name of that var, instead. (This
3159 * allows correct decompiling of cases where there are identically
3160 * named columns on both sides of the join.) When it's not a
3161 * simple reference, we have to just print the unqualified
3162 * variable name (this can only happen with columns that were
3163 * merged by USING or NATURAL clauses).
3165 * This wouldn't work in decompiling plan trees, because we don't
3166 * store joinaliasvars lists after planning; but a plan tree
3167 * should never contain a join alias variable.
3169 if (rte->joinaliasvars == NIL)
3170 elog(ERROR, "cannot decompile join alias var in plan tree");
3175 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3176 if (IsA(aliasvar, Var))
3178 return get_variable(aliasvar, var->varlevelsup + levelsup,
3182 /* Unnamed join has neither schemaname nor refname */
3187 if (attnum == InvalidAttrNumber)
3190 attname = get_rte_attribute_name(rte, attnum);
3192 if (refname && (context->varprefix || attname == NULL))
3195 appendStringInfo(buf, "%s.",
3196 quote_identifier(schemaname));
3198 if (strcmp(refname, "*NEW*") == 0)
3199 appendStringInfoString(buf, "new");
3200 else if (strcmp(refname, "*OLD*") == 0)
3201 appendStringInfoString(buf, "old");
3203 appendStringInfoString(buf, quote_identifier(refname));
3205 if (attname || showstar)
3206 appendStringInfoChar(buf, '.');
3209 appendStringInfoString(buf, quote_identifier(attname));
3211 appendStringInfoChar(buf, '*');
3218 * Get the name of a field of an expression of composite type.
3220 * This is fairly straightforward except for the case of a Var of type RECORD.
3221 * Since no actual table or view column is allowed to have type RECORD, such
3222 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3223 * drill down to find the ultimate defining expression and attempt to infer
3224 * the field name from it. We ereport if we can't determine the name.
3226 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3229 get_name_for_var_field(Var *var, int fieldno,
3230 int levelsup, deparse_context *context)
3235 deparse_namespace *dpns;
3236 TupleDesc tupleDesc;
3240 * If it's a Var of type RECORD, we have to find what the Var refers to;
3241 * if not, we can use get_expr_result_type. If that fails, we try
3242 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3243 * an acceptable message.
3245 if (!IsA(var, Var) ||
3246 var->vartype != RECORDOID)
3248 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3249 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3250 exprTypmod((Node *) var));
3252 /* Got the tupdesc, so we can extract the field name */
3253 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3254 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3257 /* Find appropriate nesting depth */
3258 netlevelsup = var->varlevelsup + levelsup;
3259 if (netlevelsup >= list_length(context->namespaces))
3260 elog(ERROR, "bogus varlevelsup: %d offset %d",
3261 var->varlevelsup, levelsup);
3262 dpns = (deparse_namespace *) list_nth(context->namespaces,
3266 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3267 * likely that varno is OUTER or INNER, in which case we must dig down
3268 * into the subplans.
3270 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3272 rte = rt_fetch(var->varno, dpns->rtable);
3273 attnum = var->varattno;
3275 else if (var->varno == OUTER && dpns->outer_plan)
3282 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3284 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3286 Assert(netlevelsup == 0);
3287 save_outer = dpns->outer_plan;
3288 save_inner = dpns->inner_plan;
3289 push_plan(dpns, dpns->outer_plan);
3291 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3294 dpns->outer_plan = save_outer;
3295 dpns->inner_plan = save_inner;
3298 else if (var->varno == INNER && dpns->inner_plan)
3305 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3307 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3309 Assert(netlevelsup == 0);
3310 save_outer = dpns->outer_plan;
3311 save_inner = dpns->inner_plan;
3312 push_plan(dpns, dpns->inner_plan);
3314 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3317 dpns->outer_plan = save_outer;
3318 dpns->inner_plan = save_inner;
3323 elog(ERROR, "bogus varno: %d", var->varno);
3324 return NULL; /* keep compiler quiet */
3327 if (attnum == InvalidAttrNumber)
3329 /* Var is whole-row reference to RTE, so select the right field */
3330 return get_rte_attribute_name(rte, fieldno);
3334 * This part has essentially the same logic as the parser's
3335 * expandRecordVariable() function, but we are dealing with a different
3336 * representation of the input context, and we only need one field name
3337 * not a TupleDesc. Also, we need a special case for deparsing Plan
3338 * trees, because the subquery field has been removed from SUBQUERY RTEs.
3340 expr = (Node *) var; /* default if we can't drill down */
3342 switch (rte->rtekind)
3349 * This case should not occur: a column of a table or values list
3350 * shouldn't have type RECORD. Fall through and fail (most
3351 * likely) at the bottom.
3358 /* Subselect-in-FROM: examine sub-select's output expr */
3359 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3362 if (ste == NULL || ste->resjunk)
3363 elog(ERROR, "subquery %s does not have attribute %d",
3364 rte->eref->aliasname, attnum);
3365 expr = (Node *) ste->expr;
3369 * Recurse into the sub-select to see what its Var
3370 * refers to. We have to build an additional level of
3371 * namespace to keep in step with varlevelsup in the
3374 deparse_namespace mydpns;
3377 mydpns.rtable = rte->subquery->rtable;
3378 mydpns.outer_plan = mydpns.inner_plan = NULL;
3380 context->namespaces = lcons(&mydpns,
3381 context->namespaces);
3383 result = get_name_for_var_field((Var *) expr, fieldno,
3386 context->namespaces =
3387 list_delete_first(context->namespaces);
3391 /* else fall through to inspect the expression */
3396 * We're deparsing a Plan tree so we don't have complete
3397 * RTE entries. But the only place we'd see a Var
3398 * directly referencing a SUBQUERY RTE is in a
3399 * SubqueryScan plan node, and we can look into the child
3400 * plan's tlist instead.
3407 if (!dpns->inner_plan)
3408 elog(ERROR, "failed to find plan for subquery %s",
3409 rte->eref->aliasname);
3410 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3413 elog(ERROR, "bogus varattno for subquery var: %d",
3415 Assert(netlevelsup == 0);
3416 save_outer = dpns->outer_plan;
3417 save_inner = dpns->inner_plan;
3418 push_plan(dpns, dpns->inner_plan);
3420 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3423 dpns->outer_plan = save_outer;
3424 dpns->inner_plan = save_inner;
3430 /* Join RTE --- recursively inspect the alias variable */
3431 if (rte->joinaliasvars == NIL)
3432 elog(ERROR, "cannot decompile join alias var in plan tree");
3433 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3434 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3436 return get_name_for_var_field((Var *) expr, fieldno,
3437 var->varlevelsup + levelsup,
3439 /* else fall through to inspect the expression */
3444 * We couldn't get here unless a function is declared with one of
3445 * its result columns as RECORD, which is not allowed.
3450 * XXX not implemented yet, we need more infrastructure in
3451 * deparse_namespace and explain.c.
3453 elog(ERROR, "deparsing field references to whole-row vars from WITH queries not implemented yet");
3458 * We now have an expression we can't expand any more, so see if
3459 * get_expr_result_type() can do anything with it. If not, pass to
3460 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3461 * appropriate error message while failing.
3463 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3464 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
3467 /* Got the tupdesc, so we can extract the field name */
3468 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3469 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3474 * find_rte_by_refname - look up an RTE by refname in a deparse context
3476 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3478 * NOTE: this code is not really correct since it does not take account of
3479 * the fact that not all the RTEs in a rangetable may be visible from the
3480 * point where a Var reference appears. For the purposes we need, however,
3481 * the only consequence of a false match is that we might stick a schema
3482 * qualifier on a Var that doesn't really need it. So it seems close
3485 static RangeTblEntry *
3486 find_rte_by_refname(const char *refname, deparse_context *context)
3488 RangeTblEntry *result = NULL;
3491 foreach(nslist, context->namespaces)
3493 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
3496 foreach(rtlist, dpns->rtable)
3498 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
3500 if (strcmp(rte->eref->aliasname, refname) == 0)
3503 return NULL; /* it's ambiguous */
3515 * get_simple_binary_op_name
3517 * helper function for isSimpleNode
3518 * will return single char binary operator name, or NULL if it's not
3521 get_simple_binary_op_name(OpExpr *expr)
3523 List *args = expr->args;
3525 if (list_length(args) == 2)
3527 /* binary operator */
3528 Node *arg1 = (Node *) linitial(args);
3529 Node *arg2 = (Node *) lsecond(args);
3532 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
3533 if (strlen(op) == 1)
3541 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3543 * true : simple in the context of parent node's type
3544 * false : not simple
3547 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
3552 switch (nodeTag(node))
3557 case T_CoerceToDomainValue:
3558 case T_SetToDefault:
3559 case T_CurrentOfExpr:
3560 /* single words: always simple */
3566 case T_CoalesceExpr:
3572 /* function-like: name(..) or name[..] */
3575 /* CASE keywords act as parentheses */
3582 * appears simple since . has top precedence, unless parent is
3583 * T_FieldSelect itself!
3585 return (IsA(parentNode, FieldSelect) ? false : true);
3590 * treat like FieldSelect (probably doesn't matter)
3592 return (IsA(parentNode, FieldStore) ? false : true);
3594 case T_CoerceToDomain:
3595 /* maybe simple, check args */
3596 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
3599 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
3602 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
3604 case T_ArrayCoerceExpr:
3605 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
3607 case T_ConvertRowtypeExpr:
3608 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
3613 /* depends on parent node type; needs further checking */
3614 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
3617 const char *parentOp;
3620 bool is_lopriparent;
3621 bool is_hipriparent;
3623 op = get_simple_binary_op_name((OpExpr *) node);
3627 /* We know only the basic operators + - and * / % */
3628 is_lopriop = (strchr("+-", *op) != NULL);
3629 is_hipriop = (strchr("*/%", *op) != NULL);
3630 if (!(is_lopriop || is_hipriop))
3633 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
3637 is_lopriparent = (strchr("+-", *parentOp) != NULL);
3638 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
3639 if (!(is_lopriparent || is_hipriparent))
3642 if (is_hipriop && is_lopriparent)
3643 return true; /* op binds tighter than parent */
3645 if (is_lopriop && is_hipriparent)
3649 * Operators are same priority --- can skip parens only if
3650 * we have (a - b) - c, not a - (b - c).
3652 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
3657 /* else do the same stuff as for T_SubLink et al. */
3664 case T_DistinctExpr:
3665 switch (nodeTag(parentNode))
3669 /* special handling for casts */
3670 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3672 if (type == COERCE_EXPLICIT_CAST ||
3673 type == COERCE_IMPLICIT_CAST)
3675 return true; /* own parentheses */
3677 case T_BoolExpr: /* lower precedence */
3678 case T_ArrayRef: /* other separators */
3679 case T_ArrayExpr: /* other separators */
3680 case T_RowExpr: /* other separators */
3681 case T_CoalesceExpr: /* own parentheses */
3682 case T_MinMaxExpr: /* own parentheses */
3683 case T_XmlExpr: /* own parentheses */
3684 case T_NullIfExpr: /* other separators */
3685 case T_Aggref: /* own parentheses */
3686 case T_CaseExpr: /* other separators */
3693 switch (nodeTag(parentNode))
3696 if (prettyFlags & PRETTYFLAG_PAREN)
3699 BoolExprType parentType;
3701 type = ((BoolExpr *) node)->boolop;
3702 parentType = ((BoolExpr *) parentNode)->boolop;
3707 if (parentType == AND_EXPR || parentType == OR_EXPR)
3711 if (parentType == OR_EXPR)
3719 /* special handling for casts */
3720 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3722 if (type == COERCE_EXPLICIT_CAST ||
3723 type == COERCE_IMPLICIT_CAST)
3725 return true; /* own parentheses */
3727 case T_ArrayRef: /* other separators */
3728 case T_ArrayExpr: /* other separators */
3729 case T_RowExpr: /* other separators */
3730 case T_CoalesceExpr: /* own parentheses */
3731 case T_MinMaxExpr: /* own parentheses */
3732 case T_XmlExpr: /* own parentheses */
3733 case T_NullIfExpr: /* other separators */
3734 case T_Aggref: /* own parentheses */
3735 case T_CaseExpr: /* other separators */
3744 /* those we don't know: in dubio complexo */
3750 * appendStringInfoSpaces - append spaces to buffer
3753 appendStringInfoSpaces(StringInfo buf, int count)
3756 appendStringInfoChar(buf, ' ');
3760 * appendContextKeyword - append a keyword to buffer
3762 * If prettyPrint is enabled, perform a line break, and adjust indentation.
3763 * Otherwise, just append the keyword.
3766 appendContextKeyword(deparse_context *context, const char *str,
3767 int indentBefore, int indentAfter, int indentPlus)
3769 if (PRETTY_INDENT(context))
3771 context->indentLevel += indentBefore;
3773 appendStringInfoChar(context->buf, '\n');
3774 appendStringInfoSpaces(context->buf,
3775 Max(context->indentLevel, 0) + indentPlus);
3776 appendStringInfoString(context->buf, str);
3778 context->indentLevel += indentAfter;
3779 if (context->indentLevel < 0)
3780 context->indentLevel = 0;
3783 appendStringInfoString(context->buf, str);
3787 * get_rule_expr_paren - deparse expr using get_rule_expr,
3788 * embracing the string with parentheses if necessary for prettyPrint.
3790 * Never embrace if prettyFlags=0, because it's done in the calling node.
3792 * Any node that does *not* embrace its argument node by sql syntax (with
3793 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
3794 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
3798 get_rule_expr_paren(Node *node, deparse_context *context,
3799 bool showimplicit, Node *parentNode)
3803 need_paren = PRETTY_PAREN(context) &&
3804 !isSimpleNode(node, parentNode, context->prettyFlags);
3807 appendStringInfoChar(context->buf, '(');
3809 get_rule_expr(node, context, showimplicit);
3812 appendStringInfoChar(context->buf, ')');
3817 * get_rule_expr - Parse back an expression
3819 * Note: showimplicit determines whether we display any implicit cast that
3820 * is present at the top of the expression tree. It is a passed argument,
3821 * not a field of the context struct, because we change the value as we
3822 * recurse down into the expression. In general we suppress implicit casts
3823 * when the result type is known with certainty (eg, the arguments of an
3824 * OR must be boolean). We display implicit casts for arguments of functions
3825 * and operators, since this is needed to be certain that the same function
3826 * or operator will be chosen when the expression is re-parsed.
3830 get_rule_expr(Node *node, deparse_context *context,
3833 StringInfo buf = context->buf;
3839 * Each level of get_rule_expr must emit an indivisible term
3840 * (parenthesized if necessary) to ensure result is reparsed into the same
3841 * expression tree. The only exception is that when the input is a List,
3842 * we emit the component items comma-separated with no surrounding
3843 * decoration; this is convenient for most callers.
3845 switch (nodeTag(node))
3848 (void) get_variable((Var *) node, 0, true, context);
3852 get_const_expr((Const *) node, context, 0);
3856 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
3860 get_agg_expr((Aggref *) node, context);
3865 ArrayRef *aref = (ArrayRef *) node;
3869 * Parenthesize the argument unless it's a simple Var or a
3870 * FieldSelect. (In particular, if it's another ArrayRef, we
3871 * *must* parenthesize to avoid confusion.)
3873 need_parens = !IsA(aref->refexpr, Var) &&
3874 !IsA(aref->refexpr, FieldSelect);
3876 appendStringInfoChar(buf, '(');
3877 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
3879 appendStringInfoChar(buf, ')');
3880 printSubscripts(aref, context);
3883 * Array assignment nodes should have been handled in
3884 * processIndirection().
3886 if (aref->refassgnexpr)
3887 elog(ERROR, "unexpected refassgnexpr");
3892 get_func_expr((FuncExpr *) node, context, showimplicit);
3896 get_oper_expr((OpExpr *) node, context);
3899 case T_DistinctExpr:
3901 DistinctExpr *expr = (DistinctExpr *) node;
3902 List *args = expr->args;
3903 Node *arg1 = (Node *) linitial(args);
3904 Node *arg2 = (Node *) lsecond(args);
3906 if (!PRETTY_PAREN(context))
3907 appendStringInfoChar(buf, '(');
3908 get_rule_expr_paren(arg1, context, true, node);
3909 appendStringInfo(buf, " IS DISTINCT FROM ");
3910 get_rule_expr_paren(arg2, context, true, node);
3911 if (!PRETTY_PAREN(context))
3912 appendStringInfoChar(buf, ')');
3916 case T_ScalarArrayOpExpr:
3918 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
3919 List *args = expr->args;
3920 Node *arg1 = (Node *) linitial(args);
3921 Node *arg2 = (Node *) lsecond(args);
3923 if (!PRETTY_PAREN(context))
3924 appendStringInfoChar(buf, '(');
3925 get_rule_expr_paren(arg1, context, true, node);
3926 appendStringInfo(buf, " %s %s (",
3927 generate_operator_name(expr->opno,
3929 get_element_type(exprType(arg2))),
3930 expr->useOr ? "ANY" : "ALL");
3931 get_rule_expr_paren(arg2, context, true, node);
3932 appendStringInfoChar(buf, ')');
3933 if (!PRETTY_PAREN(context))
3934 appendStringInfoChar(buf, ')');
3940 BoolExpr *expr = (BoolExpr *) node;
3941 Node *first_arg = linitial(expr->args);
3942 ListCell *arg = lnext(list_head(expr->args));
3944 switch (expr->boolop)
3947 if (!PRETTY_PAREN(context))
3948 appendStringInfoChar(buf, '(');
3949 get_rule_expr_paren(first_arg, context,
3953 appendStringInfo(buf, " AND ");
3954 get_rule_expr_paren((Node *) lfirst(arg), context,
3958 if (!PRETTY_PAREN(context))
3959 appendStringInfoChar(buf, ')');
3963 if (!PRETTY_PAREN(context))
3964 appendStringInfoChar(buf, '(');
3965 get_rule_expr_paren(first_arg, context,
3969 appendStringInfo(buf, " OR ");
3970 get_rule_expr_paren((Node *) lfirst(arg), context,
3974 if (!PRETTY_PAREN(context))
3975 appendStringInfoChar(buf, ')');
3979 if (!PRETTY_PAREN(context))
3980 appendStringInfoChar(buf, '(');
3981 appendStringInfo(buf, "NOT ");
3982 get_rule_expr_paren(first_arg, context,
3984 if (!PRETTY_PAREN(context))
3985 appendStringInfoChar(buf, ')');
3989 elog(ERROR, "unrecognized boolop: %d",
3990 (int) expr->boolop);
3996 get_sublink_expr((SubLink *) node, context);
4002 * We cannot see an already-planned subplan in rule deparsing,
4003 * only while EXPLAINing a query plan. For now, just punt.
4005 if (((SubPlan *) node)->useHashTable)
4006 appendStringInfo(buf, "(hashed subplan)");
4008 appendStringInfo(buf, "(subplan)");
4012 case T_AlternativeSubPlan:
4013 /* As above, just punt */
4014 appendStringInfo(buf, "(alternative subplans)");
4019 FieldSelect *fselect = (FieldSelect *) node;
4020 Node *arg = (Node *) fselect->arg;
4021 int fno = fselect->fieldnum;
4022 const char *fieldname;
4026 * Parenthesize the argument unless it's an ArrayRef or
4027 * another FieldSelect. Note in particular that it would be
4028 * WRONG to not parenthesize a Var argument; simplicity is not
4029 * the issue here, having the right number of names is.
4031 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4033 appendStringInfoChar(buf, '(');
4034 get_rule_expr(arg, context, true);
4036 appendStringInfoChar(buf, ')');
4039 * Get and print the field name.
4041 fieldname = get_name_for_var_field((Var *) arg, fno,
4043 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4050 * We shouldn't see FieldStore here; it should have been stripped
4051 * off by processIndirection().
4053 elog(ERROR, "unexpected FieldStore");
4058 RelabelType *relabel = (RelabelType *) node;
4059 Node *arg = (Node *) relabel->arg;
4061 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
4064 /* don't show the implicit cast */
4065 get_rule_expr_paren(arg, context, false, node);
4069 get_coercion_expr(arg, context,
4070 relabel->resulttype,
4071 relabel->resulttypmod,
4079 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
4080 Node *arg = (Node *) iocoerce->arg;
4082 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4085 /* don't show the implicit cast */
4086 get_rule_expr_paren(arg, context, false, node);
4090 get_coercion_expr(arg, context,
4091 iocoerce->resulttype,
4098 case T_ArrayCoerceExpr:
4100 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4101 Node *arg = (Node *) acoerce->arg;
4103 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4106 /* don't show the implicit cast */
4107 get_rule_expr_paren(arg, context, false, node);
4111 get_coercion_expr(arg, context,
4112 acoerce->resulttype,
4113 acoerce->resulttypmod,
4119 case T_ConvertRowtypeExpr:
4121 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4122 Node *arg = (Node *) convert->arg;
4124 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4127 /* don't show the implicit cast */
4128 get_rule_expr_paren(arg, context, false, node);
4132 get_coercion_expr(arg, context,
4133 convert->resulttype, -1,
4141 CaseExpr *caseexpr = (CaseExpr *) node;
4144 appendContextKeyword(context, "CASE",
4145 0, PRETTYINDENT_VAR, 0);
4148 appendStringInfoChar(buf, ' ');
4149 get_rule_expr((Node *) caseexpr->arg, context, true);
4151 foreach(temp, caseexpr->args)
4153 CaseWhen *when = (CaseWhen *) lfirst(temp);
4154 Node *w = (Node *) when->expr;
4156 if (!PRETTY_INDENT(context))
4157 appendStringInfoChar(buf, ' ');
4158 appendContextKeyword(context, "WHEN ",
4163 * The parser should have produced WHEN clauses of the
4164 * form "CaseTestExpr = RHS"; we want to show just the
4165 * RHS. If the user wrote something silly like "CASE
4166 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4167 * simplify_boolean_equality() may have reduced this
4168 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4169 * which we have to show "TRUE" or "FALSE". Also,
4170 * depending on context the original CaseTestExpr
4171 * might have been reduced to a Const (but we won't
4172 * see "WHEN Const").
4178 Assert(IsA(linitial(((OpExpr *) w)->args),
4180 IsA(linitial(((OpExpr *) w)->args),
4182 rhs = (Node *) lsecond(((OpExpr *) w)->args);
4183 get_rule_expr(rhs, context, false);
4185 else if (IsA(w, CaseTestExpr))
4186 appendStringInfo(buf, "TRUE");
4187 else if (not_clause(w))
4189 Assert(IsA(get_notclausearg((Expr *) w),
4191 appendStringInfo(buf, "FALSE");
4194 elog(ERROR, "unexpected CASE WHEN clause: %d",
4198 get_rule_expr(w, context, false);
4199 appendStringInfo(buf, " THEN ");
4200 get_rule_expr((Node *) when->result, context, true);
4202 if (!PRETTY_INDENT(context))
4203 appendStringInfoChar(buf, ' ');
4204 appendContextKeyword(context, "ELSE ",
4206 get_rule_expr((Node *) caseexpr->defresult, context, true);
4207 if (!PRETTY_INDENT(context))
4208 appendStringInfoChar(buf, ' ');
4209 appendContextKeyword(context, "END",
4210 -PRETTYINDENT_VAR, 0, 0);
4216 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4218 appendStringInfo(buf, "ARRAY[");
4219 get_rule_expr((Node *) arrayexpr->elements, context, true);
4220 appendStringInfoChar(buf, ']');
4226 RowExpr *rowexpr = (RowExpr *) node;
4227 TupleDesc tupdesc = NULL;
4233 * If it's a named type and not RECORD, we may have to skip
4234 * dropped columns and/or claim there are NULLs for added
4237 if (rowexpr->row_typeid != RECORDOID)
4239 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4240 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4244 * SQL99 allows "ROW" to be omitted when there is more than
4245 * one column, but for simplicity we always print it.
4247 appendStringInfo(buf, "ROW(");
4250 foreach(arg, rowexpr->args)
4252 Node *e = (Node *) lfirst(arg);
4254 if (tupdesc == NULL ||
4255 !tupdesc->attrs[i]->attisdropped)
4257 appendStringInfoString(buf, sep);
4258 get_rule_expr(e, context, true);
4263 if (tupdesc != NULL)
4265 while (i < tupdesc->natts)
4267 if (!tupdesc->attrs[i]->attisdropped)
4269 appendStringInfoString(buf, sep);
4270 appendStringInfo(buf, "NULL");
4276 ReleaseTupleDesc(tupdesc);
4278 appendStringInfo(buf, ")");
4279 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4280 appendStringInfo(buf, "::%s",
4281 format_type_with_typemod(rowexpr->row_typeid, -1));
4285 case T_RowCompareExpr:
4287 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
4292 * SQL99 allows "ROW" to be omitted when there is more than
4293 * one column, but for simplicity we always print it.
4295 appendStringInfo(buf, "(ROW(");
4297 foreach(arg, rcexpr->largs)
4299 Node *e = (Node *) lfirst(arg);
4301 appendStringInfoString(buf, sep);
4302 get_rule_expr(e, context, true);
4307 * We assume that the name of the first-column operator will
4308 * do for all the rest too. This is definitely open to
4309 * failure, eg if some but not all operators were renamed
4310 * since the construct was parsed, but there seems no way to
4313 appendStringInfo(buf, ") %s ROW(",
4314 generate_operator_name(linitial_oid(rcexpr->opnos),
4315 exprType(linitial(rcexpr->largs)),
4316 exprType(linitial(rcexpr->rargs))));
4318 foreach(arg, rcexpr->rargs)
4320 Node *e = (Node *) lfirst(arg);
4322 appendStringInfoString(buf, sep);
4323 get_rule_expr(e, context, true);
4326 appendStringInfo(buf, "))");
4330 case T_CoalesceExpr:
4332 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
4334 appendStringInfo(buf, "COALESCE(");
4335 get_rule_expr((Node *) coalesceexpr->args, context, true);
4336 appendStringInfoChar(buf, ')');
4342 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
4344 switch (minmaxexpr->op)
4347 appendStringInfo(buf, "GREATEST(");
4350 appendStringInfo(buf, "LEAST(");
4353 get_rule_expr((Node *) minmaxexpr->args, context, true);
4354 appendStringInfoChar(buf, ')');
4360 XmlExpr *xexpr = (XmlExpr *) node;
4361 bool needcomma = false;
4369 appendStringInfoString(buf, "XMLCONCAT(");
4372 appendStringInfoString(buf, "XMLELEMENT(");
4375 appendStringInfoString(buf, "XMLFOREST(");
4378 appendStringInfoString(buf, "XMLPARSE(");
4381 appendStringInfoString(buf, "XMLPI(");
4384 appendStringInfoString(buf, "XMLROOT(");
4386 case IS_XMLSERIALIZE:
4387 appendStringInfoString(buf, "XMLSERIALIZE(");
4392 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
4394 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
4395 appendStringInfoString(buf, "DOCUMENT ");
4397 appendStringInfoString(buf, "CONTENT ");
4401 appendStringInfo(buf, "NAME %s",
4402 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
4405 if (xexpr->named_args)
4407 if (xexpr->op != IS_XMLFOREST)
4410 appendStringInfoString(buf, ", ");
4411 appendStringInfoString(buf, "XMLATTRIBUTES(");
4414 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
4416 Node *e = (Node *) lfirst(arg);
4417 char *argname = strVal(lfirst(narg));
4420 appendStringInfoString(buf, ", ");
4421 get_rule_expr((Node *) e, context, true);
4422 appendStringInfo(buf, " AS %s",
4423 quote_identifier(map_xml_name_to_sql_identifier(argname)));
4426 if (xexpr->op != IS_XMLFOREST)
4427 appendStringInfoChar(buf, ')');
4432 appendStringInfoString(buf, ", ");
4439 case IS_XMLSERIALIZE:
4440 /* no extra decoration needed */
4441 get_rule_expr((Node *) xexpr->args, context, true);
4444 Assert(list_length(xexpr->args) == 2);
4446 get_rule_expr((Node *) linitial(xexpr->args),
4449 con = (Const *) lsecond(xexpr->args);
4450 Assert(IsA(con, Const));
4451 Assert(!con->constisnull);
4452 if (DatumGetBool(con->constvalue))
4453 appendStringInfoString(buf,
4454 " PRESERVE WHITESPACE");
4456 appendStringInfoString(buf,
4457 " STRIP WHITESPACE");
4460 Assert(list_length(xexpr->args) == 3);
4462 get_rule_expr((Node *) linitial(xexpr->args),
4465 appendStringInfoString(buf, ", VERSION ");
4466 con = (Const *) lsecond(xexpr->args);
4467 if (IsA(con, Const) &&
4469 appendStringInfoString(buf, "NO VALUE");
4471 get_rule_expr((Node *) con, context, false);
4473 con = (Const *) lthird(xexpr->args);
4474 Assert(IsA(con, Const));
4475 if (con->constisnull)
4476 /* suppress STANDALONE NO VALUE */ ;
4479 switch (DatumGetInt32(con->constvalue))
4481 case XML_STANDALONE_YES:
4482 appendStringInfoString(buf,
4483 ", STANDALONE YES");
4485 case XML_STANDALONE_NO:
4486 appendStringInfoString(buf,
4489 case XML_STANDALONE_NO_VALUE:
4490 appendStringInfoString(buf,
4491 ", STANDALONE NO VALUE");
4499 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
4504 if (xexpr->op == IS_XMLSERIALIZE)
4505 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
4507 if (xexpr->op == IS_DOCUMENT)
4508 appendStringInfoString(buf, " IS DOCUMENT");
4510 appendStringInfoChar(buf, ')');
4516 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4518 appendStringInfo(buf, "NULLIF(");
4519 get_rule_expr((Node *) nullifexpr->args, context, true);
4520 appendStringInfoChar(buf, ')');
4526 NullTest *ntest = (NullTest *) node;
4528 if (!PRETTY_PAREN(context))
4529 appendStringInfoChar(buf, '(');
4530 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
4531 switch (ntest->nulltesttype)
4534 appendStringInfo(buf, " IS NULL");
4537 appendStringInfo(buf, " IS NOT NULL");
4540 elog(ERROR, "unrecognized nulltesttype: %d",
4541 (int) ntest->nulltesttype);
4543 if (!PRETTY_PAREN(context))
4544 appendStringInfoChar(buf, ')');
4550 BooleanTest *btest = (BooleanTest *) node;
4552 if (!PRETTY_PAREN(context))
4553 appendStringInfoChar(buf, '(');
4554 get_rule_expr_paren((Node *) btest->arg, context, false, node);
4555 switch (btest->booltesttype)
4558 appendStringInfo(buf, " IS TRUE");
4561 appendStringInfo(buf, " IS NOT TRUE");
4564 appendStringInfo(buf, " IS FALSE");
4567 appendStringInfo(buf, " IS NOT FALSE");
4570 appendStringInfo(buf, " IS UNKNOWN");
4572 case IS_NOT_UNKNOWN:
4573 appendStringInfo(buf, " IS NOT UNKNOWN");
4576 elog(ERROR, "unrecognized booltesttype: %d",
4577 (int) btest->booltesttype);
4579 if (!PRETTY_PAREN(context))
4580 appendStringInfoChar(buf, ')');
4584 case T_CoerceToDomain:
4586 CoerceToDomain *ctest = (CoerceToDomain *) node;
4587 Node *arg = (Node *) ctest->arg;
4589 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
4592 /* don't show the implicit cast */
4593 get_rule_expr(arg, context, false);
4597 get_coercion_expr(arg, context,
4599 ctest->resulttypmod,
4605 case T_CoerceToDomainValue:
4606 appendStringInfo(buf, "VALUE");
4609 case T_SetToDefault:
4610 appendStringInfo(buf, "DEFAULT");
4613 case T_CurrentOfExpr:
4615 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
4617 if (cexpr->cursor_name)
4618 appendStringInfo(buf, "CURRENT OF %s",
4619 quote_identifier(cexpr->cursor_name));
4621 appendStringInfo(buf, "CURRENT OF $%d",
4622 cexpr->cursor_param);
4632 foreach(l, (List *) node)
4634 appendStringInfoString(buf, sep);
4635 get_rule_expr((Node *) lfirst(l), context, showimplicit);
4642 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
4649 * get_oper_expr - Parse back an OpExpr node
4652 get_oper_expr(OpExpr *expr, deparse_context *context)
4654 StringInfo buf = context->buf;
4655 Oid opno = expr->opno;
4656 List *args = expr->args;
4658 if (!PRETTY_PAREN(context))
4659 appendStringInfoChar(buf, '(');
4660 if (list_length(args) == 2)
4662 /* binary operator */
4663 Node *arg1 = (Node *) linitial(args);
4664 Node *arg2 = (Node *) lsecond(args);
4666 get_rule_expr_paren(arg1, context, true, (Node *) expr);
4667 appendStringInfo(buf, " %s ",
4668 generate_operator_name(opno,
4671 get_rule_expr_paren(arg2, context, true, (Node *) expr);
4675 /* unary operator --- but which side? */
4676 Node *arg = (Node *) linitial(args);
4678 Form_pg_operator optup;
4680 tp = SearchSysCache(OPEROID,
4681 ObjectIdGetDatum(opno),
4683 if (!HeapTupleIsValid(tp))
4684 elog(ERROR, "cache lookup failed for operator %u", opno);
4685 optup = (Form_pg_operator) GETSTRUCT(tp);
4686 switch (optup->oprkind)
4689 appendStringInfo(buf, "%s ",
4690 generate_operator_name(opno,
4693 get_rule_expr_paren(arg, context, true, (Node *) expr);
4696 get_rule_expr_paren(arg, context, true, (Node *) expr);
4697 appendStringInfo(buf, " %s",
4698 generate_operator_name(opno,
4703 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
4705 ReleaseSysCache(tp);
4707 if (!PRETTY_PAREN(context))
4708 appendStringInfoChar(buf, ')');
4712 * get_func_expr - Parse back a FuncExpr node
4715 get_func_expr(FuncExpr *expr, deparse_context *context,
4718 StringInfo buf = context->buf;
4719 Oid funcoid = expr->funcid;
4720 Oid argtypes[FUNC_MAX_ARGS];
4726 * If the function call came from an implicit coercion, then just show the
4727 * first argument --- unless caller wants to see implicit coercions.
4729 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
4731 get_rule_expr_paren((Node *) linitial(expr->args), context,
4732 false, (Node *) expr);
4737 * If the function call came from a cast, then show the first argument
4738 * plus an explicit cast operation.
4740 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
4741 expr->funcformat == COERCE_IMPLICIT_CAST)
4743 Node *arg = linitial(expr->args);
4744 Oid rettype = expr->funcresulttype;
4745 int32 coercedTypmod;
4747 /* Get the typmod if this is a length-coercion function */
4748 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
4750 get_coercion_expr(arg, context,
4751 rettype, coercedTypmod,
4758 * Normal function: display as proname(args). First we need to extract
4759 * the argument datatypes.
4762 foreach(l, expr->args)
4764 if (nargs >= FUNC_MAX_ARGS)
4766 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
4767 errmsg("too many arguments")));
4768 argtypes[nargs] = exprType((Node *) lfirst(l));
4772 appendStringInfo(buf, "%s(",
4773 generate_function_name(funcoid, nargs, argtypes,
4776 foreach(l, expr->args)
4779 appendStringInfoString(buf, ", ");
4780 if (is_variadic && lnext(l) == NULL)
4781 appendStringInfoString(buf, "VARIADIC ");
4782 get_rule_expr((Node *) lfirst(l), context, true);
4784 appendStringInfoChar(buf, ')');
4788 * get_agg_expr - Parse back an Aggref node
4791 get_agg_expr(Aggref *aggref, deparse_context *context)
4793 StringInfo buf = context->buf;
4794 Oid argtypes[FUNC_MAX_ARGS];
4799 foreach(l, aggref->args)
4801 if (nargs >= FUNC_MAX_ARGS)
4803 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
4804 errmsg("too many arguments")));
4805 argtypes[nargs] = exprType((Node *) lfirst(l));
4809 appendStringInfo(buf, "%s(%s",
4810 generate_function_name(aggref->aggfnoid,
4811 nargs, argtypes, NULL),
4812 aggref->aggdistinct ? "DISTINCT " : "");
4813 /* aggstar can be set only in zero-argument aggregates */
4814 if (aggref->aggstar)
4815 appendStringInfoChar(buf, '*');
4817 get_rule_expr((Node *) aggref->args, context, true);
4818 appendStringInfoChar(buf, ')');
4824 * Make a string representation of a value coerced to a specific type
4828 get_coercion_expr(Node *arg, deparse_context *context,
4829 Oid resulttype, int32 resulttypmod,
4832 StringInfo buf = context->buf;
4835 * Since parse_coerce.c doesn't immediately collapse application of
4836 * length-coercion functions to constants, what we'll typically see in
4837 * such cases is a Const with typmod -1 and a length-coercion function
4838 * right above it. Avoid generating redundant output. However, beware of
4839 * suppressing casts when the user actually wrote something like
4840 * 'foo'::text::char(3).
4842 if (arg && IsA(arg, Const) &&
4843 ((Const *) arg)->consttype == resulttype &&
4844 ((Const *) arg)->consttypmod == -1)
4846 /* Show the constant without normal ::typename decoration */
4847 get_const_expr((Const *) arg, context, -1);
4851 if (!PRETTY_PAREN(context))
4852 appendStringInfoChar(buf, '(');
4853 get_rule_expr_paren(arg, context, false, parentNode);
4854 if (!PRETTY_PAREN(context))
4855 appendStringInfoChar(buf, ')');
4857 appendStringInfo(buf, "::%s",
4858 format_type_with_typemod(resulttype, resulttypmod));
4864 * Make a string representation of a Const
4866 * showtype can be -1 to never show "::typename" decoration, or +1 to always
4867 * show it, or 0 to show it only if the constant wouldn't be assumed to be
4868 * the right type by default.
4872 get_const_expr(Const *constval, deparse_context *context, int showtype)
4874 StringInfo buf = context->buf;
4878 bool isfloat = false;
4881 if (constval->constisnull)
4884 * Always label the type of a NULL constant to prevent misdecisions
4885 * about type when reparsing.
4887 appendStringInfo(buf, "NULL");
4889 appendStringInfo(buf, "::%s",
4890 format_type_with_typemod(constval->consttype,
4891 constval->consttypmod));
4895 getTypeOutputInfo(constval->consttype,
4896 &typoutput, &typIsVarlena);
4898 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
4900 switch (constval->consttype)
4911 * These types are printed without quotes unless they contain
4912 * values that aren't accepted by the scanner unquoted (e.g.,
4913 * 'NaN'). Note that strtod() and friends might accept NaN,
4914 * so we can't use that to test.
4916 * In reality we only need to defend against infinity and NaN,
4917 * so we need not get too crazy about pattern matching here.
4919 * There is a special-case gotcha: if the constant is signed,
4920 * we need to parenthesize it, else the parser might see a
4921 * leading plus/minus as binding less tightly than adjacent
4922 * operators --- particularly, the cast that we might attach
4925 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
4927 if (extval[0] == '+' || extval[0] == '-')
4928 appendStringInfo(buf, "(%s)", extval);
4930 appendStringInfoString(buf, extval);
4931 if (strcspn(extval, "eE.") != strlen(extval))
4932 isfloat = true; /* it looks like a float */
4935 appendStringInfo(buf, "'%s'", extval);
4941 appendStringInfo(buf, "B'%s'", extval);
4945 if (strcmp(extval, "t") == 0)
4946 appendStringInfo(buf, "true");
4948 appendStringInfo(buf, "false");
4952 simple_quote_literal(buf, extval);
4962 * For showtype == 0, append ::typename unless the constant will be
4963 * implicitly typed as the right type when it is read in.
4965 * XXX this code has to be kept in sync with the behavior of the parser,
4966 * especially make_const.
4968 switch (constval->consttype)
4973 /* These types can be left unlabeled */
4979 * Float-looking constants will be typed as numeric, but if
4980 * there's a specific typmod we need to show it.
4982 needlabel = !isfloat || (constval->consttypmod >= 0);
4988 if (needlabel || showtype > 0)
4989 appendStringInfo(buf, "::%s",
4990 format_type_with_typemod(constval->consttype,
4991 constval->consttypmod));
4995 * simple_quote_literal - Format a string as a SQL literal, append to buf
4998 simple_quote_literal(StringInfo buf, const char *val)
5003 * We form the string literal according to the prevailing setting
5004 * of standard_conforming_strings; we never use E''. User is
5005 * responsible for making sure result is used correctly.
5007 appendStringInfoChar(buf, '\'');
5008 for (valptr = val; *valptr; valptr++)
5012 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
5013 appendStringInfoChar(buf, ch);
5014 appendStringInfoChar(buf, ch);
5016 appendStringInfoChar(buf, '\'');
5021 * get_sublink_expr - Parse back a sublink
5025 get_sublink_expr(SubLink *sublink, deparse_context *context)
5027 StringInfo buf = context->buf;
5028 Query *query = (Query *) (sublink->subselect);
5029 char *opname = NULL;
5032 if (sublink->subLinkType == ARRAY_SUBLINK)
5033 appendStringInfo(buf, "ARRAY(");
5035 appendStringInfoChar(buf, '(');
5038 * Note that we print the name of only the first operator, when there are
5039 * multiple combining operators. This is an approximation that could go
5040 * wrong in various scenarios (operators in different schemas, renamed
5041 * operators, etc) but there is not a whole lot we can do about it, since
5042 * the syntax allows only one operator to be shown.
5044 if (sublink->testexpr)
5046 if (IsA(sublink->testexpr, OpExpr))
5048 /* single combining operator */
5049 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
5051 get_rule_expr(linitial(opexpr->args), context, true);
5052 opname = generate_operator_name(opexpr->opno,
5053 exprType(linitial(opexpr->args)),
5054 exprType(lsecond(opexpr->args)));
5056 else if (IsA(sublink->testexpr, BoolExpr))
5058 /* multiple combining operators, = or <> cases */
5062 appendStringInfoChar(buf, '(');
5064 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
5066 OpExpr *opexpr = (OpExpr *) lfirst(l);
5068 Assert(IsA(opexpr, OpExpr));
5069 appendStringInfoString(buf, sep);
5070 get_rule_expr(linitial(opexpr->args), context, true);
5072 opname = generate_operator_name(opexpr->opno,
5073 exprType(linitial(opexpr->args)),
5074 exprType(lsecond(opexpr->args)));
5077 appendStringInfoChar(buf, ')');
5079 else if (IsA(sublink->testexpr, RowCompareExpr))
5081 /* multiple combining operators, < <= > >= cases */
5082 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
5084 appendStringInfoChar(buf, '(');
5085 get_rule_expr((Node *) rcexpr->largs, context, true);
5086 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
5087 exprType(linitial(rcexpr->largs)),
5088 exprType(linitial(rcexpr->rargs)));
5089 appendStringInfoChar(buf, ')');
5092 elog(ERROR, "unrecognized testexpr type: %d",
5093 (int) nodeTag(sublink->testexpr));
5098 switch (sublink->subLinkType)
5100 case EXISTS_SUBLINK:
5101 appendStringInfo(buf, "EXISTS ");
5105 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5106 appendStringInfo(buf, " IN ");
5108 appendStringInfo(buf, " %s ANY ", opname);
5112 appendStringInfo(buf, " %s ALL ", opname);
5115 case ROWCOMPARE_SUBLINK:
5116 appendStringInfo(buf, " %s ", opname);
5124 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
5126 elog(ERROR, "unrecognized sublink type: %d",
5127 (int) sublink->subLinkType);
5132 appendStringInfoChar(buf, '(');
5134 get_query_def(query, buf, context->namespaces, NULL,
5135 context->prettyFlags, context->indentLevel);
5138 appendStringInfo(buf, "))");
5140 appendStringInfoChar(buf, ')');
5145 * get_from_clause - Parse back a FROM clause
5147 * "prefix" is the keyword that denotes the start of the list of FROM
5148 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5149 * is USING when parsing back DELETE.
5153 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5155 StringInfo buf = context->buf;
5160 * We use the query's jointree as a guide to what to print. However, we
5161 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5162 * only appear at the top level of the jointree, so it's sufficient to
5163 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5166 foreach(l, query->jointree->fromlist)
5168 Node *jtnode = (Node *) lfirst(l);
5170 if (IsA(jtnode, RangeTblRef))
5172 int varno = ((RangeTblRef *) jtnode)->rtindex;
5173 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5181 appendContextKeyword(context, prefix,
5182 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5186 appendStringInfoString(buf, ", ");
5188 get_from_clause_item(jtnode, query, context);
5193 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5195 StringInfo buf = context->buf;
5197 if (IsA(jtnode, RangeTblRef))
5199 int varno = ((RangeTblRef *) jtnode)->rtindex;
5200 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5201 bool gavealias = false;
5203 switch (rte->rtekind)
5206 /* Normal relation RTE */
5207 appendStringInfo(buf, "%s%s",
5209 generate_relation_name(rte->relid));
5213 appendStringInfoChar(buf, '(');
5214 get_query_def(rte->subquery, buf, context->namespaces, NULL,
5215 context->prettyFlags, context->indentLevel);
5216 appendStringInfoChar(buf, ')');
5220 get_rule_expr(rte->funcexpr, context, true);
5223 /* Values list RTE */
5224 get_values_def(rte->values_lists, context);
5227 appendStringInfoString(buf, quote_identifier(rte->ctename));
5230 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
5234 if (rte->alias != NULL)
5236 appendStringInfo(buf, " %s",
5237 quote_identifier(rte->alias->aliasname));
5240 else if (rte->rtekind == RTE_RELATION &&
5241 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
5244 * Apparently the rel has been renamed since the rule was made.
5245 * Emit a fake alias clause so that variable references will still
5246 * work. This is not a 100% solution but should work in most
5247 * reasonable situations.
5249 appendStringInfo(buf, " %s",
5250 quote_identifier(rte->eref->aliasname));
5253 else if (rte->rtekind == RTE_FUNCTION)
5256 * For a function RTE, always give an alias. This covers possible
5257 * renaming of the function and/or instability of the
5258 * FigureColname rules for things that aren't simple functions.
5260 appendStringInfo(buf, " %s",
5261 quote_identifier(rte->eref->aliasname));
5265 if (rte->rtekind == RTE_FUNCTION)
5267 if (rte->funccoltypes != NIL)
5269 /* Function returning RECORD, reconstruct the columndefs */
5271 appendStringInfo(buf, " AS ");
5272 get_from_clause_coldeflist(rte->eref->colnames,
5274 rte->funccoltypmods,
5280 * For a function RTE, always emit a complete column alias
5281 * list; this is to protect against possible instability of
5282 * the default column names (eg, from altering parameter
5285 get_from_clause_alias(rte->eref, rte, context);
5291 * For non-function RTEs, just report whatever the user originally
5292 * gave as column aliases.
5294 get_from_clause_alias(rte->alias, rte, context);
5297 else if (IsA(jtnode, JoinExpr))
5299 JoinExpr *j = (JoinExpr *) jtnode;
5300 bool need_paren_on_right;
5302 need_paren_on_right = PRETTY_PAREN(context) &&
5303 !IsA(j->rarg, RangeTblRef) &&
5304 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
5306 if (!PRETTY_PAREN(context) || j->alias != NULL)
5307 appendStringInfoChar(buf, '(');
5309 get_from_clause_item(j->larg, query, context);
5313 if (!PRETTY_INDENT(context))
5314 appendStringInfoChar(buf, ' ');
5315 switch (j->jointype)
5318 appendContextKeyword(context, "NATURAL JOIN ",
5320 PRETTYINDENT_JOIN, 0);
5323 appendContextKeyword(context, "NATURAL LEFT JOIN ",
5325 PRETTYINDENT_JOIN, 0);
5328 appendContextKeyword(context, "NATURAL FULL JOIN ",
5330 PRETTYINDENT_JOIN, 0);
5333 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
5335 PRETTYINDENT_JOIN, 0);
5338 elog(ERROR, "unrecognized join type: %d",
5344 switch (j->jointype)
5348 appendContextKeyword(context, " JOIN ",
5350 PRETTYINDENT_JOIN, 2);
5352 appendContextKeyword(context, " CROSS JOIN ",
5354 PRETTYINDENT_JOIN, 1);
5357 appendContextKeyword(context, " LEFT JOIN ",
5359 PRETTYINDENT_JOIN, 2);
5362 appendContextKeyword(context, " FULL JOIN ",
5364 PRETTYINDENT_JOIN, 2);
5367 appendContextKeyword(context, " RIGHT JOIN ",
5369 PRETTYINDENT_JOIN, 2);
5372 elog(ERROR, "unrecognized join type: %d",
5377 if (need_paren_on_right)
5378 appendStringInfoChar(buf, '(');
5379 get_from_clause_item(j->rarg, query, context);
5380 if (need_paren_on_right)
5381 appendStringInfoChar(buf, ')');
5383 context->indentLevel -= PRETTYINDENT_JOIN_ON;
5391 appendStringInfo(buf, " USING (");
5392 foreach(col, j->using)
5394 if (col != list_head(j->using))
5395 appendStringInfo(buf, ", ");
5396 appendStringInfoString(buf,
5397 quote_identifier(strVal(lfirst(col))));
5399 appendStringInfoChar(buf, ')');
5403 appendStringInfo(buf, " ON ");
5404 if (!PRETTY_PAREN(context))
5405 appendStringInfoChar(buf, '(');
5406 get_rule_expr(j->quals, context, false);
5407 if (!PRETTY_PAREN(context))
5408 appendStringInfoChar(buf, ')');
5411 if (!PRETTY_PAREN(context) || j->alias != NULL)
5412 appendStringInfoChar(buf, ')');
5414 /* Yes, it's correct to put alias after the right paren ... */
5415 if (j->alias != NULL)
5417 appendStringInfo(buf, " %s",
5418 quote_identifier(j->alias->aliasname));
5419 get_from_clause_alias(j->alias,
5420 rt_fetch(j->rtindex, query->rtable),
5425 elog(ERROR, "unrecognized node type: %d",
5426 (int) nodeTag(jtnode));
5430 * get_from_clause_alias - reproduce column alias list
5432 * This is tricky because we must ignore dropped columns.
5435 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
5436 deparse_context *context)
5438 StringInfo buf = context->buf;
5443 if (alias == NULL || alias->colnames == NIL)
5444 return; /* definitely nothing to do */
5447 foreach(col, alias->colnames)
5450 if (get_rte_attribute_is_dropped(rte, attnum))
5454 appendStringInfoChar(buf, '(');
5458 appendStringInfo(buf, ", ");
5459 appendStringInfoString(buf,
5460 quote_identifier(strVal(lfirst(col))));
5463 appendStringInfoChar(buf, ')');
5467 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5469 * The coldeflist is appended immediately (no space) to buf. Caller is
5470 * responsible for ensuring that an alias or AS is present before it.
5473 get_from_clause_coldeflist(List *names, List *types, List *typmods,
5474 deparse_context *context)
5476 StringInfo buf = context->buf;
5482 appendStringInfoChar(buf, '(');
5484 l2 = list_head(types);
5485 l3 = list_head(typmods);
5488 char *attname = strVal(lfirst(l1));
5492 atttypid = lfirst_oid(l2);
5494 atttypmod = lfirst_int(l3);
5498 appendStringInfo(buf, ", ");
5499 appendStringInfo(buf, "%s %s",
5500 quote_identifier(attname),
5501 format_type_with_typemod(atttypid, atttypmod));
5505 appendStringInfoChar(buf, ')');
5509 * get_opclass_name - fetch name of an index operator class
5511 * The opclass name is appended (after a space) to buf.
5513 * Output is suppressed if the opclass is the default for the given
5514 * actual_datatype. (If you don't want this behavior, just pass
5515 * InvalidOid for actual_datatype.)
5518 get_opclass_name(Oid opclass, Oid actual_datatype,
5522 Form_pg_opclass opcrec;
5526 ht_opc = SearchSysCache(CLAOID,
5527 ObjectIdGetDatum(opclass),
5529 if (!HeapTupleIsValid(ht_opc))
5530 elog(ERROR, "cache lookup failed for opclass %u", opclass);
5531 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
5533 if (!OidIsValid(actual_datatype) ||
5534 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
5536 /* Okay, we need the opclass name. Do we need to qualify it? */
5537 opcname = NameStr(opcrec->opcname);
5538 if (OpclassIsVisible(opclass))
5539 appendStringInfo(buf, " %s", quote_identifier(opcname));
5542 nspname = get_namespace_name(opcrec->opcnamespace);
5543 appendStringInfo(buf, " %s.%s",
5544 quote_identifier(nspname),
5545 quote_identifier(opcname));
5548 ReleaseSysCache(ht_opc);
5552 * processIndirection - take care of array and subfield assignment
5554 * We strip any top-level FieldStore or assignment ArrayRef nodes that
5555 * appear in the input, and return the subexpression that's to be assigned.
5556 * If printit is true, we also print out the appropriate decoration for the
5557 * base column name (that the caller just printed).
5560 processIndirection(Node *node, deparse_context *context, bool printit)
5562 StringInfo buf = context->buf;
5568 if (IsA(node, FieldStore))
5570 FieldStore *fstore = (FieldStore *) node;
5574 /* lookup tuple type */
5575 typrelid = get_typ_typrelid(fstore->resulttype);
5576 if (!OidIsValid(typrelid))
5577 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
5578 format_type_be(fstore->resulttype));
5581 * Print the field name. Note we assume here that there's only
5582 * one field being assigned to. This is okay in stored rules but
5583 * could be wrong in executable target lists. Presently no
5584 * problem since explain.c doesn't print plan targetlists, but
5585 * someday may have to think of something ...
5587 fieldname = get_relid_attribute_name(typrelid,
5588 linitial_int(fstore->fieldnums));
5590 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
5593 * We ignore arg since it should be an uninteresting reference to
5594 * the target column or subcolumn.
5596 node = (Node *) linitial(fstore->newvals);
5598 else if (IsA(node, ArrayRef))
5600 ArrayRef *aref = (ArrayRef *) node;
5602 if (aref->refassgnexpr == NULL)
5605 printSubscripts(aref, context);
5608 * We ignore refexpr since it should be an uninteresting reference
5609 * to the target column or subcolumn.
5611 node = (Node *) aref->refassgnexpr;
5621 printSubscripts(ArrayRef *aref, deparse_context *context)
5623 StringInfo buf = context->buf;
5624 ListCell *lowlist_item;
5625 ListCell *uplist_item;
5627 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
5628 foreach(uplist_item, aref->refupperindexpr)
5630 appendStringInfoChar(buf, '[');
5633 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
5634 appendStringInfoChar(buf, ':');
5635 lowlist_item = lnext(lowlist_item);
5637 get_rule_expr((Node *) lfirst(uplist_item), context, false);
5638 appendStringInfoChar(buf, ']');
5643 * quote_identifier - Quote an identifier only if needed
5645 * When quotes are needed, we palloc the required space; slightly
5646 * space-wasteful but well worth it for notational simplicity.
5649 quote_identifier(const char *ident)
5652 * Can avoid quoting if ident starts with a lowercase letter or underscore
5653 * and contains only lowercase letters, digits, and underscores, *and* is
5654 * not any SQL keyword. Otherwise, supply quotes.
5663 * would like to use <ctype.h> macros here, but they might yield unwanted
5664 * locale-specific results...
5666 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
5668 for (ptr = ident; *ptr; ptr++)
5672 if ((ch >= 'a' && ch <= 'z') ||
5673 (ch >= '0' && ch <= '9') ||
5689 * Check for keyword. We quote keywords except for unreserved ones.
5690 * (In some cases we could avoid quoting a col_name or type_func_name
5691 * keyword, but it seems much harder than it's worth to tell that.)
5693 * Note: ScanKeywordLookup() does case-insensitive comparison, but
5694 * that's fine, since we already know we have all-lower-case.
5696 const ScanKeyword *keyword = ScanKeywordLookup(ident);
5698 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
5703 return ident; /* no change needed */
5705 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
5709 for (ptr = ident; *ptr; ptr++)
5724 * quote_qualified_identifier - Quote a possibly-qualified identifier
5726 * Return a name of the form namespace.ident, or just ident if namespace
5727 * is NULL, quoting each component if necessary. The result is palloc'd.
5730 quote_qualified_identifier(const char *namespace,
5735 initStringInfo(&buf);
5737 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
5738 appendStringInfoString(&buf, quote_identifier(ident));
5743 * generate_relation_name
5744 * Compute the name to display for a relation specified by OID
5746 * The result includes all necessary quoting and schema-prefixing.
5749 generate_relation_name(Oid relid)
5752 Form_pg_class reltup;
5756 tp = SearchSysCache(RELOID,
5757 ObjectIdGetDatum(relid),
5759 if (!HeapTupleIsValid(tp))
5760 elog(ERROR, "cache lookup failed for relation %u", relid);
5761 reltup = (Form_pg_class) GETSTRUCT(tp);
5763 /* Qualify the name if not visible in search path */
5764 if (RelationIsVisible(relid))
5767 nspname = get_namespace_name(reltup->relnamespace);
5769 result = quote_qualified_identifier(nspname, NameStr(reltup->relname));
5771 ReleaseSysCache(tp);
5777 * generate_function_name
5778 * Compute the name to display for a function specified by OID,
5779 * given that it is being called with the specified actual arg types.
5780 * (Arg types matter because of ambiguous-function resolution rules.)
5782 * The result includes all necessary quoting and schema-prefixing. We can
5783 * also pass back an indication of whether the function is variadic.
5786 generate_function_name(Oid funcid, int nargs, Oid *argtypes,
5790 Form_pg_proc procform;
5794 FuncDetailCode p_result;
5799 Oid *p_true_typeids;
5801 proctup = SearchSysCache(PROCOID,
5802 ObjectIdGetDatum(funcid),
5804 if (!HeapTupleIsValid(proctup))
5805 elog(ERROR, "cache lookup failed for function %u", funcid);
5806 procform = (Form_pg_proc) GETSTRUCT(proctup);
5807 proname = NameStr(procform->proname);
5808 Assert(nargs >= procform->pronargs);
5811 * The idea here is to schema-qualify only if the parser would fail to
5812 * resolve the correct function given the unqualified func name with the
5813 * specified argtypes.
5815 p_result = func_get_detail(list_make1(makeString(proname)),
5816 NIL, nargs, argtypes, false,
5817 &p_funcid, &p_rettype,
5818 &p_retset, &p_nvargs, &p_true_typeids);
5819 if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
5823 nspname = get_namespace_name(procform->pronamespace);
5825 result = quote_qualified_identifier(nspname, proname);
5827 /* Check variadic-ness if caller cares */
5830 /* "any" variadics are not treated as variadics for listing */
5831 if (OidIsValid(procform->provariadic) &&
5832 procform->provariadic != ANYOID)
5833 *is_variadic = true;
5835 *is_variadic = false;
5838 ReleaseSysCache(proctup);
5844 * generate_operator_name
5845 * Compute the name to display for an operator specified by OID,
5846 * given that it is being called with the specified actual arg types.
5847 * (Arg types matter because of ambiguous-operator resolution rules.
5848 * Pass InvalidOid for unused arg of a unary operator.)
5850 * The result includes all necessary quoting and schema-prefixing,
5851 * plus the OPERATOR() decoration needed to use a qualified operator name
5855 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
5859 Form_pg_operator operform;
5864 initStringInfo(&buf);
5866 opertup = SearchSysCache(OPEROID,
5867 ObjectIdGetDatum(operid),
5869 if (!HeapTupleIsValid(opertup))
5870 elog(ERROR, "cache lookup failed for operator %u", operid);
5871 operform = (Form_pg_operator) GETSTRUCT(opertup);
5872 oprname = NameStr(operform->oprname);
5875 * The idea here is to schema-qualify only if the parser would fail to
5876 * resolve the correct operator given the unqualified op name with the
5877 * specified argtypes.
5879 switch (operform->oprkind)
5882 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
5886 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
5890 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
5894 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
5895 p_result = NULL; /* keep compiler quiet */
5899 if (p_result != NULL && oprid(p_result) == operid)
5903 nspname = get_namespace_name(operform->oprnamespace);
5904 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
5907 appendStringInfoString(&buf, oprname);
5910 appendStringInfoChar(&buf, ')');
5912 if (p_result != NULL)
5913 ReleaseSysCache(p_result);
5915 ReleaseSysCache(opertup);
5921 * Given a C string, produce a TEXT datum.
5923 * We assume that the input was palloc'd and may be freed.
5926 string_to_text(char *str)
5930 result = cstring_to_text(str);
5936 * Generate a C string representing a relation's reloptions, or NULL if none.
5939 flatten_reloptions(Oid relid)
5941 char *result = NULL;
5946 tuple = SearchSysCache(RELOID,
5947 ObjectIdGetDatum(relid),
5949 if (!HeapTupleIsValid(tuple))
5950 elog(ERROR, "cache lookup failed for relation %u", relid);
5952 reloptions = SysCacheGetAttr(RELOID, tuple,
5953 Anum_pg_class_reloptions, &isnull);
5960 * We want to use array_to_text(reloptions, ', ') --- but
5961 * DirectFunctionCall2(array_to_text) does not work, because
5962 * array_to_text() relies on flinfo to be valid. So use
5965 sep = CStringGetTextDatum(", ");
5966 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
5967 result = TextDatumGetCString(txt);
5970 ReleaseSysCache(tuple);