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.284 2008/09/06 20:18:08 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_select_query_def(Query *query, deparse_context *context,
149 TupleDesc resultDesc);
150 static void get_insert_query_def(Query *query, deparse_context *context);
151 static void get_update_query_def(Query *query, deparse_context *context);
152 static void get_delete_query_def(Query *query, deparse_context *context);
153 static void get_utility_query_def(Query *query, deparse_context *context);
154 static void get_basic_select_query(Query *query, deparse_context *context,
155 TupleDesc resultDesc);
156 static void get_target_list(List *targetList, deparse_context *context,
157 TupleDesc resultDesc);
158 static void get_setop_query(Node *setOp, Query *query,
159 deparse_context *context,
160 TupleDesc resultDesc);
161 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
163 deparse_context *context);
164 static char *get_variable(Var *var, int levelsup, bool showstar,
165 deparse_context *context);
166 static RangeTblEntry *find_rte_by_refname(const char *refname,
167 deparse_context *context);
168 static const char *get_simple_binary_op_name(OpExpr *expr);
169 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
170 static void appendStringInfoSpaces(StringInfo buf, int count);
171 static void appendContextKeyword(deparse_context *context, const char *str,
172 int indentBefore, int indentAfter, int indentPlus);
173 static void get_rule_expr(Node *node, deparse_context *context,
175 static void get_oper_expr(OpExpr *expr, deparse_context *context);
176 static void get_func_expr(FuncExpr *expr, deparse_context *context,
178 static void get_agg_expr(Aggref *aggref, deparse_context *context);
179 static void get_coercion_expr(Node *arg, deparse_context *context,
180 Oid resulttype, int32 resulttypmod,
182 static void get_const_expr(Const *constval, deparse_context *context,
184 static void simple_quote_literal(StringInfo buf, const char *val);
185 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
186 static void get_from_clause(Query *query, const char *prefix,
187 deparse_context *context);
188 static void get_from_clause_item(Node *jtnode, Query *query,
189 deparse_context *context);
190 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
191 deparse_context *context);
192 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
193 deparse_context *context);
194 static void get_opclass_name(Oid opclass, Oid actual_datatype,
196 static Node *processIndirection(Node *node, deparse_context *context,
198 static void printSubscripts(ArrayRef *aref, deparse_context *context);
199 static char *generate_relation_name(Oid relid);
200 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes,
202 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
203 static text *string_to_text(char *str);
204 static char *flatten_reloptions(Oid relid);
206 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
210 * get_ruledef - Do it all and return a text
211 * that could be used as a statement
212 * to recreate the rule
216 pg_get_ruledef(PG_FUNCTION_ARGS)
218 Oid ruleoid = PG_GETARG_OID(0);
220 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
225 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
227 Oid ruleoid = PG_GETARG_OID(0);
228 bool pretty = PG_GETARG_BOOL(1);
231 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
232 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
237 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
247 * Do this first so that string is alloc'd in outer context not SPI's.
249 initStringInfo(&buf);
252 * Connect to SPI manager
254 if (SPI_connect() != SPI_OK_CONNECT)
255 elog(ERROR, "SPI_connect failed");
258 * On the first call prepare the plan to lookup pg_rewrite. We read
259 * pg_rewrite over the SPI manager instead of using the syscache to be
260 * checked for read access on pg_rewrite.
262 if (plan_getrulebyoid == NULL)
267 argtypes[0] = OIDOID;
268 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
270 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
271 plan_getrulebyoid = SPI_saveplan(plan);
275 * Get the pg_rewrite tuple for this rule
277 args[0] = ObjectIdGetDatum(ruleoid);
279 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
280 if (spirc != SPI_OK_SELECT)
281 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
282 if (SPI_processed != 1)
283 appendStringInfo(&buf, "-");
287 * Get the rule's definition and put it into executor's memory
289 ruletup = SPI_tuptable->vals[0];
290 rulettc = SPI_tuptable->tupdesc;
291 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
295 * Disconnect from SPI manager
297 if (SPI_finish() != SPI_OK_FINISH)
298 elog(ERROR, "SPI_finish failed");
305 * get_viewdef - Mainly the same thing, but we
306 * only return the SELECT part of a view
310 pg_get_viewdef(PG_FUNCTION_ARGS)
313 Oid viewoid = PG_GETARG_OID(0);
315 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
320 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
323 Oid viewoid = PG_GETARG_OID(0);
324 bool pretty = PG_GETARG_BOOL(1);
327 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
328 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
332 pg_get_viewdef_name(PG_FUNCTION_ARGS)
334 /* By qualified name */
335 text *viewname = PG_GETARG_TEXT_P(0);
339 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
340 viewoid = RangeVarGetRelid(viewrel, false);
342 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
347 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
349 /* By qualified name */
350 text *viewname = PG_GETARG_TEXT_P(0);
351 bool pretty = PG_GETARG_BOOL(1);
356 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
357 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
358 viewoid = RangeVarGetRelid(viewrel, false);
360 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
364 * Common code for by-OID and by-name variants of pg_get_viewdef
367 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
377 * Do this first so that string is alloc'd in outer context not SPI's.
379 initStringInfo(&buf);
382 * Connect to SPI manager
384 if (SPI_connect() != SPI_OK_CONNECT)
385 elog(ERROR, "SPI_connect failed");
388 * On the first call prepare the plan to lookup pg_rewrite. We read
389 * pg_rewrite over the SPI manager instead of using the syscache to be
390 * checked for read access on pg_rewrite.
392 if (plan_getviewrule == NULL)
397 argtypes[0] = OIDOID;
398 argtypes[1] = NAMEOID;
399 plan = SPI_prepare(query_getviewrule, 2, argtypes);
401 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
402 plan_getviewrule = SPI_saveplan(plan);
406 * Get the pg_rewrite tuple for the view's SELECT rule
408 args[0] = ObjectIdGetDatum(viewoid);
409 args[1] = PointerGetDatum(ViewSelectRuleName);
412 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
413 if (spirc != SPI_OK_SELECT)
414 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
415 if (SPI_processed != 1)
416 appendStringInfo(&buf, "Not a view");
420 * Get the rule's definition and put it into executor's memory
422 ruletup = SPI_tuptable->vals[0];
423 rulettc = SPI_tuptable->tupdesc;
424 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
428 * Disconnect from SPI manager
430 if (SPI_finish() != SPI_OK_FINISH)
431 elog(ERROR, "SPI_finish failed");
437 * get_triggerdef - Get the definition of a trigger
441 pg_get_triggerdef(PG_FUNCTION_ARGS)
443 Oid trigid = PG_GETARG_OID(0);
445 Form_pg_trigger trigrec;
454 * Fetch the pg_trigger tuple by the Oid of the trigger
456 tgrel = heap_open(TriggerRelationId, AccessShareLock);
458 ScanKeyInit(&skey[0],
459 ObjectIdAttributeNumber,
460 BTEqualStrategyNumber, F_OIDEQ,
461 ObjectIdGetDatum(trigid));
463 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
464 SnapshotNow, 1, skey);
466 ht_trig = systable_getnext(tgscan);
468 if (!HeapTupleIsValid(ht_trig))
469 elog(ERROR, "could not find tuple for trigger %u", trigid);
471 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
474 * Start the trigger definition. Note that the trigger's name should never
475 * be schema-qualified, but the trigger rel's name may be.
477 initStringInfo(&buf);
479 tgname = NameStr(trigrec->tgname);
480 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
481 trigrec->tgisconstraint ? "CONSTRAINT " : "",
482 quote_identifier(tgname));
484 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
485 appendStringInfo(&buf, "BEFORE");
487 appendStringInfo(&buf, "AFTER");
488 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
490 appendStringInfo(&buf, " INSERT");
493 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
496 appendStringInfo(&buf, " OR DELETE");
498 appendStringInfo(&buf, " DELETE");
501 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
504 appendStringInfo(&buf, " OR UPDATE");
506 appendStringInfo(&buf, " UPDATE");
508 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
511 appendStringInfo(&buf, " OR TRUNCATE");
513 appendStringInfo(&buf, " TRUNCATE");
515 appendStringInfo(&buf, " ON %s ",
516 generate_relation_name(trigrec->tgrelid));
518 if (trigrec->tgisconstraint)
520 if (trigrec->tgconstrrelid != InvalidOid)
521 appendStringInfo(&buf, "FROM %s ",
522 generate_relation_name(trigrec->tgconstrrelid));
523 if (!trigrec->tgdeferrable)
524 appendStringInfo(&buf, "NOT ");
525 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
526 if (trigrec->tginitdeferred)
527 appendStringInfo(&buf, "DEFERRED ");
529 appendStringInfo(&buf, "IMMEDIATE ");
533 if (TRIGGER_FOR_ROW(trigrec->tgtype))
534 appendStringInfo(&buf, "FOR EACH ROW ");
536 appendStringInfo(&buf, "FOR EACH STATEMENT ");
538 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
539 generate_function_name(trigrec->tgfoid, 0, NULL, NULL));
541 if (trigrec->tgnargs > 0)
548 val = DatumGetByteaP(fastgetattr(ht_trig,
549 Anum_pg_trigger_tgargs,
550 tgrel->rd_att, &isnull));
552 elog(ERROR, "tgargs is null for trigger %u", trigid);
553 p = (char *) VARDATA(val);
554 for (i = 0; i < trigrec->tgnargs; i++)
557 appendStringInfo(&buf, ", ");
558 simple_quote_literal(&buf, p);
559 /* advance p to next string embedded in tgargs */
566 /* We deliberately do not put semi-colon at end */
567 appendStringInfo(&buf, ")");
570 systable_endscan(tgscan);
572 heap_close(tgrel, AccessShareLock);
574 PG_RETURN_TEXT_P(string_to_text(buf.data));
578 * get_indexdef - Get the definition of an index
580 * In the extended version, there is a colno argument as well as pretty bool.
581 * if colno == 0, we want a complete index definition.
582 * if colno > 0, we only want the Nth index key's variable or expression.
584 * Note that the SQL-function versions of this omit any info about the
585 * index tablespace; this is intentional because pg_dump wants it that way.
586 * However pg_get_indexdef_string() includes index tablespace if not default.
590 pg_get_indexdef(PG_FUNCTION_ARGS)
592 Oid indexrelid = PG_GETARG_OID(0);
594 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
599 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
601 Oid indexrelid = PG_GETARG_OID(0);
602 int32 colno = PG_GETARG_INT32(1);
603 bool pretty = PG_GETARG_BOOL(2);
606 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
607 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
608 false, prettyFlags)));
611 /* Internal version that returns a palloc'd C string */
613 pg_get_indexdef_string(Oid indexrelid)
615 return pg_get_indexdef_worker(indexrelid, 0, true, 0);
619 pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
625 Form_pg_index idxrec;
626 Form_pg_class idxrelrec;
629 ListCell *indexpr_item;
635 Datum indoptionDatum;
638 int2vector *indoption;
644 * Fetch the pg_index tuple by the Oid of the index
646 ht_idx = SearchSysCache(INDEXRELID,
647 ObjectIdGetDatum(indexrelid),
649 if (!HeapTupleIsValid(ht_idx))
650 elog(ERROR, "cache lookup failed for index %u", indexrelid);
651 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
653 indrelid = idxrec->indrelid;
654 Assert(indexrelid == idxrec->indexrelid);
656 /* Must get indclass and indoption the hard way */
657 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
658 Anum_pg_index_indclass, &isnull);
660 indclass = (oidvector *) DatumGetPointer(indclassDatum);
661 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
662 Anum_pg_index_indoption, &isnull);
664 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
667 * Fetch the pg_class tuple of the index relation
669 ht_idxrel = SearchSysCache(RELOID,
670 ObjectIdGetDatum(indexrelid),
672 if (!HeapTupleIsValid(ht_idxrel))
673 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
674 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
677 * Fetch the pg_am tuple of the index' access method
679 ht_am = SearchSysCache(AMOID,
680 ObjectIdGetDatum(idxrelrec->relam),
682 if (!HeapTupleIsValid(ht_am))
683 elog(ERROR, "cache lookup failed for access method %u",
685 amrec = (Form_pg_am) GETSTRUCT(ht_am);
688 * Get the index expressions, if any. (NOTE: we do not use the relcache
689 * versions of the expressions and predicate, because we want to display
690 * non-const-folded expressions.)
692 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
698 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
699 Anum_pg_index_indexprs, &isnull);
701 exprsString = TextDatumGetCString(exprsDatum);
702 indexprs = (List *) stringToNode(exprsString);
708 indexpr_item = list_head(indexprs);
710 context = deparse_context_for(get_rel_name(indrelid), indrelid);
713 * Start the index definition. Note that the index's name should never be
714 * schema-qualified, but the indexed rel's name may be.
716 initStringInfo(&buf);
719 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
720 idxrec->indisunique ? "UNIQUE " : "",
721 quote_identifier(NameStr(idxrelrec->relname)),
722 generate_relation_name(indrelid),
723 quote_identifier(NameStr(amrec->amname)));
726 * Report the indexed attributes
729 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
731 AttrNumber attnum = idxrec->indkey.values[keyno];
732 int16 opt = indoption->values[keyno];
735 appendStringInfoString(&buf, sep);
740 /* Simple index column */
743 attname = get_relid_attribute_name(indrelid, attnum);
744 if (!colno || colno == keyno + 1)
745 appendStringInfoString(&buf, quote_identifier(attname));
746 keycoltype = get_atttype(indrelid, attnum);
750 /* expressional index */
753 if (indexpr_item == NULL)
754 elog(ERROR, "too few entries in indexprs list");
755 indexkey = (Node *) lfirst(indexpr_item);
756 indexpr_item = lnext(indexpr_item);
758 str = deparse_expression_pretty(indexkey, context, false, false,
760 if (!colno || colno == keyno + 1)
762 /* Need parens if it's not a bare function call */
763 if (indexkey && IsA(indexkey, FuncExpr) &&
764 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
765 appendStringInfoString(&buf, str);
767 appendStringInfo(&buf, "(%s)", str);
769 keycoltype = exprType(indexkey);
772 /* Provide decoration only in the colno=0 case */
775 /* Add the operator class name, if not default */
776 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
778 /* Add options if relevant */
779 if (amrec->amcanorder)
781 /* if it supports sort ordering, report DESC and NULLS opts */
782 if (opt & INDOPTION_DESC)
784 appendStringInfo(&buf, " DESC");
785 /* NULLS FIRST is the default in this case */
786 if (!(opt & INDOPTION_NULLS_FIRST))
787 appendStringInfo(&buf, " NULLS LAST");
791 if (opt & INDOPTION_NULLS_FIRST)
792 appendStringInfo(&buf, " NULLS FIRST");
800 appendStringInfoChar(&buf, ')');
803 * If it has options, append "WITH (options)"
805 str = flatten_reloptions(indexrelid);
808 appendStringInfo(&buf, " WITH (%s)", str);
813 * If it's in a nondefault tablespace, say so, but only if requested
819 tblspc = get_rel_tablespace(indexrelid);
820 if (OidIsValid(tblspc))
821 appendStringInfo(&buf, " TABLESPACE %s",
822 quote_identifier(get_tablespace_name(tblspc)));
826 * If it's a partial index, decompile and append the predicate
828 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
835 /* Convert text string to node tree */
836 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
837 Anum_pg_index_indpred, &isnull);
839 predString = TextDatumGetCString(predDatum);
840 node = (Node *) stringToNode(predString);
844 str = deparse_expression_pretty(node, context, false, false,
846 appendStringInfo(&buf, " WHERE %s", str);
851 ReleaseSysCache(ht_idx);
852 ReleaseSysCache(ht_idxrel);
853 ReleaseSysCache(ht_am);
860 * pg_get_constraintdef
862 * Returns the definition for the constraint, ie, everything that needs to
863 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
866 pg_get_constraintdef(PG_FUNCTION_ARGS)
868 Oid constraintId = PG_GETARG_OID(0);
870 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
875 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
877 Oid constraintId = PG_GETARG_OID(0);
878 bool pretty = PG_GETARG_BOOL(1);
881 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
882 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
883 false, prettyFlags)));
886 /* Internal version that returns a palloc'd C string */
888 pg_get_constraintdef_string(Oid constraintId)
890 return pg_get_constraintdef_worker(constraintId, true, 0);
894 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
898 Form_pg_constraint conForm;
901 tup = SearchSysCache(CONSTROID,
902 ObjectIdGetDatum(constraintId),
904 if (!HeapTupleIsValid(tup)) /* should not happen */
905 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
906 conForm = (Form_pg_constraint) GETSTRUCT(tup);
908 initStringInfo(&buf);
910 if (fullCommand && OidIsValid(conForm->conrelid))
912 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
913 generate_relation_name(conForm->conrelid),
914 quote_identifier(NameStr(conForm->conname)));
917 switch (conForm->contype)
919 case CONSTRAINT_FOREIGN:
925 /* Start off the constraint definition */
926 appendStringInfo(&buf, "FOREIGN KEY (");
928 /* Fetch and build referencing-column list */
929 val = SysCacheGetAttr(CONSTROID, tup,
930 Anum_pg_constraint_conkey, &isnull);
932 elog(ERROR, "null conkey for constraint %u",
935 decompile_column_index_array(val, conForm->conrelid, &buf);
937 /* add foreign relation name */
938 appendStringInfo(&buf, ") REFERENCES %s(",
939 generate_relation_name(conForm->confrelid));
941 /* Fetch and build referenced-column list */
942 val = SysCacheGetAttr(CONSTROID, tup,
943 Anum_pg_constraint_confkey, &isnull);
945 elog(ERROR, "null confkey for constraint %u",
948 decompile_column_index_array(val, conForm->confrelid, &buf);
950 appendStringInfo(&buf, ")");
953 switch (conForm->confmatchtype)
955 case FKCONSTR_MATCH_FULL:
956 string = " MATCH FULL";
958 case FKCONSTR_MATCH_PARTIAL:
959 string = " MATCH PARTIAL";
961 case FKCONSTR_MATCH_UNSPECIFIED:
965 elog(ERROR, "unrecognized confmatchtype: %d",
966 conForm->confmatchtype);
967 string = ""; /* keep compiler quiet */
970 appendStringInfoString(&buf, string);
972 /* Add ON UPDATE and ON DELETE clauses, if needed */
973 switch (conForm->confupdtype)
975 case FKCONSTR_ACTION_NOACTION:
976 string = NULL; /* suppress default */
978 case FKCONSTR_ACTION_RESTRICT:
981 case FKCONSTR_ACTION_CASCADE:
984 case FKCONSTR_ACTION_SETNULL:
987 case FKCONSTR_ACTION_SETDEFAULT:
988 string = "SET DEFAULT";
991 elog(ERROR, "unrecognized confupdtype: %d",
992 conForm->confupdtype);
993 string = NULL; /* keep compiler quiet */
997 appendStringInfo(&buf, " ON UPDATE %s", string);
999 switch (conForm->confdeltype)
1001 case FKCONSTR_ACTION_NOACTION:
1002 string = NULL; /* suppress default */
1004 case FKCONSTR_ACTION_RESTRICT:
1005 string = "RESTRICT";
1007 case FKCONSTR_ACTION_CASCADE:
1010 case FKCONSTR_ACTION_SETNULL:
1011 string = "SET NULL";
1013 case FKCONSTR_ACTION_SETDEFAULT:
1014 string = "SET DEFAULT";
1017 elog(ERROR, "unrecognized confdeltype: %d",
1018 conForm->confdeltype);
1019 string = NULL; /* keep compiler quiet */
1023 appendStringInfo(&buf, " ON DELETE %s", string);
1025 if (conForm->condeferrable)
1026 appendStringInfo(&buf, " DEFERRABLE");
1027 if (conForm->condeferred)
1028 appendStringInfo(&buf, " INITIALLY DEFERRED");
1032 case CONSTRAINT_PRIMARY:
1033 case CONSTRAINT_UNIQUE:
1039 /* Start off the constraint definition */
1040 if (conForm->contype == CONSTRAINT_PRIMARY)
1041 appendStringInfo(&buf, "PRIMARY KEY (");
1043 appendStringInfo(&buf, "UNIQUE (");
1045 /* Fetch and build target column list */
1046 val = SysCacheGetAttr(CONSTROID, tup,
1047 Anum_pg_constraint_conkey, &isnull);
1049 elog(ERROR, "null conkey for constraint %u",
1052 decompile_column_index_array(val, conForm->conrelid, &buf);
1054 appendStringInfo(&buf, ")");
1056 indexId = get_constraint_index(constraintId);
1058 /* XXX why do we only print these bits if fullCommand? */
1059 if (fullCommand && OidIsValid(indexId))
1061 char *options = flatten_reloptions(indexId);
1066 appendStringInfo(&buf, " WITH (%s)", options);
1070 tblspc = get_rel_tablespace(indexId);
1071 if (OidIsValid(tblspc))
1072 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1073 quote_identifier(get_tablespace_name(tblspc)));
1078 case CONSTRAINT_CHECK:
1087 /* Fetch constraint expression in parsetree form */
1088 val = SysCacheGetAttr(CONSTROID, tup,
1089 Anum_pg_constraint_conbin, &isnull);
1091 elog(ERROR, "null conbin for constraint %u",
1094 conbin = TextDatumGetCString(val);
1095 expr = stringToNode(conbin);
1097 /* Set up deparsing context for Var nodes in constraint */
1098 if (conForm->conrelid != InvalidOid)
1100 /* relation constraint */
1101 context = deparse_context_for(get_rel_name(conForm->conrelid),
1106 /* domain constraint --- can't have Vars */
1110 consrc = deparse_expression_pretty(expr, context, false, false,
1114 * Now emit the constraint definition. There are cases where
1115 * the constraint expression will be fully parenthesized and
1116 * we don't need the outer parens ... but there are other
1117 * cases where we do need 'em. Be conservative for now.
1119 * Note that simply checking for leading '(' and trailing ')'
1120 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1122 appendStringInfo(&buf, "CHECK (%s)", consrc);
1127 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1132 ReleaseSysCache(tup);
1139 * Convert an int16[] Datum into a comma-separated list of column names
1140 * for the indicated relation; append the list to buf.
1143 decompile_column_index_array(Datum column_index_array, Oid relId,
1150 /* Extract data from array of int16 */
1151 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1152 INT2OID, 2, true, 's',
1153 &keys, NULL, &nKeys);
1155 for (j = 0; j < nKeys; j++)
1159 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1162 appendStringInfoString(buf, quote_identifier(colName));
1164 appendStringInfo(buf, ", %s", quote_identifier(colName));
1170 * get_expr - Decompile an expression tree
1172 * Input: an expression tree in nodeToString form, and a relation OID
1174 * Output: reverse-listed expression
1176 * Currently, the expression can only refer to a single relation, namely
1177 * the one specified by the second parameter. This is sufficient for
1178 * partial indexes, column default expressions, etc.
1182 pg_get_expr(PG_FUNCTION_ARGS)
1184 text *expr = PG_GETARG_TEXT_P(0);
1185 Oid relid = PG_GETARG_OID(1);
1188 /* Get the name for the relation */
1189 relname = get_rel_name(relid);
1190 if (relname == NULL)
1191 PG_RETURN_NULL(); /* should we raise an error? */
1193 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1197 pg_get_expr_ext(PG_FUNCTION_ARGS)
1199 text *expr = PG_GETARG_TEXT_P(0);
1200 Oid relid = PG_GETARG_OID(1);
1201 bool pretty = PG_GETARG_BOOL(2);
1205 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1207 /* Get the name for the relation */
1208 relname = get_rel_name(relid);
1209 if (relname == NULL)
1210 PG_RETURN_NULL(); /* should we raise an error? */
1212 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1216 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1223 /* Convert input TEXT object to C string */
1224 exprstr = text_to_cstring(expr);
1226 /* Convert expression to node tree */
1227 node = (Node *) stringToNode(exprstr);
1230 context = deparse_context_for(relname, relid);
1231 str = deparse_expression_pretty(node, context, false, false,
1241 * get_userbyid - Get a user name by roleid and
1242 * fallback to 'unknown (OID=n)'
1246 pg_get_userbyid(PG_FUNCTION_ARGS)
1248 Oid roleid = PG_GETARG_OID(0);
1251 Form_pg_authid role_rec;
1254 * Allocate space for the result
1256 result = (Name) palloc(NAMEDATALEN);
1257 memset(NameStr(*result), 0, NAMEDATALEN);
1260 * Get the pg_authid entry and print the result
1262 roletup = SearchSysCache(AUTHOID,
1263 ObjectIdGetDatum(roleid),
1265 if (HeapTupleIsValid(roletup))
1267 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1268 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1269 ReleaseSysCache(roletup);
1272 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1274 PG_RETURN_NAME(result);
1279 * pg_get_serial_sequence
1280 * Get the name of the sequence used by a serial column,
1281 * formatted suitably for passing to setval, nextval or currval.
1282 * First parameter is not treated as double-quoted, second parameter
1283 * is --- see documentation for reason.
1286 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1288 text *tablename = PG_GETARG_TEXT_P(0);
1289 text *columnname = PG_GETARG_TEXT_PP(1);
1294 Oid sequenceId = InvalidOid;
1300 /* Get the OID of the table */
1301 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1302 tableOid = RangeVarGetRelid(tablerv, false);
1304 /* Get the number of the column */
1305 column = text_to_cstring(columnname);
1307 attnum = get_attnum(tableOid, column);
1308 if (attnum == InvalidAttrNumber)
1310 (errcode(ERRCODE_UNDEFINED_COLUMN),
1311 errmsg("column \"%s\" of relation \"%s\" does not exist",
1312 column, tablerv->relname)));
1314 /* Search the dependency table for the dependent sequence */
1315 depRel = heap_open(DependRelationId, AccessShareLock);
1317 ScanKeyInit(&key[0],
1318 Anum_pg_depend_refclassid,
1319 BTEqualStrategyNumber, F_OIDEQ,
1320 ObjectIdGetDatum(RelationRelationId));
1321 ScanKeyInit(&key[1],
1322 Anum_pg_depend_refobjid,
1323 BTEqualStrategyNumber, F_OIDEQ,
1324 ObjectIdGetDatum(tableOid));
1325 ScanKeyInit(&key[2],
1326 Anum_pg_depend_refobjsubid,
1327 BTEqualStrategyNumber, F_INT4EQ,
1328 Int32GetDatum(attnum));
1330 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1331 SnapshotNow, 3, key);
1333 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1335 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1338 * We assume any auto dependency of a sequence on a column must be
1339 * what we are looking for. (We need the relkind test because indexes
1340 * can also have auto dependencies on columns.)
1342 if (deprec->classid == RelationRelationId &&
1343 deprec->objsubid == 0 &&
1344 deprec->deptype == DEPENDENCY_AUTO &&
1345 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1347 sequenceId = deprec->objid;
1352 systable_endscan(scan);
1353 heap_close(depRel, AccessShareLock);
1355 if (OidIsValid(sequenceId))
1358 Form_pg_class classtuple;
1362 /* Get the sequence's pg_class entry */
1363 classtup = SearchSysCache(RELOID,
1364 ObjectIdGetDatum(sequenceId),
1366 if (!HeapTupleIsValid(classtup))
1367 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1368 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1370 /* Get the namespace */
1371 nspname = get_namespace_name(classtuple->relnamespace);
1373 elog(ERROR, "cache lookup failed for namespace %u",
1374 classtuple->relnamespace);
1376 /* And construct the result string */
1377 result = quote_qualified_identifier(nspname,
1378 NameStr(classtuple->relname));
1380 ReleaseSysCache(classtup);
1382 PG_RETURN_TEXT_P(string_to_text(result));
1390 * pg_get_functiondef
1391 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1392 * the specified function.
1395 pg_get_functiondef(PG_FUNCTION_ARGS)
1397 Oid funcid = PG_GETARG_OID(0);
1403 Form_pg_language lang;
1412 initStringInfo(&buf);
1414 /* Look up the function */
1415 proctup = SearchSysCache(PROCOID,
1416 ObjectIdGetDatum(funcid),
1418 if (!HeapTupleIsValid(proctup))
1419 elog(ERROR, "cache lookup failed for function %u", funcid);
1420 proc = (Form_pg_proc) GETSTRUCT(proctup);
1421 name = NameStr(proc->proname);
1425 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1426 errmsg("\"%s\" is an aggregate function", name)));
1428 /* Need its pg_language tuple for the language name */
1429 langtup = SearchSysCache(LANGOID,
1430 ObjectIdGetDatum(proc->prolang),
1432 if (!HeapTupleIsValid(langtup))
1433 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1434 lang = (Form_pg_language) GETSTRUCT(langtup);
1437 * We always qualify the function name, to ensure the right function
1440 nsp = get_namespace_name(proc->pronamespace);
1441 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1442 quote_qualified_identifier(nsp, name));
1443 (void) print_function_arguments(&buf, proctup, false);
1444 appendStringInfoString(&buf, ")\n RETURNS ");
1445 print_function_rettype(&buf, proctup);
1446 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1447 quote_identifier(NameStr(lang->lanname)));
1449 /* Emit some miscellaneous options on one line */
1452 switch (proc->provolatile)
1454 case PROVOLATILE_IMMUTABLE:
1455 appendStringInfoString(&buf, " IMMUTABLE");
1457 case PROVOLATILE_STABLE:
1458 appendStringInfoString(&buf, " STABLE");
1460 case PROVOLATILE_VOLATILE:
1463 if (proc->proisstrict)
1464 appendStringInfoString(&buf, " STRICT");
1465 if (proc->prosecdef)
1466 appendStringInfoString(&buf, " SECURITY DEFINER");
1468 /* This code for the default cost and rows should match functioncmds.c */
1469 if (proc->prolang == INTERNALlanguageId ||
1470 proc->prolang == ClanguageId)
1474 if (proc->procost != procost)
1475 appendStringInfo(&buf, " COST %g", proc->procost);
1477 if (proc->prorows > 0 && proc->prorows != 1000)
1478 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1480 if (oldlen != buf.len)
1481 appendStringInfoChar(&buf, '\n');
1483 /* Emit any proconfig options, one per line */
1484 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1487 ArrayType *a = DatumGetArrayTypeP(tmp);
1490 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1491 Assert(ARR_NDIM(a) == 1);
1492 Assert(ARR_LBOUND(a)[0] == 1);
1494 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1498 d = array_ref(a, 1, &i,
1499 -1 /* varlenarray */ ,
1500 -1 /* TEXT's typlen */ ,
1501 false /* TEXT's typbyval */ ,
1502 'i' /* TEXT's typalign */ ,
1506 char *configitem = TextDatumGetCString(d);
1509 pos = strchr(configitem, '=');
1514 appendStringInfo(&buf, " SET %s TO ",
1515 quote_identifier(configitem));
1518 * Some GUC variable names are 'LIST' type and hence must not
1521 if (pg_strcasecmp(configitem, "DateStyle") == 0
1522 || pg_strcasecmp(configitem, "search_path") == 0)
1523 appendStringInfoString(&buf, pos);
1525 simple_quote_literal(&buf, pos);
1526 appendStringInfoChar(&buf, '\n');
1531 /* And finally the function definition ... */
1532 appendStringInfoString(&buf, "AS ");
1534 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1537 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1538 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1541 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1543 elog(ERROR, "null prosrc");
1544 prosrc = TextDatumGetCString(tmp);
1547 * We always use dollar quoting. Figure out a suitable delimiter.
1549 * Since the user is likely to be editing the function body string,
1550 * we shouldn't use a short delimiter that he might easily create a
1551 * conflict with. Hence prefer "$function$", but extend if needed.
1553 initStringInfo(&dq);
1554 appendStringInfoString(&dq, "$function");
1555 while (strstr(prosrc, dq.data) != NULL)
1556 appendStringInfoChar(&dq, 'x');
1557 appendStringInfoChar(&dq, '$');
1559 appendStringInfoString(&buf, dq.data);
1560 appendStringInfoString(&buf, prosrc);
1561 appendStringInfoString(&buf, dq.data);
1563 appendStringInfoString(&buf, "\n");
1565 ReleaseSysCache(langtup);
1566 ReleaseSysCache(proctup);
1568 PG_RETURN_TEXT_P(string_to_text(buf.data));
1572 * pg_get_function_arguments
1573 * Get a nicely-formatted list of arguments for a function.
1574 * This is everything that would go between the parentheses in
1578 pg_get_function_arguments(PG_FUNCTION_ARGS)
1580 Oid funcid = PG_GETARG_OID(0);
1584 initStringInfo(&buf);
1586 proctup = SearchSysCache(PROCOID,
1587 ObjectIdGetDatum(funcid),
1589 if (!HeapTupleIsValid(proctup))
1590 elog(ERROR, "cache lookup failed for function %u", funcid);
1592 (void) print_function_arguments(&buf, proctup, false);
1594 ReleaseSysCache(proctup);
1596 PG_RETURN_TEXT_P(string_to_text(buf.data));
1600 * pg_get_function_result
1601 * Get a nicely-formatted version of the result type of a function.
1602 * This is what would appear after RETURNS in CREATE FUNCTION.
1605 pg_get_function_result(PG_FUNCTION_ARGS)
1607 Oid funcid = PG_GETARG_OID(0);
1611 initStringInfo(&buf);
1613 proctup = SearchSysCache(PROCOID,
1614 ObjectIdGetDatum(funcid),
1616 if (!HeapTupleIsValid(proctup))
1617 elog(ERROR, "cache lookup failed for function %u", funcid);
1619 print_function_rettype(&buf, proctup);
1621 ReleaseSysCache(proctup);
1623 PG_RETURN_TEXT_P(string_to_text(buf.data));
1627 * Guts of pg_get_function_result: append the function's return type
1628 * to the specified buffer.
1631 print_function_rettype(StringInfo buf, HeapTuple proctup)
1633 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1635 StringInfoData rbuf;
1637 initStringInfo(&rbuf);
1639 if (proc->proretset)
1641 /* It might be a table function; try to print the arguments */
1642 appendStringInfoString(&rbuf, "TABLE(");
1643 ntabargs = print_function_arguments(&rbuf, proctup, true);
1645 appendStringInfoString(&rbuf, ")");
1647 resetStringInfo(&rbuf);
1652 /* Not a table function, so do the normal thing */
1653 if (proc->proretset)
1654 appendStringInfoString(&rbuf, "SETOF ");
1655 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1658 appendStringInfoString(buf, rbuf.data);
1662 * Common code for pg_get_function_arguments and pg_get_function_result:
1663 * append the desired subset of arguments to buf. We print only TABLE
1664 * arguments when print_table_args is true, and all the others when it's false.
1665 * Function return value is the number of arguments printed.
1668 print_function_arguments(StringInfo buf, HeapTuple proctup,
1669 bool print_table_args)
1678 numargs = get_func_arg_info(proctup,
1679 &argtypes, &argnames, &argmodes);
1682 for (i = 0; i < numargs; i++)
1684 Oid argtype = argtypes[i];
1685 char *argname = argnames ? argnames[i] : NULL;
1686 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1687 const char *modename;
1689 if (print_table_args != (argmode == PROARGMODE_TABLE))
1697 case PROARGMODE_INOUT:
1698 modename = "INOUT ";
1700 case PROARGMODE_OUT:
1703 case PROARGMODE_VARIADIC:
1704 modename = "VARIADIC ";
1706 case PROARGMODE_TABLE:
1710 elog(ERROR, "invalid parameter mode '%c'", argmode);
1711 modename = NULL; /* keep compiler quiet */
1715 appendStringInfoString(buf, ", ");
1716 appendStringInfoString(buf, modename);
1717 if (argname && argname[0])
1718 appendStringInfo(buf, "%s ", argname);
1719 appendStringInfoString(buf, format_type_be(argtype));
1728 * deparse_expression - General utility for deparsing expressions
1730 * calls deparse_expression_pretty with all prettyPrinting disabled
1733 deparse_expression(Node *expr, List *dpcontext,
1734 bool forceprefix, bool showimplicit)
1736 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1737 showimplicit, 0, 0);
1741 * deparse_expression_pretty - General utility for deparsing expressions
1743 * expr is the node tree to be deparsed. It must be a transformed expression
1744 * tree (ie, not the raw output of gram.y).
1746 * dpcontext is a list of deparse_namespace nodes representing the context
1747 * for interpreting Vars in the node tree.
1749 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1751 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1753 * tries to pretty up the output according to prettyFlags and startIndent.
1755 * The result is a palloc'd string.
1759 deparse_expression_pretty(Node *expr, List *dpcontext,
1760 bool forceprefix, bool showimplicit,
1761 int prettyFlags, int startIndent)
1764 deparse_context context;
1766 initStringInfo(&buf);
1768 context.namespaces = dpcontext;
1769 context.varprefix = forceprefix;
1770 context.prettyFlags = prettyFlags;
1771 context.indentLevel = startIndent;
1773 get_rule_expr(expr, &context, showimplicit);
1779 * deparse_context_for - Build deparse context for a single relation
1781 * Given the reference name (alias) and OID of a relation, build deparsing
1782 * context for an expression referencing only that relation (as varno 1,
1783 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1787 deparse_context_for(const char *aliasname, Oid relid)
1789 deparse_namespace *dpns;
1792 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1794 /* Build a minimal RTE for the rel */
1795 rte = makeNode(RangeTblEntry);
1796 rte->rtekind = RTE_RELATION;
1798 rte->eref = makeAlias(aliasname, NIL);
1800 rte->inFromCl = true;
1802 /* Build one-element rtable */
1803 dpns->rtable = list_make1(rte);
1804 dpns->outer_plan = dpns->inner_plan = NULL;
1806 /* Return a one-deep namespace stack */
1807 return list_make1(dpns);
1811 * deparse_context_for_plan - Build deparse context for a plan node
1813 * When deparsing an expression in a Plan tree, we might have to resolve
1814 * OUTER or INNER references. Pass the plan nodes whose targetlists define
1815 * such references, or NULL when none are expected. (outer_plan and
1816 * inner_plan really ought to be declared as "Plan *", but we use "Node *"
1817 * to avoid having to include plannodes.h in builtins.h.)
1819 * As a special case, when deparsing a SubqueryScan plan, pass the subplan
1820 * as inner_plan (there won't be any regular innerPlan() in this case).
1822 * The plan's rangetable list must also be passed. We actually prefer to use
1823 * the rangetable to resolve simple Vars, but the subplan inputs are needed
1824 * for Vars that reference expressions computed in subplan target lists.
1827 deparse_context_for_plan(Node *outer_plan, Node *inner_plan,
1830 deparse_namespace *dpns;
1832 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1834 dpns->rtable = rtable;
1835 dpns->outer_plan = (Plan *) outer_plan;
1836 dpns->inner_plan = (Plan *) inner_plan;
1838 /* Return a one-deep namespace stack */
1839 return list_make1(dpns);
1843 * make_ruledef - reconstruct the CREATE RULE command
1844 * for a given pg_rewrite tuple
1848 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1858 List *actions = NIL;
1864 * Get the attribute values from the rules tuple
1866 fno = SPI_fnumber(rulettc, "rulename");
1867 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1869 rulename = NameStr(*(DatumGetName(dat)));
1871 fno = SPI_fnumber(rulettc, "ev_type");
1872 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1874 ev_type = DatumGetChar(dat);
1876 fno = SPI_fnumber(rulettc, "ev_class");
1877 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1879 ev_class = DatumGetObjectId(dat);
1881 fno = SPI_fnumber(rulettc, "ev_attr");
1882 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1884 ev_attr = DatumGetInt16(dat);
1886 fno = SPI_fnumber(rulettc, "is_instead");
1887 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1889 is_instead = DatumGetBool(dat);
1891 /* these could be nulls */
1892 fno = SPI_fnumber(rulettc, "ev_qual");
1893 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1895 fno = SPI_fnumber(rulettc, "ev_action");
1896 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1897 if (ev_action != NULL)
1898 actions = (List *) stringToNode(ev_action);
1901 * Build the rules definition text
1903 appendStringInfo(buf, "CREATE RULE %s AS",
1904 quote_identifier(rulename));
1906 if (prettyFlags & PRETTYFLAG_INDENT)
1907 appendStringInfoString(buf, "\n ON ");
1909 appendStringInfoString(buf, " ON ");
1911 /* The event the rule is fired for */
1915 appendStringInfo(buf, "SELECT");
1919 appendStringInfo(buf, "UPDATE");
1923 appendStringInfo(buf, "INSERT");
1927 appendStringInfo(buf, "DELETE");
1932 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1933 errmsg("rule \"%s\" has unsupported event type %d",
1934 rulename, ev_type)));
1938 /* The relation the rule is fired on */
1939 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class));
1941 appendStringInfo(buf, ".%s",
1942 quote_identifier(get_relid_attribute_name(ev_class,
1945 /* If the rule has an event qualification, add it */
1946 if (ev_qual == NULL)
1948 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
1952 deparse_context context;
1953 deparse_namespace dpns;
1955 if (prettyFlags & PRETTYFLAG_INDENT)
1956 appendStringInfoString(buf, "\n ");
1957 appendStringInfo(buf, " WHERE ");
1959 qual = stringToNode(ev_qual);
1962 * We need to make a context for recognizing any Vars in the qual
1963 * (which can only be references to OLD and NEW). Use the rtable of
1964 * the first query in the action list for this purpose.
1966 query = (Query *) linitial(actions);
1969 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
1970 * into the SELECT, and that's what we need to look at. (Ugly kluge
1971 * ... try to fix this when we redesign querytrees.)
1973 query = getInsertSelectQuery(query, NULL);
1975 /* Must acquire locks right away; see notes in get_query_def() */
1976 AcquireRewriteLocks(query);
1979 context.namespaces = list_make1(&dpns);
1980 context.varprefix = (list_length(query->rtable) != 1);
1981 context.prettyFlags = prettyFlags;
1982 context.indentLevel = PRETTYINDENT_STD;
1983 dpns.rtable = query->rtable;
1984 dpns.outer_plan = dpns.inner_plan = NULL;
1986 get_rule_expr(qual, &context, false);
1989 appendStringInfo(buf, " DO ");
1991 /* The INSTEAD keyword (if so) */
1993 appendStringInfo(buf, "INSTEAD ");
1995 /* Finally the rules actions */
1996 if (list_length(actions) > 1)
2001 appendStringInfo(buf, "(");
2002 foreach(action, actions)
2004 query = (Query *) lfirst(action);
2005 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2007 appendStringInfo(buf, ";\n");
2009 appendStringInfo(buf, "; ");
2011 appendStringInfo(buf, ");");
2013 else if (list_length(actions) == 0)
2015 appendStringInfo(buf, "NOTHING;");
2021 query = (Query *) linitial(actions);
2022 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2023 appendStringInfo(buf, ";");
2029 * make_viewdef - reconstruct the SELECT part of a
2034 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2044 List *actions = NIL;
2045 Relation ev_relation;
2050 * Get the attribute values from the rules tuple
2052 fno = SPI_fnumber(rulettc, "ev_type");
2053 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2055 fno = SPI_fnumber(rulettc, "ev_class");
2056 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2058 fno = SPI_fnumber(rulettc, "ev_attr");
2059 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2061 fno = SPI_fnumber(rulettc, "is_instead");
2062 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2064 fno = SPI_fnumber(rulettc, "ev_qual");
2065 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2067 fno = SPI_fnumber(rulettc, "ev_action");
2068 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2069 if (ev_action != NULL)
2070 actions = (List *) stringToNode(ev_action);
2072 if (list_length(actions) != 1)
2074 appendStringInfo(buf, "Not a view");
2078 query = (Query *) linitial(actions);
2080 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2081 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2083 appendStringInfo(buf, "Not a view");
2087 ev_relation = heap_open(ev_class, AccessShareLock);
2089 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2091 appendStringInfo(buf, ";");
2093 heap_close(ev_relation, AccessShareLock);
2098 * get_query_def - Parse back one query parsetree
2100 * If resultDesc is not NULL, then it is the output tuple descriptor for
2101 * the view represented by a SELECT query.
2105 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2106 TupleDesc resultDesc, int prettyFlags, int startIndent)
2108 deparse_context context;
2109 deparse_namespace dpns;
2112 * Before we begin to examine the query, acquire locks on referenced
2113 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2114 * consistent results. Note we assume it's OK to scribble on the passed
2117 AcquireRewriteLocks(query);
2120 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2121 context.varprefix = (parentnamespace != NIL ||
2122 list_length(query->rtable) != 1);
2123 context.prettyFlags = prettyFlags;
2124 context.indentLevel = startIndent;
2126 dpns.rtable = query->rtable;
2127 dpns.outer_plan = dpns.inner_plan = NULL;
2129 switch (query->commandType)
2132 get_select_query_def(query, &context, resultDesc);
2136 get_update_query_def(query, &context);
2140 get_insert_query_def(query, &context);
2144 get_delete_query_def(query, &context);
2148 appendStringInfo(buf, "NOTHING");
2152 get_utility_query_def(query, &context);
2156 elog(ERROR, "unrecognized query command type: %d",
2157 query->commandType);
2163 * get_values_def - Parse back a VALUES list
2167 get_values_def(List *values_lists, deparse_context *context)
2169 StringInfo buf = context->buf;
2170 bool first_list = true;
2173 appendStringInfoString(buf, "VALUES ");
2175 foreach(vtl, values_lists)
2177 List *sublist = (List *) lfirst(vtl);
2178 bool first_col = true;
2184 appendStringInfoString(buf, ", ");
2186 appendStringInfoChar(buf, '(');
2187 foreach(lc, sublist)
2189 Node *col = (Node *) lfirst(lc);
2194 appendStringInfoChar(buf, ',');
2197 * Strip any top-level nodes representing indirection assignments,
2198 * then print the result.
2200 get_rule_expr(processIndirection(col, context, false),
2203 appendStringInfoChar(buf, ')');
2208 * get_select_query_def - Parse back a SELECT parsetree
2212 get_select_query_def(Query *query, deparse_context *context,
2213 TupleDesc resultDesc)
2215 StringInfo buf = context->buf;
2221 * If the Query node has a setOperations tree, then it's the top level of
2222 * a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT fields are
2223 * interesting in the top query itself.
2225 if (query->setOperations)
2227 get_setop_query(query->setOperations, query, context, resultDesc);
2228 /* ORDER BY clauses must be simple in this case */
2233 get_basic_select_query(query, context, resultDesc);
2234 force_colno = false;
2237 /* Add the ORDER BY clause if given */
2238 if (query->sortClause != NIL)
2240 appendContextKeyword(context, " ORDER BY ",
2241 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2243 foreach(l, query->sortClause)
2245 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2248 TypeCacheEntry *typentry;
2250 appendStringInfoString(buf, sep);
2251 sortexpr = get_rule_sortgroupclause(srt, query->targetList,
2252 force_colno, context);
2253 sortcoltype = exprType(sortexpr);
2254 /* See whether operator is default < or > for datatype */
2255 typentry = lookup_type_cache(sortcoltype,
2256 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
2257 if (srt->sortop == typentry->lt_opr)
2259 /* ASC is default, so emit nothing for it */
2260 if (srt->nulls_first)
2261 appendStringInfo(buf, " NULLS FIRST");
2263 else if (srt->sortop == typentry->gt_opr)
2265 appendStringInfo(buf, " DESC");
2266 /* DESC defaults to NULLS FIRST */
2267 if (!srt->nulls_first)
2268 appendStringInfo(buf, " NULLS LAST");
2272 appendStringInfo(buf, " USING %s",
2273 generate_operator_name(srt->sortop,
2276 /* be specific to eliminate ambiguity */
2277 if (srt->nulls_first)
2278 appendStringInfo(buf, " NULLS FIRST");
2280 appendStringInfo(buf, " NULLS LAST");
2286 /* Add the LIMIT clause if given */
2287 if (query->limitOffset != NULL)
2289 appendContextKeyword(context, " OFFSET ",
2290 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2291 get_rule_expr(query->limitOffset, context, false);
2293 if (query->limitCount != NULL)
2295 appendContextKeyword(context, " LIMIT ",
2296 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2297 if (IsA(query->limitCount, Const) &&
2298 ((Const *) query->limitCount)->constisnull)
2299 appendStringInfo(buf, "ALL");
2301 get_rule_expr(query->limitCount, context, false);
2304 /* Add FOR UPDATE/SHARE clauses if present */
2305 foreach(l, query->rowMarks)
2307 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2308 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2311 appendContextKeyword(context, " FOR UPDATE",
2312 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2314 appendContextKeyword(context, " FOR SHARE",
2315 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2316 appendStringInfo(buf, " OF %s",
2317 quote_identifier(rte->eref->aliasname));
2319 appendStringInfo(buf, " NOWAIT");
2324 get_basic_select_query(Query *query, deparse_context *context,
2325 TupleDesc resultDesc)
2327 StringInfo buf = context->buf;
2331 if (PRETTY_INDENT(context))
2333 context->indentLevel += PRETTYINDENT_STD;
2334 appendStringInfoChar(buf, ' ');
2338 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2339 * VALUES part. This reverses what transformValuesClause() did at parse
2340 * time. If the jointree contains just a single VALUES RTE, we assume
2341 * this case applies (without looking at the targetlist...)
2343 if (list_length(query->jointree->fromlist) == 1)
2345 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2347 if (IsA(rtr, RangeTblRef))
2349 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2351 if (rte->rtekind == RTE_VALUES)
2353 get_values_def(rte->values_lists, context);
2360 * Build up the query string - first we say SELECT
2362 appendStringInfo(buf, "SELECT");
2364 /* Add the DISTINCT clause if given */
2365 if (query->distinctClause != NIL)
2367 if (query->hasDistinctOn)
2369 appendStringInfo(buf, " DISTINCT ON (");
2371 foreach(l, query->distinctClause)
2373 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2375 appendStringInfoString(buf, sep);
2376 get_rule_sortgroupclause(srt, query->targetList,
2380 appendStringInfo(buf, ")");
2383 appendStringInfo(buf, " DISTINCT");
2386 /* Then we tell what to select (the targetlist) */
2387 get_target_list(query->targetList, context, resultDesc);
2389 /* Add the FROM clause if needed */
2390 get_from_clause(query, " FROM ", context);
2392 /* Add the WHERE clause if given */
2393 if (query->jointree->quals != NULL)
2395 appendContextKeyword(context, " WHERE ",
2396 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2397 get_rule_expr(query->jointree->quals, context, false);
2400 /* Add the GROUP BY clause if given */
2401 if (query->groupClause != NULL)
2403 appendContextKeyword(context, " GROUP BY ",
2404 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2406 foreach(l, query->groupClause)
2408 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2410 appendStringInfoString(buf, sep);
2411 get_rule_sortgroupclause(grp, query->targetList,
2417 /* Add the HAVING clause if given */
2418 if (query->havingQual != NULL)
2420 appendContextKeyword(context, " HAVING ",
2421 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2422 get_rule_expr(query->havingQual, context, false);
2427 * get_target_list - Parse back a SELECT target list
2429 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2433 get_target_list(List *targetList, deparse_context *context,
2434 TupleDesc resultDesc)
2436 StringInfo buf = context->buf;
2443 foreach(l, targetList)
2445 TargetEntry *tle = (TargetEntry *) lfirst(l);
2450 continue; /* ignore junk entries */
2452 appendStringInfoString(buf, sep);
2457 * We special-case Var nodes rather than using get_rule_expr. This is
2458 * needed because get_rule_expr will display a whole-row Var as
2459 * "foo.*", which is the preferred notation in most contexts, but at
2460 * the top level of a SELECT list it's not right (the parser will
2461 * expand that notation into multiple columns, yielding behavior
2462 * different from a whole-row Var). We want just "foo", instead.
2464 if (tle->expr && IsA(tle->expr, Var))
2466 attname = get_variable((Var *) tle->expr, 0, false, context);
2470 get_rule_expr((Node *) tle->expr, context, true);
2471 /* We'll show the AS name unless it's this: */
2472 attname = "?column?";
2476 * Figure out what the result column should be called. In the context
2477 * of a view, use the view's tuple descriptor (so as to pick up the
2478 * effects of any column RENAME that's been done on the view).
2479 * Otherwise, just use what we can find in the TLE.
2481 if (resultDesc && colno <= resultDesc->natts)
2482 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2484 colname = tle->resname;
2486 /* Show AS unless the column's name is correct as-is */
2487 if (colname) /* resname could be NULL */
2489 if (attname == NULL || strcmp(attname, colname) != 0)
2490 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2496 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2497 TupleDesc resultDesc)
2499 StringInfo buf = context->buf;
2502 if (IsA(setOp, RangeTblRef))
2504 RangeTblRef *rtr = (RangeTblRef *) setOp;
2505 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2506 Query *subquery = rte->subquery;
2508 Assert(subquery != NULL);
2509 Assert(subquery->setOperations == NULL);
2510 /* Need parens if ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2511 need_paren = (subquery->sortClause ||
2512 subquery->rowMarks ||
2513 subquery->limitOffset ||
2514 subquery->limitCount);
2516 appendStringInfoChar(buf, '(');
2517 get_query_def(subquery, buf, context->namespaces, resultDesc,
2518 context->prettyFlags, context->indentLevel);
2520 appendStringInfoChar(buf, ')');
2522 else if (IsA(setOp, SetOperationStmt))
2524 SetOperationStmt *op = (SetOperationStmt *) setOp;
2527 * We force parens whenever nesting two SetOperationStmts. There are
2528 * some cases in which parens are needed around a leaf query too, but
2529 * those are more easily handled at the next level down (see code
2532 need_paren = !IsA(op->larg, RangeTblRef);
2535 appendStringInfoChar(buf, '(');
2536 get_setop_query(op->larg, query, context, resultDesc);
2538 appendStringInfoChar(buf, ')');
2540 if (!PRETTY_INDENT(context))
2541 appendStringInfoChar(buf, ' ');
2545 appendContextKeyword(context, "UNION ",
2546 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2548 case SETOP_INTERSECT:
2549 appendContextKeyword(context, "INTERSECT ",
2550 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2553 appendContextKeyword(context, "EXCEPT ",
2554 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2557 elog(ERROR, "unrecognized set op: %d",
2561 appendStringInfo(buf, "ALL ");
2563 if (PRETTY_INDENT(context))
2564 appendContextKeyword(context, "", 0, 0, 0);
2566 need_paren = !IsA(op->rarg, RangeTblRef);
2569 appendStringInfoChar(buf, '(');
2570 get_setop_query(op->rarg, query, context, resultDesc);
2572 appendStringInfoChar(buf, ')');
2576 elog(ERROR, "unrecognized node type: %d",
2577 (int) nodeTag(setOp));
2582 * Display a sort/group clause.
2584 * Also returns the expression tree, so caller need not find it again.
2587 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2588 deparse_context *context)
2590 StringInfo buf = context->buf;
2594 tle = get_sortgroupclause_tle(srt, tlist);
2595 expr = (Node *) tle->expr;
2598 * Use column-number form if requested by caller. Otherwise, if
2599 * expression is a constant, force it to be dumped with an explicit
2600 * cast as decoration --- this is because a simple integer constant
2601 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2602 * if we dump it without any decoration. Otherwise, just dump the
2603 * expression normally.
2607 Assert(!tle->resjunk);
2608 appendStringInfo(buf, "%d", tle->resno);
2610 else if (expr && IsA(expr, Const))
2611 get_const_expr((Const *) expr, context, 1);
2613 get_rule_expr(expr, context, true);
2619 * get_insert_query_def - Parse back an INSERT parsetree
2623 get_insert_query_def(Query *query, deparse_context *context)
2625 StringInfo buf = context->buf;
2626 RangeTblEntry *select_rte = NULL;
2627 RangeTblEntry *values_rte = NULL;
2630 ListCell *values_cell;
2632 List *strippedexprs;
2635 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
2636 * a single RTE for the SELECT or VALUES.
2638 foreach(l, query->rtable)
2640 rte = (RangeTblEntry *) lfirst(l);
2642 if (rte->rtekind == RTE_SUBQUERY)
2645 elog(ERROR, "too many subquery RTEs in INSERT");
2649 if (rte->rtekind == RTE_VALUES)
2652 elog(ERROR, "too many values RTEs in INSERT");
2656 if (select_rte && values_rte)
2657 elog(ERROR, "both subquery and values RTEs in INSERT");
2660 * Start the query with INSERT INTO relname
2662 rte = rt_fetch(query->resultRelation, query->rtable);
2663 Assert(rte->rtekind == RTE_RELATION);
2665 if (PRETTY_INDENT(context))
2667 context->indentLevel += PRETTYINDENT_STD;
2668 appendStringInfoChar(buf, ' ');
2670 appendStringInfo(buf, "INSERT INTO %s (",
2671 generate_relation_name(rte->relid));
2674 * Add the insert-column-names list. To handle indirection properly, we
2675 * need to look for indirection nodes in the top targetlist (if it's
2676 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
2677 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
2678 * assume that all the expression lists will have similar indirection in
2682 values_cell = list_head((List *) linitial(values_rte->values_lists));
2685 strippedexprs = NIL;
2687 foreach(l, query->targetList)
2689 TargetEntry *tle = (TargetEntry *) lfirst(l);
2692 continue; /* ignore junk entries */
2694 appendStringInfoString(buf, sep);
2698 * Put out name of target column; look in the catalogs, not at
2699 * tle->resname, since resname will fail to track RENAME.
2701 appendStringInfoString(buf,
2702 quote_identifier(get_relid_attribute_name(rte->relid,
2706 * Print any indirection needed (subfields or subscripts), and strip
2707 * off the top-level nodes representing the indirection assignments.
2711 /* we discard the stripped expression in this case */
2712 processIndirection((Node *) lfirst(values_cell), context, true);
2713 values_cell = lnext(values_cell);
2717 /* we keep a list of the stripped expressions in this case */
2718 strippedexprs = lappend(strippedexprs,
2719 processIndirection((Node *) tle->expr,
2723 appendStringInfo(buf, ") ");
2727 /* Add the SELECT */
2728 get_query_def(select_rte->subquery, buf, NIL, NULL,
2729 context->prettyFlags, context->indentLevel);
2731 else if (values_rte)
2733 /* Add the multi-VALUES expression lists */
2734 get_values_def(values_rte->values_lists, context);
2738 /* Add the single-VALUES expression list */
2739 appendContextKeyword(context, "VALUES (",
2740 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
2741 get_rule_expr((Node *) strippedexprs, context, false);
2742 appendStringInfoChar(buf, ')');
2745 /* Add RETURNING if present */
2746 if (query->returningList)
2748 appendContextKeyword(context, " RETURNING",
2749 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2750 get_target_list(query->returningList, context, NULL);
2756 * get_update_query_def - Parse back an UPDATE parsetree
2760 get_update_query_def(Query *query, deparse_context *context)
2762 StringInfo buf = context->buf;
2768 * Start the query with UPDATE relname SET
2770 rte = rt_fetch(query->resultRelation, query->rtable);
2771 Assert(rte->rtekind == RTE_RELATION);
2772 if (PRETTY_INDENT(context))
2774 appendStringInfoChar(buf, ' ');
2775 context->indentLevel += PRETTYINDENT_STD;
2777 appendStringInfo(buf, "UPDATE %s%s",
2779 generate_relation_name(rte->relid));
2780 if (rte->alias != NULL)
2781 appendStringInfo(buf, " %s",
2782 quote_identifier(rte->alias->aliasname));
2783 appendStringInfoString(buf, " SET ");
2785 /* Add the comma separated list of 'attname = value' */
2787 foreach(l, query->targetList)
2789 TargetEntry *tle = (TargetEntry *) lfirst(l);
2793 continue; /* ignore junk entries */
2795 appendStringInfoString(buf, sep);
2799 * Put out name of target column; look in the catalogs, not at
2800 * tle->resname, since resname will fail to track RENAME.
2802 appendStringInfoString(buf,
2803 quote_identifier(get_relid_attribute_name(rte->relid,
2807 * Print any indirection needed (subfields or subscripts), and strip
2808 * off the top-level nodes representing the indirection assignments.
2810 expr = processIndirection((Node *) tle->expr, context, true);
2812 appendStringInfo(buf, " = ");
2814 get_rule_expr(expr, context, false);
2817 /* Add the FROM clause if needed */
2818 get_from_clause(query, " FROM ", context);
2820 /* Add a WHERE clause if given */
2821 if (query->jointree->quals != NULL)
2823 appendContextKeyword(context, " WHERE ",
2824 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2825 get_rule_expr(query->jointree->quals, context, false);
2828 /* Add RETURNING if present */
2829 if (query->returningList)
2831 appendContextKeyword(context, " RETURNING",
2832 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2833 get_target_list(query->returningList, context, NULL);
2839 * get_delete_query_def - Parse back a DELETE parsetree
2843 get_delete_query_def(Query *query, deparse_context *context)
2845 StringInfo buf = context->buf;
2849 * Start the query with DELETE FROM relname
2851 rte = rt_fetch(query->resultRelation, query->rtable);
2852 Assert(rte->rtekind == RTE_RELATION);
2853 if (PRETTY_INDENT(context))
2855 appendStringInfoChar(buf, ' ');
2856 context->indentLevel += PRETTYINDENT_STD;
2858 appendStringInfo(buf, "DELETE FROM %s%s",
2860 generate_relation_name(rte->relid));
2861 if (rte->alias != NULL)
2862 appendStringInfo(buf, " %s",
2863 quote_identifier(rte->alias->aliasname));
2865 /* Add the USING clause if given */
2866 get_from_clause(query, " USING ", context);
2868 /* Add a WHERE clause if given */
2869 if (query->jointree->quals != NULL)
2871 appendContextKeyword(context, " WHERE ",
2872 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2873 get_rule_expr(query->jointree->quals, context, false);
2876 /* Add RETURNING if present */
2877 if (query->returningList)
2879 appendContextKeyword(context, " RETURNING",
2880 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2881 get_target_list(query->returningList, context, NULL);
2887 * get_utility_query_def - Parse back a UTILITY parsetree
2891 get_utility_query_def(Query *query, deparse_context *context)
2893 StringInfo buf = context->buf;
2895 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
2897 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
2899 appendContextKeyword(context, "",
2900 0, PRETTYINDENT_STD, 1);
2901 appendStringInfo(buf, "NOTIFY %s",
2902 quote_identifier(stmt->conditionname));
2906 /* Currently only NOTIFY utility commands can appear in rules */
2907 elog(ERROR, "unexpected utility statement type");
2913 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
2915 * When expanding an OUTER or INNER reference, we must push new outer/inner
2916 * subplans in case the referenced expression itself uses OUTER/INNER. We
2917 * modify the top stack entry in-place to avoid affecting levelsup issues
2918 * (although in a Plan tree there really shouldn't be any).
2920 * Caller must save and restore outer_plan and inner_plan around this.
2923 push_plan(deparse_namespace *dpns, Plan *subplan)
2926 * We special-case Append to pretend that the first child plan is the
2927 * OUTER referent; otherwise normal.
2929 if (IsA(subplan, Append))
2930 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
2932 dpns->outer_plan = outerPlan(subplan);
2935 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
2936 * use OUTER because that could someday conflict with the normal meaning.)
2938 if (IsA(subplan, SubqueryScan))
2939 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
2941 dpns->inner_plan = innerPlan(subplan);
2946 * Display a Var appropriately.
2948 * In some cases (currently only when recursing into an unnamed join)
2949 * the Var's varlevelsup has to be interpreted with respect to a context
2950 * above the current one; levelsup indicates the offset.
2952 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
2953 * if FALSE, merely as "foo".
2955 * Returns the attname of the Var, or NULL if not determinable.
2958 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
2960 StringInfo buf = context->buf;
2964 deparse_namespace *dpns;
2969 /* Find appropriate nesting depth */
2970 netlevelsup = var->varlevelsup + levelsup;
2971 if (netlevelsup >= list_length(context->namespaces))
2972 elog(ERROR, "bogus varlevelsup: %d offset %d",
2973 var->varlevelsup, levelsup);
2974 dpns = (deparse_namespace *) list_nth(context->namespaces,
2978 * Try to find the relevant RTE in this rtable. In a plan tree, it's
2979 * likely that varno is OUTER or INNER, in which case we must dig down
2980 * into the subplans.
2982 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
2984 rte = rt_fetch(var->varno, dpns->rtable);
2985 attnum = var->varattno;
2987 else if (var->varno == OUTER && dpns->outer_plan)
2993 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
2995 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
2997 Assert(netlevelsup == 0);
2998 save_outer = dpns->outer_plan;
2999 save_inner = dpns->inner_plan;
3000 push_plan(dpns, dpns->outer_plan);
3003 * Force parentheses because our caller probably assumed a Var is a
3004 * simple expression.
3006 if (!IsA(tle->expr, Var))
3007 appendStringInfoChar(buf, '(');
3008 get_rule_expr((Node *) tle->expr, context, true);
3009 if (!IsA(tle->expr, Var))
3010 appendStringInfoChar(buf, ')');
3012 dpns->outer_plan = save_outer;
3013 dpns->inner_plan = save_inner;
3016 else if (var->varno == INNER && dpns->inner_plan)
3022 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3024 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3026 Assert(netlevelsup == 0);
3027 save_outer = dpns->outer_plan;
3028 save_inner = dpns->inner_plan;
3029 push_plan(dpns, dpns->inner_plan);
3032 * Force parentheses because our caller probably assumed a Var is a
3033 * simple expression.
3035 if (!IsA(tle->expr, Var))
3036 appendStringInfoChar(buf, '(');
3037 get_rule_expr((Node *) tle->expr, context, true);
3038 if (!IsA(tle->expr, Var))
3039 appendStringInfoChar(buf, ')');
3041 dpns->outer_plan = save_outer;
3042 dpns->inner_plan = save_inner;
3047 elog(ERROR, "bogus varno: %d", var->varno);
3048 return NULL; /* keep compiler quiet */
3051 /* Identify names to use */
3052 schemaname = NULL; /* default assumptions */
3053 refname = rte->eref->aliasname;
3055 /* Exceptions occur only if the RTE is alias-less */
3056 if (rte->alias == NULL)
3058 if (rte->rtekind == RTE_RELATION)
3061 * It's possible that use of the bare refname would find another
3062 * more-closely-nested RTE, or be ambiguous, in which case we need
3063 * to specify the schemaname to avoid these errors.
3065 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3066 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3068 else if (rte->rtekind == RTE_JOIN)
3071 * If it's an unnamed join, look at the expansion of the alias
3072 * variable. If it's a simple reference to one of the input vars
3073 * then recursively print the name of that var, instead. (This
3074 * allows correct decompiling of cases where there are identically
3075 * named columns on both sides of the join.) When it's not a
3076 * simple reference, we have to just print the unqualified
3077 * variable name (this can only happen with columns that were
3078 * merged by USING or NATURAL clauses).
3080 * This wouldn't work in decompiling plan trees, because we don't
3081 * store joinaliasvars lists after planning; but a plan tree
3082 * should never contain a join alias variable.
3084 if (rte->joinaliasvars == NIL)
3085 elog(ERROR, "cannot decompile join alias var in plan tree");
3090 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3091 if (IsA(aliasvar, Var))
3093 return get_variable(aliasvar, var->varlevelsup + levelsup,
3097 /* Unnamed join has neither schemaname nor refname */
3102 if (attnum == InvalidAttrNumber)
3105 attname = get_rte_attribute_name(rte, attnum);
3107 if (refname && (context->varprefix || attname == NULL))
3110 appendStringInfo(buf, "%s.",
3111 quote_identifier(schemaname));
3113 if (strcmp(refname, "*NEW*") == 0)
3114 appendStringInfoString(buf, "new");
3115 else if (strcmp(refname, "*OLD*") == 0)
3116 appendStringInfoString(buf, "old");
3118 appendStringInfoString(buf, quote_identifier(refname));
3120 if (attname || showstar)
3121 appendStringInfoChar(buf, '.');
3124 appendStringInfoString(buf, quote_identifier(attname));
3126 appendStringInfoChar(buf, '*');
3133 * Get the name of a field of an expression of composite type.
3135 * This is fairly straightforward except for the case of a Var of type RECORD.
3136 * Since no actual table or view column is allowed to have type RECORD, such
3137 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3138 * drill down to find the ultimate defining expression and attempt to infer
3139 * the field name from it. We ereport if we can't determine the name.
3141 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3144 get_name_for_var_field(Var *var, int fieldno,
3145 int levelsup, deparse_context *context)
3150 deparse_namespace *dpns;
3151 TupleDesc tupleDesc;
3155 * If it's a Var of type RECORD, we have to find what the Var refers to;
3156 * if not, we can use get_expr_result_type. If that fails, we try
3157 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3158 * an acceptable message.
3160 if (!IsA(var, Var) ||
3161 var->vartype != RECORDOID)
3163 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3164 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3165 exprTypmod((Node *) var));
3167 /* Got the tupdesc, so we can extract the field name */
3168 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3169 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3172 /* Find appropriate nesting depth */
3173 netlevelsup = var->varlevelsup + levelsup;
3174 if (netlevelsup >= list_length(context->namespaces))
3175 elog(ERROR, "bogus varlevelsup: %d offset %d",
3176 var->varlevelsup, levelsup);
3177 dpns = (deparse_namespace *) list_nth(context->namespaces,
3181 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3182 * likely that varno is OUTER or INNER, in which case we must dig down
3183 * into the subplans.
3185 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3187 rte = rt_fetch(var->varno, dpns->rtable);
3188 attnum = var->varattno;
3190 else if (var->varno == OUTER && dpns->outer_plan)
3197 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3199 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3201 Assert(netlevelsup == 0);
3202 save_outer = dpns->outer_plan;
3203 save_inner = dpns->inner_plan;
3204 push_plan(dpns, dpns->outer_plan);
3206 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3209 dpns->outer_plan = save_outer;
3210 dpns->inner_plan = save_inner;
3213 else if (var->varno == INNER && dpns->inner_plan)
3220 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3222 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3224 Assert(netlevelsup == 0);
3225 save_outer = dpns->outer_plan;
3226 save_inner = dpns->inner_plan;
3227 push_plan(dpns, dpns->inner_plan);
3229 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3232 dpns->outer_plan = save_outer;
3233 dpns->inner_plan = save_inner;
3238 elog(ERROR, "bogus varno: %d", var->varno);
3239 return NULL; /* keep compiler quiet */
3242 if (attnum == InvalidAttrNumber)
3244 /* Var is whole-row reference to RTE, so select the right field */
3245 return get_rte_attribute_name(rte, fieldno);
3249 * This part has essentially the same logic as the parser's
3250 * expandRecordVariable() function, but we are dealing with a different
3251 * representation of the input context, and we only need one field name
3252 * not a TupleDesc. Also, we need a special case for deparsing Plan
3253 * trees, because the subquery field has been removed from SUBQUERY RTEs.
3255 expr = (Node *) var; /* default if we can't drill down */
3257 switch (rte->rtekind)
3264 * This case should not occur: a column of a table or values list
3265 * shouldn't have type RECORD. Fall through and fail (most
3266 * likely) at the bottom.
3273 /* Subselect-in-FROM: examine sub-select's output expr */
3274 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3277 if (ste == NULL || ste->resjunk)
3278 elog(ERROR, "subquery %s does not have attribute %d",
3279 rte->eref->aliasname, attnum);
3280 expr = (Node *) ste->expr;
3284 * Recurse into the sub-select to see what its Var
3285 * refers to. We have to build an additional level of
3286 * namespace to keep in step with varlevelsup in the
3289 deparse_namespace mydpns;
3292 mydpns.rtable = rte->subquery->rtable;
3293 mydpns.outer_plan = mydpns.inner_plan = NULL;
3295 context->namespaces = lcons(&mydpns,
3296 context->namespaces);
3298 result = get_name_for_var_field((Var *) expr, fieldno,
3301 context->namespaces =
3302 list_delete_first(context->namespaces);
3306 /* else fall through to inspect the expression */
3311 * We're deparsing a Plan tree so we don't have complete
3312 * RTE entries. But the only place we'd see a Var
3313 * directly referencing a SUBQUERY RTE is in a
3314 * SubqueryScan plan node, and we can look into the child
3315 * plan's tlist instead.
3322 if (!dpns->inner_plan)
3323 elog(ERROR, "failed to find plan for subquery %s",
3324 rte->eref->aliasname);
3325 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3328 elog(ERROR, "bogus varattno for subquery var: %d",
3330 Assert(netlevelsup == 0);
3331 save_outer = dpns->outer_plan;
3332 save_inner = dpns->inner_plan;
3333 push_plan(dpns, dpns->inner_plan);
3335 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3338 dpns->outer_plan = save_outer;
3339 dpns->inner_plan = save_inner;
3345 /* Join RTE --- recursively inspect the alias variable */
3346 if (rte->joinaliasvars == NIL)
3347 elog(ERROR, "cannot decompile join alias var in plan tree");
3348 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3349 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3351 return get_name_for_var_field((Var *) expr, fieldno,
3352 var->varlevelsup + levelsup,
3354 /* else fall through to inspect the expression */
3359 * We couldn't get here unless a function is declared with one of
3360 * its result columns as RECORD, which is not allowed.
3366 * We now have an expression we can't expand any more, so see if
3367 * get_expr_result_type() can do anything with it. If not, pass to
3368 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3369 * appropriate error message while failing.
3371 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3372 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
3375 /* Got the tupdesc, so we can extract the field name */
3376 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3377 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3382 * find_rte_by_refname - look up an RTE by refname in a deparse context
3384 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3386 * NOTE: this code is not really correct since it does not take account of
3387 * the fact that not all the RTEs in a rangetable may be visible from the
3388 * point where a Var reference appears. For the purposes we need, however,
3389 * the only consequence of a false match is that we might stick a schema
3390 * qualifier on a Var that doesn't really need it. So it seems close
3393 static RangeTblEntry *
3394 find_rte_by_refname(const char *refname, deparse_context *context)
3396 RangeTblEntry *result = NULL;
3399 foreach(nslist, context->namespaces)
3401 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
3404 foreach(rtlist, dpns->rtable)
3406 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
3408 if (strcmp(rte->eref->aliasname, refname) == 0)
3411 return NULL; /* it's ambiguous */
3423 * get_simple_binary_op_name
3425 * helper function for isSimpleNode
3426 * will return single char binary operator name, or NULL if it's not
3429 get_simple_binary_op_name(OpExpr *expr)
3431 List *args = expr->args;
3433 if (list_length(args) == 2)
3435 /* binary operator */
3436 Node *arg1 = (Node *) linitial(args);
3437 Node *arg2 = (Node *) lsecond(args);
3440 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
3441 if (strlen(op) == 1)
3449 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3451 * true : simple in the context of parent node's type
3452 * false : not simple
3455 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
3460 switch (nodeTag(node))
3465 case T_CoerceToDomainValue:
3466 case T_SetToDefault:
3467 case T_CurrentOfExpr:
3468 /* single words: always simple */
3474 case T_CoalesceExpr:
3480 /* function-like: name(..) or name[..] */
3483 /* CASE keywords act as parentheses */
3490 * appears simple since . has top precedence, unless parent is
3491 * T_FieldSelect itself!
3493 return (IsA(parentNode, FieldSelect) ? false : true);
3498 * treat like FieldSelect (probably doesn't matter)
3500 return (IsA(parentNode, FieldStore) ? false : true);
3502 case T_CoerceToDomain:
3503 /* maybe simple, check args */
3504 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
3507 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
3510 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
3512 case T_ArrayCoerceExpr:
3513 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
3515 case T_ConvertRowtypeExpr:
3516 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
3521 /* depends on parent node type; needs further checking */
3522 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
3525 const char *parentOp;
3528 bool is_lopriparent;
3529 bool is_hipriparent;
3531 op = get_simple_binary_op_name((OpExpr *) node);
3535 /* We know only the basic operators + - and * / % */
3536 is_lopriop = (strchr("+-", *op) != NULL);
3537 is_hipriop = (strchr("*/%", *op) != NULL);
3538 if (!(is_lopriop || is_hipriop))
3541 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
3545 is_lopriparent = (strchr("+-", *parentOp) != NULL);
3546 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
3547 if (!(is_lopriparent || is_hipriparent))
3550 if (is_hipriop && is_lopriparent)
3551 return true; /* op binds tighter than parent */
3553 if (is_lopriop && is_hipriparent)
3557 * Operators are same priority --- can skip parens only if
3558 * we have (a - b) - c, not a - (b - c).
3560 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
3565 /* else do the same stuff as for T_SubLink et al. */
3572 case T_DistinctExpr:
3573 switch (nodeTag(parentNode))
3577 /* special handling for casts */
3578 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3580 if (type == COERCE_EXPLICIT_CAST ||
3581 type == COERCE_IMPLICIT_CAST)
3583 return true; /* own parentheses */
3585 case T_BoolExpr: /* lower precedence */
3586 case T_ArrayRef: /* other separators */
3587 case T_ArrayExpr: /* other separators */
3588 case T_RowExpr: /* other separators */
3589 case T_CoalesceExpr: /* own parentheses */
3590 case T_MinMaxExpr: /* own parentheses */
3591 case T_XmlExpr: /* own parentheses */
3592 case T_NullIfExpr: /* other separators */
3593 case T_Aggref: /* own parentheses */
3594 case T_CaseExpr: /* other separators */
3601 switch (nodeTag(parentNode))
3604 if (prettyFlags & PRETTYFLAG_PAREN)
3607 BoolExprType parentType;
3609 type = ((BoolExpr *) node)->boolop;
3610 parentType = ((BoolExpr *) parentNode)->boolop;
3615 if (parentType == AND_EXPR || parentType == OR_EXPR)
3619 if (parentType == OR_EXPR)
3627 /* special handling for casts */
3628 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3630 if (type == COERCE_EXPLICIT_CAST ||
3631 type == COERCE_IMPLICIT_CAST)
3633 return true; /* own parentheses */
3635 case T_ArrayRef: /* other separators */
3636 case T_ArrayExpr: /* other separators */
3637 case T_RowExpr: /* other separators */
3638 case T_CoalesceExpr: /* own parentheses */
3639 case T_MinMaxExpr: /* own parentheses */
3640 case T_XmlExpr: /* own parentheses */
3641 case T_NullIfExpr: /* other separators */
3642 case T_Aggref: /* own parentheses */
3643 case T_CaseExpr: /* other separators */
3652 /* those we don't know: in dubio complexo */
3658 * appendStringInfoSpaces - append spaces to buffer
3661 appendStringInfoSpaces(StringInfo buf, int count)
3664 appendStringInfoChar(buf, ' ');
3668 * appendContextKeyword - append a keyword to buffer
3670 * If prettyPrint is enabled, perform a line break, and adjust indentation.
3671 * Otherwise, just append the keyword.
3674 appendContextKeyword(deparse_context *context, const char *str,
3675 int indentBefore, int indentAfter, int indentPlus)
3677 if (PRETTY_INDENT(context))
3679 context->indentLevel += indentBefore;
3681 appendStringInfoChar(context->buf, '\n');
3682 appendStringInfoSpaces(context->buf,
3683 Max(context->indentLevel, 0) + indentPlus);
3684 appendStringInfoString(context->buf, str);
3686 context->indentLevel += indentAfter;
3687 if (context->indentLevel < 0)
3688 context->indentLevel = 0;
3691 appendStringInfoString(context->buf, str);
3695 * get_rule_expr_paren - deparse expr using get_rule_expr,
3696 * embracing the string with parentheses if necessary for prettyPrint.
3698 * Never embrace if prettyFlags=0, because it's done in the calling node.
3700 * Any node that does *not* embrace its argument node by sql syntax (with
3701 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
3702 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
3706 get_rule_expr_paren(Node *node, deparse_context *context,
3707 bool showimplicit, Node *parentNode)
3711 need_paren = PRETTY_PAREN(context) &&
3712 !isSimpleNode(node, parentNode, context->prettyFlags);
3715 appendStringInfoChar(context->buf, '(');
3717 get_rule_expr(node, context, showimplicit);
3720 appendStringInfoChar(context->buf, ')');
3725 * get_rule_expr - Parse back an expression
3727 * Note: showimplicit determines whether we display any implicit cast that
3728 * is present at the top of the expression tree. It is a passed argument,
3729 * not a field of the context struct, because we change the value as we
3730 * recurse down into the expression. In general we suppress implicit casts
3731 * when the result type is known with certainty (eg, the arguments of an
3732 * OR must be boolean). We display implicit casts for arguments of functions
3733 * and operators, since this is needed to be certain that the same function
3734 * or operator will be chosen when the expression is re-parsed.
3738 get_rule_expr(Node *node, deparse_context *context,
3741 StringInfo buf = context->buf;
3747 * Each level of get_rule_expr must emit an indivisible term
3748 * (parenthesized if necessary) to ensure result is reparsed into the same
3749 * expression tree. The only exception is that when the input is a List,
3750 * we emit the component items comma-separated with no surrounding
3751 * decoration; this is convenient for most callers.
3753 switch (nodeTag(node))
3756 (void) get_variable((Var *) node, 0, true, context);
3760 get_const_expr((Const *) node, context, 0);
3764 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
3768 get_agg_expr((Aggref *) node, context);
3773 ArrayRef *aref = (ArrayRef *) node;
3777 * Parenthesize the argument unless it's a simple Var or a
3778 * FieldSelect. (In particular, if it's another ArrayRef, we
3779 * *must* parenthesize to avoid confusion.)
3781 need_parens = !IsA(aref->refexpr, Var) &&
3782 !IsA(aref->refexpr, FieldSelect);
3784 appendStringInfoChar(buf, '(');
3785 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
3787 appendStringInfoChar(buf, ')');
3788 printSubscripts(aref, context);
3791 * Array assignment nodes should have been handled in
3792 * processIndirection().
3794 if (aref->refassgnexpr)
3795 elog(ERROR, "unexpected refassgnexpr");
3800 get_func_expr((FuncExpr *) node, context, showimplicit);
3804 get_oper_expr((OpExpr *) node, context);
3807 case T_DistinctExpr:
3809 DistinctExpr *expr = (DistinctExpr *) node;
3810 List *args = expr->args;
3811 Node *arg1 = (Node *) linitial(args);
3812 Node *arg2 = (Node *) lsecond(args);
3814 if (!PRETTY_PAREN(context))
3815 appendStringInfoChar(buf, '(');
3816 get_rule_expr_paren(arg1, context, true, node);
3817 appendStringInfo(buf, " IS DISTINCT FROM ");
3818 get_rule_expr_paren(arg2, context, true, node);
3819 if (!PRETTY_PAREN(context))
3820 appendStringInfoChar(buf, ')');
3824 case T_ScalarArrayOpExpr:
3826 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
3827 List *args = expr->args;
3828 Node *arg1 = (Node *) linitial(args);
3829 Node *arg2 = (Node *) lsecond(args);
3831 if (!PRETTY_PAREN(context))
3832 appendStringInfoChar(buf, '(');
3833 get_rule_expr_paren(arg1, context, true, node);
3834 appendStringInfo(buf, " %s %s (",
3835 generate_operator_name(expr->opno,
3837 get_element_type(exprType(arg2))),
3838 expr->useOr ? "ANY" : "ALL");
3839 get_rule_expr_paren(arg2, context, true, node);
3840 appendStringInfoChar(buf, ')');
3841 if (!PRETTY_PAREN(context))
3842 appendStringInfoChar(buf, ')');
3848 BoolExpr *expr = (BoolExpr *) node;
3849 Node *first_arg = linitial(expr->args);
3850 ListCell *arg = lnext(list_head(expr->args));
3852 switch (expr->boolop)
3855 if (!PRETTY_PAREN(context))
3856 appendStringInfoChar(buf, '(');
3857 get_rule_expr_paren(first_arg, context,
3861 appendStringInfo(buf, " AND ");
3862 get_rule_expr_paren((Node *) lfirst(arg), context,
3866 if (!PRETTY_PAREN(context))
3867 appendStringInfoChar(buf, ')');
3871 if (!PRETTY_PAREN(context))
3872 appendStringInfoChar(buf, '(');
3873 get_rule_expr_paren(first_arg, context,
3877 appendStringInfo(buf, " OR ");
3878 get_rule_expr_paren((Node *) lfirst(arg), context,
3882 if (!PRETTY_PAREN(context))
3883 appendStringInfoChar(buf, ')');
3887 if (!PRETTY_PAREN(context))
3888 appendStringInfoChar(buf, '(');
3889 appendStringInfo(buf, "NOT ");
3890 get_rule_expr_paren(first_arg, context,
3892 if (!PRETTY_PAREN(context))
3893 appendStringInfoChar(buf, ')');
3897 elog(ERROR, "unrecognized boolop: %d",
3898 (int) expr->boolop);
3904 get_sublink_expr((SubLink *) node, context);
3910 * We cannot see an already-planned subplan in rule deparsing,
3911 * only while EXPLAINing a query plan. For now, just punt.
3913 if (((SubPlan *) node)->useHashTable)
3914 appendStringInfo(buf, "(hashed subplan)");
3916 appendStringInfo(buf, "(subplan)");
3920 case T_AlternativeSubPlan:
3921 /* As above, just punt */
3922 appendStringInfo(buf, "(alternative subplans)");
3927 FieldSelect *fselect = (FieldSelect *) node;
3928 Node *arg = (Node *) fselect->arg;
3929 int fno = fselect->fieldnum;
3930 const char *fieldname;
3934 * Parenthesize the argument unless it's an ArrayRef or
3935 * another FieldSelect. Note in particular that it would be
3936 * WRONG to not parenthesize a Var argument; simplicity is not
3937 * the issue here, having the right number of names is.
3939 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
3941 appendStringInfoChar(buf, '(');
3942 get_rule_expr(arg, context, true);
3944 appendStringInfoChar(buf, ')');
3947 * Get and print the field name.
3949 fieldname = get_name_for_var_field((Var *) arg, fno,
3951 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
3958 * We shouldn't see FieldStore here; it should have been stripped
3959 * off by processIndirection().
3961 elog(ERROR, "unexpected FieldStore");
3966 RelabelType *relabel = (RelabelType *) node;
3967 Node *arg = (Node *) relabel->arg;
3969 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
3972 /* don't show the implicit cast */
3973 get_rule_expr_paren(arg, context, false, node);
3977 get_coercion_expr(arg, context,
3978 relabel->resulttype,
3979 relabel->resulttypmod,
3987 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
3988 Node *arg = (Node *) iocoerce->arg;
3990 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
3993 /* don't show the implicit cast */
3994 get_rule_expr_paren(arg, context, false, node);
3998 get_coercion_expr(arg, context,
3999 iocoerce->resulttype,
4006 case T_ArrayCoerceExpr:
4008 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4009 Node *arg = (Node *) acoerce->arg;
4011 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4014 /* don't show the implicit cast */
4015 get_rule_expr_paren(arg, context, false, node);
4019 get_coercion_expr(arg, context,
4020 acoerce->resulttype,
4021 acoerce->resulttypmod,
4027 case T_ConvertRowtypeExpr:
4029 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4030 Node *arg = (Node *) convert->arg;
4032 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4035 /* don't show the implicit cast */
4036 get_rule_expr_paren(arg, context, false, node);
4040 get_coercion_expr(arg, context,
4041 convert->resulttype, -1,
4049 CaseExpr *caseexpr = (CaseExpr *) node;
4052 appendContextKeyword(context, "CASE",
4053 0, PRETTYINDENT_VAR, 0);
4056 appendStringInfoChar(buf, ' ');
4057 get_rule_expr((Node *) caseexpr->arg, context, true);
4059 foreach(temp, caseexpr->args)
4061 CaseWhen *when = (CaseWhen *) lfirst(temp);
4062 Node *w = (Node *) when->expr;
4064 if (!PRETTY_INDENT(context))
4065 appendStringInfoChar(buf, ' ');
4066 appendContextKeyword(context, "WHEN ",
4071 * The parser should have produced WHEN clauses of the
4072 * form "CaseTestExpr = RHS"; we want to show just the
4073 * RHS. If the user wrote something silly like "CASE
4074 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4075 * simplify_boolean_equality() may have reduced this
4076 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4077 * which we have to show "TRUE" or "FALSE". Also,
4078 * depending on context the original CaseTestExpr
4079 * might have been reduced to a Const (but we won't
4080 * see "WHEN Const").
4086 Assert(IsA(linitial(((OpExpr *) w)->args),
4088 IsA(linitial(((OpExpr *) w)->args),
4090 rhs = (Node *) lsecond(((OpExpr *) w)->args);
4091 get_rule_expr(rhs, context, false);
4093 else if (IsA(w, CaseTestExpr))
4094 appendStringInfo(buf, "TRUE");
4095 else if (not_clause(w))
4097 Assert(IsA(get_notclausearg((Expr *) w),
4099 appendStringInfo(buf, "FALSE");
4102 elog(ERROR, "unexpected CASE WHEN clause: %d",
4106 get_rule_expr(w, context, false);
4107 appendStringInfo(buf, " THEN ");
4108 get_rule_expr((Node *) when->result, context, true);
4110 if (!PRETTY_INDENT(context))
4111 appendStringInfoChar(buf, ' ');
4112 appendContextKeyword(context, "ELSE ",
4114 get_rule_expr((Node *) caseexpr->defresult, context, true);
4115 if (!PRETTY_INDENT(context))
4116 appendStringInfoChar(buf, ' ');
4117 appendContextKeyword(context, "END",
4118 -PRETTYINDENT_VAR, 0, 0);
4124 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4126 appendStringInfo(buf, "ARRAY[");
4127 get_rule_expr((Node *) arrayexpr->elements, context, true);
4128 appendStringInfoChar(buf, ']');
4134 RowExpr *rowexpr = (RowExpr *) node;
4135 TupleDesc tupdesc = NULL;
4141 * If it's a named type and not RECORD, we may have to skip
4142 * dropped columns and/or claim there are NULLs for added
4145 if (rowexpr->row_typeid != RECORDOID)
4147 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4148 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4152 * SQL99 allows "ROW" to be omitted when there is more than
4153 * one column, but for simplicity we always print it.
4155 appendStringInfo(buf, "ROW(");
4158 foreach(arg, rowexpr->args)
4160 Node *e = (Node *) lfirst(arg);
4162 if (tupdesc == NULL ||
4163 !tupdesc->attrs[i]->attisdropped)
4165 appendStringInfoString(buf, sep);
4166 get_rule_expr(e, context, true);
4171 if (tupdesc != NULL)
4173 while (i < tupdesc->natts)
4175 if (!tupdesc->attrs[i]->attisdropped)
4177 appendStringInfoString(buf, sep);
4178 appendStringInfo(buf, "NULL");
4184 ReleaseTupleDesc(tupdesc);
4186 appendStringInfo(buf, ")");
4187 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4188 appendStringInfo(buf, "::%s",
4189 format_type_with_typemod(rowexpr->row_typeid, -1));
4193 case T_RowCompareExpr:
4195 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
4200 * SQL99 allows "ROW" to be omitted when there is more than
4201 * one column, but for simplicity we always print it.
4203 appendStringInfo(buf, "(ROW(");
4205 foreach(arg, rcexpr->largs)
4207 Node *e = (Node *) lfirst(arg);
4209 appendStringInfoString(buf, sep);
4210 get_rule_expr(e, context, true);
4215 * We assume that the name of the first-column operator will
4216 * do for all the rest too. This is definitely open to
4217 * failure, eg if some but not all operators were renamed
4218 * since the construct was parsed, but there seems no way to
4221 appendStringInfo(buf, ") %s ROW(",
4222 generate_operator_name(linitial_oid(rcexpr->opnos),
4223 exprType(linitial(rcexpr->largs)),
4224 exprType(linitial(rcexpr->rargs))));
4226 foreach(arg, rcexpr->rargs)
4228 Node *e = (Node *) lfirst(arg);
4230 appendStringInfoString(buf, sep);
4231 get_rule_expr(e, context, true);
4234 appendStringInfo(buf, "))");
4238 case T_CoalesceExpr:
4240 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
4242 appendStringInfo(buf, "COALESCE(");
4243 get_rule_expr((Node *) coalesceexpr->args, context, true);
4244 appendStringInfoChar(buf, ')');
4250 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
4252 switch (minmaxexpr->op)
4255 appendStringInfo(buf, "GREATEST(");
4258 appendStringInfo(buf, "LEAST(");
4261 get_rule_expr((Node *) minmaxexpr->args, context, true);
4262 appendStringInfoChar(buf, ')');
4268 XmlExpr *xexpr = (XmlExpr *) node;
4269 bool needcomma = false;
4277 appendStringInfoString(buf, "XMLCONCAT(");
4280 appendStringInfoString(buf, "XMLELEMENT(");
4283 appendStringInfoString(buf, "XMLFOREST(");
4286 appendStringInfoString(buf, "XMLPARSE(");
4289 appendStringInfoString(buf, "XMLPI(");
4292 appendStringInfoString(buf, "XMLROOT(");
4294 case IS_XMLSERIALIZE:
4295 appendStringInfoString(buf, "XMLSERIALIZE(");
4300 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
4302 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
4303 appendStringInfoString(buf, "DOCUMENT ");
4305 appendStringInfoString(buf, "CONTENT ");
4309 appendStringInfo(buf, "NAME %s",
4310 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
4313 if (xexpr->named_args)
4315 if (xexpr->op != IS_XMLFOREST)
4318 appendStringInfoString(buf, ", ");
4319 appendStringInfoString(buf, "XMLATTRIBUTES(");
4322 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
4324 Node *e = (Node *) lfirst(arg);
4325 char *argname = strVal(lfirst(narg));
4328 appendStringInfoString(buf, ", ");
4329 get_rule_expr((Node *) e, context, true);
4330 appendStringInfo(buf, " AS %s",
4331 quote_identifier(map_xml_name_to_sql_identifier(argname)));
4334 if (xexpr->op != IS_XMLFOREST)
4335 appendStringInfoChar(buf, ')');
4340 appendStringInfoString(buf, ", ");
4347 case IS_XMLSERIALIZE:
4348 /* no extra decoration needed */
4349 get_rule_expr((Node *) xexpr->args, context, true);
4352 Assert(list_length(xexpr->args) == 2);
4354 get_rule_expr((Node *) linitial(xexpr->args),
4357 con = (Const *) lsecond(xexpr->args);
4358 Assert(IsA(con, Const));
4359 Assert(!con->constisnull);
4360 if (DatumGetBool(con->constvalue))
4361 appendStringInfoString(buf,
4362 " PRESERVE WHITESPACE");
4364 appendStringInfoString(buf,
4365 " STRIP WHITESPACE");
4368 Assert(list_length(xexpr->args) == 3);
4370 get_rule_expr((Node *) linitial(xexpr->args),
4373 appendStringInfoString(buf, ", VERSION ");
4374 con = (Const *) lsecond(xexpr->args);
4375 if (IsA(con, Const) &&
4377 appendStringInfoString(buf, "NO VALUE");
4379 get_rule_expr((Node *) con, context, false);
4381 con = (Const *) lthird(xexpr->args);
4382 Assert(IsA(con, Const));
4383 if (con->constisnull)
4384 /* suppress STANDALONE NO VALUE */ ;
4387 switch (DatumGetInt32(con->constvalue))
4389 case XML_STANDALONE_YES:
4390 appendStringInfoString(buf,
4391 ", STANDALONE YES");
4393 case XML_STANDALONE_NO:
4394 appendStringInfoString(buf,
4397 case XML_STANDALONE_NO_VALUE:
4398 appendStringInfoString(buf,
4399 ", STANDALONE NO VALUE");
4407 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
4412 if (xexpr->op == IS_XMLSERIALIZE)
4413 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
4415 if (xexpr->op == IS_DOCUMENT)
4416 appendStringInfoString(buf, " IS DOCUMENT");
4418 appendStringInfoChar(buf, ')');
4424 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4426 appendStringInfo(buf, "NULLIF(");
4427 get_rule_expr((Node *) nullifexpr->args, context, true);
4428 appendStringInfoChar(buf, ')');
4434 NullTest *ntest = (NullTest *) node;
4436 if (!PRETTY_PAREN(context))
4437 appendStringInfoChar(buf, '(');
4438 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
4439 switch (ntest->nulltesttype)
4442 appendStringInfo(buf, " IS NULL");
4445 appendStringInfo(buf, " IS NOT NULL");
4448 elog(ERROR, "unrecognized nulltesttype: %d",
4449 (int) ntest->nulltesttype);
4451 if (!PRETTY_PAREN(context))
4452 appendStringInfoChar(buf, ')');
4458 BooleanTest *btest = (BooleanTest *) node;
4460 if (!PRETTY_PAREN(context))
4461 appendStringInfoChar(buf, '(');
4462 get_rule_expr_paren((Node *) btest->arg, context, false, node);
4463 switch (btest->booltesttype)
4466 appendStringInfo(buf, " IS TRUE");
4469 appendStringInfo(buf, " IS NOT TRUE");
4472 appendStringInfo(buf, " IS FALSE");
4475 appendStringInfo(buf, " IS NOT FALSE");
4478 appendStringInfo(buf, " IS UNKNOWN");
4480 case IS_NOT_UNKNOWN:
4481 appendStringInfo(buf, " IS NOT UNKNOWN");
4484 elog(ERROR, "unrecognized booltesttype: %d",
4485 (int) btest->booltesttype);
4487 if (!PRETTY_PAREN(context))
4488 appendStringInfoChar(buf, ')');
4492 case T_CoerceToDomain:
4494 CoerceToDomain *ctest = (CoerceToDomain *) node;
4495 Node *arg = (Node *) ctest->arg;
4497 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
4500 /* don't show the implicit cast */
4501 get_rule_expr(arg, context, false);
4505 get_coercion_expr(arg, context,
4507 ctest->resulttypmod,
4513 case T_CoerceToDomainValue:
4514 appendStringInfo(buf, "VALUE");
4517 case T_SetToDefault:
4518 appendStringInfo(buf, "DEFAULT");
4521 case T_CurrentOfExpr:
4523 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
4525 if (cexpr->cursor_name)
4526 appendStringInfo(buf, "CURRENT OF %s",
4527 quote_identifier(cexpr->cursor_name));
4529 appendStringInfo(buf, "CURRENT OF $%d",
4530 cexpr->cursor_param);
4540 foreach(l, (List *) node)
4542 appendStringInfoString(buf, sep);
4543 get_rule_expr((Node *) lfirst(l), context, showimplicit);
4550 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
4557 * get_oper_expr - Parse back an OpExpr node
4560 get_oper_expr(OpExpr *expr, deparse_context *context)
4562 StringInfo buf = context->buf;
4563 Oid opno = expr->opno;
4564 List *args = expr->args;
4566 if (!PRETTY_PAREN(context))
4567 appendStringInfoChar(buf, '(');
4568 if (list_length(args) == 2)
4570 /* binary operator */
4571 Node *arg1 = (Node *) linitial(args);
4572 Node *arg2 = (Node *) lsecond(args);
4574 get_rule_expr_paren(arg1, context, true, (Node *) expr);
4575 appendStringInfo(buf, " %s ",
4576 generate_operator_name(opno,
4579 get_rule_expr_paren(arg2, context, true, (Node *) expr);
4583 /* unary operator --- but which side? */
4584 Node *arg = (Node *) linitial(args);
4586 Form_pg_operator optup;
4588 tp = SearchSysCache(OPEROID,
4589 ObjectIdGetDatum(opno),
4591 if (!HeapTupleIsValid(tp))
4592 elog(ERROR, "cache lookup failed for operator %u", opno);
4593 optup = (Form_pg_operator) GETSTRUCT(tp);
4594 switch (optup->oprkind)
4597 appendStringInfo(buf, "%s ",
4598 generate_operator_name(opno,
4601 get_rule_expr_paren(arg, context, true, (Node *) expr);
4604 get_rule_expr_paren(arg, context, true, (Node *) expr);
4605 appendStringInfo(buf, " %s",
4606 generate_operator_name(opno,
4611 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
4613 ReleaseSysCache(tp);
4615 if (!PRETTY_PAREN(context))
4616 appendStringInfoChar(buf, ')');
4620 * get_func_expr - Parse back a FuncExpr node
4623 get_func_expr(FuncExpr *expr, deparse_context *context,
4626 StringInfo buf = context->buf;
4627 Oid funcoid = expr->funcid;
4628 Oid argtypes[FUNC_MAX_ARGS];
4634 * If the function call came from an implicit coercion, then just show the
4635 * first argument --- unless caller wants to see implicit coercions.
4637 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
4639 get_rule_expr_paren((Node *) linitial(expr->args), context,
4640 false, (Node *) expr);
4645 * If the function call came from a cast, then show the first argument
4646 * plus an explicit cast operation.
4648 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
4649 expr->funcformat == COERCE_IMPLICIT_CAST)
4651 Node *arg = linitial(expr->args);
4652 Oid rettype = expr->funcresulttype;
4653 int32 coercedTypmod;
4655 /* Get the typmod if this is a length-coercion function */
4656 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
4658 get_coercion_expr(arg, context,
4659 rettype, coercedTypmod,
4666 * Normal function: display as proname(args). First we need to extract
4667 * the argument datatypes.
4670 foreach(l, expr->args)
4672 if (nargs >= FUNC_MAX_ARGS)
4674 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
4675 errmsg("too many arguments")));
4676 argtypes[nargs] = exprType((Node *) lfirst(l));
4680 appendStringInfo(buf, "%s(",
4681 generate_function_name(funcoid, nargs, argtypes,
4684 foreach(l, expr->args)
4687 appendStringInfoString(buf, ", ");
4688 if (is_variadic && lnext(l) == NULL)
4689 appendStringInfoString(buf, "VARIADIC ");
4690 get_rule_expr((Node *) lfirst(l), context, true);
4692 appendStringInfoChar(buf, ')');
4696 * get_agg_expr - Parse back an Aggref node
4699 get_agg_expr(Aggref *aggref, deparse_context *context)
4701 StringInfo buf = context->buf;
4702 Oid argtypes[FUNC_MAX_ARGS];
4707 foreach(l, aggref->args)
4709 if (nargs >= FUNC_MAX_ARGS)
4711 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
4712 errmsg("too many arguments")));
4713 argtypes[nargs] = exprType((Node *) lfirst(l));
4717 appendStringInfo(buf, "%s(%s",
4718 generate_function_name(aggref->aggfnoid,
4719 nargs, argtypes, NULL),
4720 aggref->aggdistinct ? "DISTINCT " : "");
4721 /* aggstar can be set only in zero-argument aggregates */
4722 if (aggref->aggstar)
4723 appendStringInfoChar(buf, '*');
4725 get_rule_expr((Node *) aggref->args, context, true);
4726 appendStringInfoChar(buf, ')');
4732 * Make a string representation of a value coerced to a specific type
4736 get_coercion_expr(Node *arg, deparse_context *context,
4737 Oid resulttype, int32 resulttypmod,
4740 StringInfo buf = context->buf;
4743 * Since parse_coerce.c doesn't immediately collapse application of
4744 * length-coercion functions to constants, what we'll typically see in
4745 * such cases is a Const with typmod -1 and a length-coercion function
4746 * right above it. Avoid generating redundant output. However, beware of
4747 * suppressing casts when the user actually wrote something like
4748 * 'foo'::text::char(3).
4750 if (arg && IsA(arg, Const) &&
4751 ((Const *) arg)->consttype == resulttype &&
4752 ((Const *) arg)->consttypmod == -1)
4754 /* Show the constant without normal ::typename decoration */
4755 get_const_expr((Const *) arg, context, -1);
4759 if (!PRETTY_PAREN(context))
4760 appendStringInfoChar(buf, '(');
4761 get_rule_expr_paren(arg, context, false, parentNode);
4762 if (!PRETTY_PAREN(context))
4763 appendStringInfoChar(buf, ')');
4765 appendStringInfo(buf, "::%s",
4766 format_type_with_typemod(resulttype, resulttypmod));
4772 * Make a string representation of a Const
4774 * showtype can be -1 to never show "::typename" decoration, or +1 to always
4775 * show it, or 0 to show it only if the constant wouldn't be assumed to be
4776 * the right type by default.
4780 get_const_expr(Const *constval, deparse_context *context, int showtype)
4782 StringInfo buf = context->buf;
4786 bool isfloat = false;
4789 if (constval->constisnull)
4792 * Always label the type of a NULL constant to prevent misdecisions
4793 * about type when reparsing.
4795 appendStringInfo(buf, "NULL");
4797 appendStringInfo(buf, "::%s",
4798 format_type_with_typemod(constval->consttype,
4799 constval->consttypmod));
4803 getTypeOutputInfo(constval->consttype,
4804 &typoutput, &typIsVarlena);
4806 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
4808 switch (constval->consttype)
4819 * These types are printed without quotes unless they contain
4820 * values that aren't accepted by the scanner unquoted (e.g.,
4821 * 'NaN'). Note that strtod() and friends might accept NaN,
4822 * so we can't use that to test.
4824 * In reality we only need to defend against infinity and NaN,
4825 * so we need not get too crazy about pattern matching here.
4827 * There is a special-case gotcha: if the constant is signed,
4828 * we need to parenthesize it, else the parser might see a
4829 * leading plus/minus as binding less tightly than adjacent
4830 * operators --- particularly, the cast that we might attach
4833 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
4835 if (extval[0] == '+' || extval[0] == '-')
4836 appendStringInfo(buf, "(%s)", extval);
4838 appendStringInfoString(buf, extval);
4839 if (strcspn(extval, "eE.") != strlen(extval))
4840 isfloat = true; /* it looks like a float */
4843 appendStringInfo(buf, "'%s'", extval);
4849 appendStringInfo(buf, "B'%s'", extval);
4853 if (strcmp(extval, "t") == 0)
4854 appendStringInfo(buf, "true");
4856 appendStringInfo(buf, "false");
4860 simple_quote_literal(buf, extval);
4870 * For showtype == 0, append ::typename unless the constant will be
4871 * implicitly typed as the right type when it is read in.
4873 * XXX this code has to be kept in sync with the behavior of the parser,
4874 * especially make_const.
4876 switch (constval->consttype)
4881 /* These types can be left unlabeled */
4887 * Float-looking constants will be typed as numeric, but if
4888 * there's a specific typmod we need to show it.
4890 needlabel = !isfloat || (constval->consttypmod >= 0);
4896 if (needlabel || showtype > 0)
4897 appendStringInfo(buf, "::%s",
4898 format_type_with_typemod(constval->consttype,
4899 constval->consttypmod));
4903 * simple_quote_literal - Format a string as a SQL literal, append to buf
4906 simple_quote_literal(StringInfo buf, const char *val)
4911 * We form the string literal according to the prevailing setting
4912 * of standard_conforming_strings; we never use E''. User is
4913 * responsible for making sure result is used correctly.
4915 appendStringInfoChar(buf, '\'');
4916 for (valptr = val; *valptr; valptr++)
4920 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
4921 appendStringInfoChar(buf, ch);
4922 appendStringInfoChar(buf, ch);
4924 appendStringInfoChar(buf, '\'');
4929 * get_sublink_expr - Parse back a sublink
4933 get_sublink_expr(SubLink *sublink, deparse_context *context)
4935 StringInfo buf = context->buf;
4936 Query *query = (Query *) (sublink->subselect);
4937 char *opname = NULL;
4940 if (sublink->subLinkType == ARRAY_SUBLINK)
4941 appendStringInfo(buf, "ARRAY(");
4943 appendStringInfoChar(buf, '(');
4946 * Note that we print the name of only the first operator, when there are
4947 * multiple combining operators. This is an approximation that could go
4948 * wrong in various scenarios (operators in different schemas, renamed
4949 * operators, etc) but there is not a whole lot we can do about it, since
4950 * the syntax allows only one operator to be shown.
4952 if (sublink->testexpr)
4954 if (IsA(sublink->testexpr, OpExpr))
4956 /* single combining operator */
4957 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
4959 get_rule_expr(linitial(opexpr->args), context, true);
4960 opname = generate_operator_name(opexpr->opno,
4961 exprType(linitial(opexpr->args)),
4962 exprType(lsecond(opexpr->args)));
4964 else if (IsA(sublink->testexpr, BoolExpr))
4966 /* multiple combining operators, = or <> cases */
4970 appendStringInfoChar(buf, '(');
4972 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
4974 OpExpr *opexpr = (OpExpr *) lfirst(l);
4976 Assert(IsA(opexpr, OpExpr));
4977 appendStringInfoString(buf, sep);
4978 get_rule_expr(linitial(opexpr->args), context, true);
4980 opname = generate_operator_name(opexpr->opno,
4981 exprType(linitial(opexpr->args)),
4982 exprType(lsecond(opexpr->args)));
4985 appendStringInfoChar(buf, ')');
4987 else if (IsA(sublink->testexpr, RowCompareExpr))
4989 /* multiple combining operators, < <= > >= cases */
4990 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
4992 appendStringInfoChar(buf, '(');
4993 get_rule_expr((Node *) rcexpr->largs, context, true);
4994 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
4995 exprType(linitial(rcexpr->largs)),
4996 exprType(linitial(rcexpr->rargs)));
4997 appendStringInfoChar(buf, ')');
5000 elog(ERROR, "unrecognized testexpr type: %d",
5001 (int) nodeTag(sublink->testexpr));
5006 switch (sublink->subLinkType)
5008 case EXISTS_SUBLINK:
5009 appendStringInfo(buf, "EXISTS ");
5013 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5014 appendStringInfo(buf, " IN ");
5016 appendStringInfo(buf, " %s ANY ", opname);
5020 appendStringInfo(buf, " %s ALL ", opname);
5023 case ROWCOMPARE_SUBLINK:
5024 appendStringInfo(buf, " %s ", opname);
5033 elog(ERROR, "unrecognized sublink type: %d",
5034 (int) sublink->subLinkType);
5039 appendStringInfoChar(buf, '(');
5041 get_query_def(query, buf, context->namespaces, NULL,
5042 context->prettyFlags, context->indentLevel);
5045 appendStringInfo(buf, "))");
5047 appendStringInfoChar(buf, ')');
5052 * get_from_clause - Parse back a FROM clause
5054 * "prefix" is the keyword that denotes the start of the list of FROM
5055 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5056 * is USING when parsing back DELETE.
5060 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5062 StringInfo buf = context->buf;
5067 * We use the query's jointree as a guide to what to print. However, we
5068 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5069 * only appear at the top level of the jointree, so it's sufficient to
5070 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5073 foreach(l, query->jointree->fromlist)
5075 Node *jtnode = (Node *) lfirst(l);
5077 if (IsA(jtnode, RangeTblRef))
5079 int varno = ((RangeTblRef *) jtnode)->rtindex;
5080 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5088 appendContextKeyword(context, prefix,
5089 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5093 appendStringInfoString(buf, ", ");
5095 get_from_clause_item(jtnode, query, context);
5100 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5102 StringInfo buf = context->buf;
5104 if (IsA(jtnode, RangeTblRef))
5106 int varno = ((RangeTblRef *) jtnode)->rtindex;
5107 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5108 bool gavealias = false;
5110 switch (rte->rtekind)
5113 /* Normal relation RTE */
5114 appendStringInfo(buf, "%s%s",
5116 generate_relation_name(rte->relid));
5120 appendStringInfoChar(buf, '(');
5121 get_query_def(rte->subquery, buf, context->namespaces, NULL,
5122 context->prettyFlags, context->indentLevel);
5123 appendStringInfoChar(buf, ')');
5127 get_rule_expr(rte->funcexpr, context, true);
5130 /* Values list RTE */
5131 get_values_def(rte->values_lists, context);
5134 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
5138 if (rte->alias != NULL)
5140 appendStringInfo(buf, " %s",
5141 quote_identifier(rte->alias->aliasname));
5144 else if (rte->rtekind == RTE_RELATION &&
5145 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
5148 * Apparently the rel has been renamed since the rule was made.
5149 * Emit a fake alias clause so that variable references will still
5150 * work. This is not a 100% solution but should work in most
5151 * reasonable situations.
5153 appendStringInfo(buf, " %s",
5154 quote_identifier(rte->eref->aliasname));
5157 else if (rte->rtekind == RTE_FUNCTION)
5160 * For a function RTE, always give an alias. This covers possible
5161 * renaming of the function and/or instability of the
5162 * FigureColname rules for things that aren't simple functions.
5164 appendStringInfo(buf, " %s",
5165 quote_identifier(rte->eref->aliasname));
5169 if (rte->rtekind == RTE_FUNCTION)
5171 if (rte->funccoltypes != NIL)
5173 /* Function returning RECORD, reconstruct the columndefs */
5175 appendStringInfo(buf, " AS ");
5176 get_from_clause_coldeflist(rte->eref->colnames,
5178 rte->funccoltypmods,
5184 * For a function RTE, always emit a complete column alias
5185 * list; this is to protect against possible instability of
5186 * the default column names (eg, from altering parameter
5189 get_from_clause_alias(rte->eref, rte, context);
5195 * For non-function RTEs, just report whatever the user originally
5196 * gave as column aliases.
5198 get_from_clause_alias(rte->alias, rte, context);
5201 else if (IsA(jtnode, JoinExpr))
5203 JoinExpr *j = (JoinExpr *) jtnode;
5204 bool need_paren_on_right;
5206 need_paren_on_right = PRETTY_PAREN(context) &&
5207 !IsA(j->rarg, RangeTblRef) &&
5208 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
5210 if (!PRETTY_PAREN(context) || j->alias != NULL)
5211 appendStringInfoChar(buf, '(');
5213 get_from_clause_item(j->larg, query, context);
5217 if (!PRETTY_INDENT(context))
5218 appendStringInfoChar(buf, ' ');
5219 switch (j->jointype)
5222 appendContextKeyword(context, "NATURAL JOIN ",
5224 PRETTYINDENT_JOIN, 0);
5227 appendContextKeyword(context, "NATURAL LEFT JOIN ",
5229 PRETTYINDENT_JOIN, 0);
5232 appendContextKeyword(context, "NATURAL FULL JOIN ",
5234 PRETTYINDENT_JOIN, 0);
5237 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
5239 PRETTYINDENT_JOIN, 0);
5242 elog(ERROR, "unrecognized join type: %d",
5248 switch (j->jointype)
5252 appendContextKeyword(context, " JOIN ",
5254 PRETTYINDENT_JOIN, 2);
5256 appendContextKeyword(context, " CROSS JOIN ",
5258 PRETTYINDENT_JOIN, 1);
5261 appendContextKeyword(context, " LEFT JOIN ",
5263 PRETTYINDENT_JOIN, 2);
5266 appendContextKeyword(context, " FULL JOIN ",
5268 PRETTYINDENT_JOIN, 2);
5271 appendContextKeyword(context, " RIGHT JOIN ",
5273 PRETTYINDENT_JOIN, 2);
5276 elog(ERROR, "unrecognized join type: %d",
5281 if (need_paren_on_right)
5282 appendStringInfoChar(buf, '(');
5283 get_from_clause_item(j->rarg, query, context);
5284 if (need_paren_on_right)
5285 appendStringInfoChar(buf, ')');
5287 context->indentLevel -= PRETTYINDENT_JOIN_ON;
5295 appendStringInfo(buf, " USING (");
5296 foreach(col, j->using)
5298 if (col != list_head(j->using))
5299 appendStringInfo(buf, ", ");
5300 appendStringInfoString(buf,
5301 quote_identifier(strVal(lfirst(col))));
5303 appendStringInfoChar(buf, ')');
5307 appendStringInfo(buf, " ON ");
5308 if (!PRETTY_PAREN(context))
5309 appendStringInfoChar(buf, '(');
5310 get_rule_expr(j->quals, context, false);
5311 if (!PRETTY_PAREN(context))
5312 appendStringInfoChar(buf, ')');
5315 if (!PRETTY_PAREN(context) || j->alias != NULL)
5316 appendStringInfoChar(buf, ')');
5318 /* Yes, it's correct to put alias after the right paren ... */
5319 if (j->alias != NULL)
5321 appendStringInfo(buf, " %s",
5322 quote_identifier(j->alias->aliasname));
5323 get_from_clause_alias(j->alias,
5324 rt_fetch(j->rtindex, query->rtable),
5329 elog(ERROR, "unrecognized node type: %d",
5330 (int) nodeTag(jtnode));
5334 * get_from_clause_alias - reproduce column alias list
5336 * This is tricky because we must ignore dropped columns.
5339 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
5340 deparse_context *context)
5342 StringInfo buf = context->buf;
5347 if (alias == NULL || alias->colnames == NIL)
5348 return; /* definitely nothing to do */
5351 foreach(col, alias->colnames)
5354 if (get_rte_attribute_is_dropped(rte, attnum))
5358 appendStringInfoChar(buf, '(');
5362 appendStringInfo(buf, ", ");
5363 appendStringInfoString(buf,
5364 quote_identifier(strVal(lfirst(col))));
5367 appendStringInfoChar(buf, ')');
5371 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5373 * The coldeflist is appended immediately (no space) to buf. Caller is
5374 * responsible for ensuring that an alias or AS is present before it.
5377 get_from_clause_coldeflist(List *names, List *types, List *typmods,
5378 deparse_context *context)
5380 StringInfo buf = context->buf;
5386 appendStringInfoChar(buf, '(');
5388 l2 = list_head(types);
5389 l3 = list_head(typmods);
5392 char *attname = strVal(lfirst(l1));
5396 atttypid = lfirst_oid(l2);
5398 atttypmod = lfirst_int(l3);
5402 appendStringInfo(buf, ", ");
5403 appendStringInfo(buf, "%s %s",
5404 quote_identifier(attname),
5405 format_type_with_typemod(atttypid, atttypmod));
5409 appendStringInfoChar(buf, ')');
5413 * get_opclass_name - fetch name of an index operator class
5415 * The opclass name is appended (after a space) to buf.
5417 * Output is suppressed if the opclass is the default for the given
5418 * actual_datatype. (If you don't want this behavior, just pass
5419 * InvalidOid for actual_datatype.)
5422 get_opclass_name(Oid opclass, Oid actual_datatype,
5426 Form_pg_opclass opcrec;
5430 ht_opc = SearchSysCache(CLAOID,
5431 ObjectIdGetDatum(opclass),
5433 if (!HeapTupleIsValid(ht_opc))
5434 elog(ERROR, "cache lookup failed for opclass %u", opclass);
5435 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
5437 if (!OidIsValid(actual_datatype) ||
5438 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
5440 /* Okay, we need the opclass name. Do we need to qualify it? */
5441 opcname = NameStr(opcrec->opcname);
5442 if (OpclassIsVisible(opclass))
5443 appendStringInfo(buf, " %s", quote_identifier(opcname));
5446 nspname = get_namespace_name(opcrec->opcnamespace);
5447 appendStringInfo(buf, " %s.%s",
5448 quote_identifier(nspname),
5449 quote_identifier(opcname));
5452 ReleaseSysCache(ht_opc);
5456 * processIndirection - take care of array and subfield assignment
5458 * We strip any top-level FieldStore or assignment ArrayRef nodes that
5459 * appear in the input, and return the subexpression that's to be assigned.
5460 * If printit is true, we also print out the appropriate decoration for the
5461 * base column name (that the caller just printed).
5464 processIndirection(Node *node, deparse_context *context, bool printit)
5466 StringInfo buf = context->buf;
5472 if (IsA(node, FieldStore))
5474 FieldStore *fstore = (FieldStore *) node;
5478 /* lookup tuple type */
5479 typrelid = get_typ_typrelid(fstore->resulttype);
5480 if (!OidIsValid(typrelid))
5481 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
5482 format_type_be(fstore->resulttype));
5485 * Print the field name. Note we assume here that there's only
5486 * one field being assigned to. This is okay in stored rules but
5487 * could be wrong in executable target lists. Presently no
5488 * problem since explain.c doesn't print plan targetlists, but
5489 * someday may have to think of something ...
5491 fieldname = get_relid_attribute_name(typrelid,
5492 linitial_int(fstore->fieldnums));
5494 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
5497 * We ignore arg since it should be an uninteresting reference to
5498 * the target column or subcolumn.
5500 node = (Node *) linitial(fstore->newvals);
5502 else if (IsA(node, ArrayRef))
5504 ArrayRef *aref = (ArrayRef *) node;
5506 if (aref->refassgnexpr == NULL)
5509 printSubscripts(aref, context);
5512 * We ignore refexpr since it should be an uninteresting reference
5513 * to the target column or subcolumn.
5515 node = (Node *) aref->refassgnexpr;
5525 printSubscripts(ArrayRef *aref, deparse_context *context)
5527 StringInfo buf = context->buf;
5528 ListCell *lowlist_item;
5529 ListCell *uplist_item;
5531 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
5532 foreach(uplist_item, aref->refupperindexpr)
5534 appendStringInfoChar(buf, '[');
5537 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
5538 appendStringInfoChar(buf, ':');
5539 lowlist_item = lnext(lowlist_item);
5541 get_rule_expr((Node *) lfirst(uplist_item), context, false);
5542 appendStringInfoChar(buf, ']');
5547 * quote_identifier - Quote an identifier only if needed
5549 * When quotes are needed, we palloc the required space; slightly
5550 * space-wasteful but well worth it for notational simplicity.
5553 quote_identifier(const char *ident)
5556 * Can avoid quoting if ident starts with a lowercase letter or underscore
5557 * and contains only lowercase letters, digits, and underscores, *and* is
5558 * not any SQL keyword. Otherwise, supply quotes.
5567 * would like to use <ctype.h> macros here, but they might yield unwanted
5568 * locale-specific results...
5570 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
5572 for (ptr = ident; *ptr; ptr++)
5576 if ((ch >= 'a' && ch <= 'z') ||
5577 (ch >= '0' && ch <= '9') ||
5593 * Check for keyword. We quote keywords except for unreserved ones.
5594 * (In some cases we could avoid quoting a col_name or type_func_name
5595 * keyword, but it seems much harder than it's worth to tell that.)
5597 * Note: ScanKeywordLookup() does case-insensitive comparison, but
5598 * that's fine, since we already know we have all-lower-case.
5600 const ScanKeyword *keyword = ScanKeywordLookup(ident);
5602 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
5607 return ident; /* no change needed */
5609 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
5613 for (ptr = ident; *ptr; ptr++)
5628 * quote_qualified_identifier - Quote a possibly-qualified identifier
5630 * Return a name of the form namespace.ident, or just ident if namespace
5631 * is NULL, quoting each component if necessary. The result is palloc'd.
5634 quote_qualified_identifier(const char *namespace,
5639 initStringInfo(&buf);
5641 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
5642 appendStringInfoString(&buf, quote_identifier(ident));
5647 * generate_relation_name
5648 * Compute the name to display for a relation specified by OID
5650 * The result includes all necessary quoting and schema-prefixing.
5653 generate_relation_name(Oid relid)
5656 Form_pg_class reltup;
5660 tp = SearchSysCache(RELOID,
5661 ObjectIdGetDatum(relid),
5663 if (!HeapTupleIsValid(tp))
5664 elog(ERROR, "cache lookup failed for relation %u", relid);
5665 reltup = (Form_pg_class) GETSTRUCT(tp);
5667 /* Qualify the name if not visible in search path */
5668 if (RelationIsVisible(relid))
5671 nspname = get_namespace_name(reltup->relnamespace);
5673 result = quote_qualified_identifier(nspname, NameStr(reltup->relname));
5675 ReleaseSysCache(tp);
5681 * generate_function_name
5682 * Compute the name to display for a function specified by OID,
5683 * given that it is being called with the specified actual arg types.
5684 * (Arg types matter because of ambiguous-function resolution rules.)
5686 * The result includes all necessary quoting and schema-prefixing. We can
5687 * also pass back an indication of whether the function is variadic.
5690 generate_function_name(Oid funcid, int nargs, Oid *argtypes,
5694 Form_pg_proc procform;
5698 FuncDetailCode p_result;
5703 Oid *p_true_typeids;
5705 proctup = SearchSysCache(PROCOID,
5706 ObjectIdGetDatum(funcid),
5708 if (!HeapTupleIsValid(proctup))
5709 elog(ERROR, "cache lookup failed for function %u", funcid);
5710 procform = (Form_pg_proc) GETSTRUCT(proctup);
5711 proname = NameStr(procform->proname);
5712 Assert(nargs >= procform->pronargs);
5715 * The idea here is to schema-qualify only if the parser would fail to
5716 * resolve the correct function given the unqualified func name with the
5717 * specified argtypes.
5719 p_result = func_get_detail(list_make1(makeString(proname)),
5720 NIL, nargs, argtypes, false,
5721 &p_funcid, &p_rettype,
5722 &p_retset, &p_nvargs, &p_true_typeids);
5723 if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
5727 nspname = get_namespace_name(procform->pronamespace);
5729 result = quote_qualified_identifier(nspname, proname);
5731 /* Check variadic-ness if caller cares */
5734 /* "any" variadics are not treated as variadics for listing */
5735 if (OidIsValid(procform->provariadic) &&
5736 procform->provariadic != ANYOID)
5737 *is_variadic = true;
5739 *is_variadic = false;
5742 ReleaseSysCache(proctup);
5748 * generate_operator_name
5749 * Compute the name to display for an operator specified by OID,
5750 * given that it is being called with the specified actual arg types.
5751 * (Arg types matter because of ambiguous-operator resolution rules.
5752 * Pass InvalidOid for unused arg of a unary operator.)
5754 * The result includes all necessary quoting and schema-prefixing,
5755 * plus the OPERATOR() decoration needed to use a qualified operator name
5759 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
5763 Form_pg_operator operform;
5768 initStringInfo(&buf);
5770 opertup = SearchSysCache(OPEROID,
5771 ObjectIdGetDatum(operid),
5773 if (!HeapTupleIsValid(opertup))
5774 elog(ERROR, "cache lookup failed for operator %u", operid);
5775 operform = (Form_pg_operator) GETSTRUCT(opertup);
5776 oprname = NameStr(operform->oprname);
5779 * The idea here is to schema-qualify only if the parser would fail to
5780 * resolve the correct operator given the unqualified op name with the
5781 * specified argtypes.
5783 switch (operform->oprkind)
5786 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
5790 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
5794 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
5798 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
5799 p_result = NULL; /* keep compiler quiet */
5803 if (p_result != NULL && oprid(p_result) == operid)
5807 nspname = get_namespace_name(operform->oprnamespace);
5808 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
5811 appendStringInfoString(&buf, oprname);
5814 appendStringInfoChar(&buf, ')');
5816 if (p_result != NULL)
5817 ReleaseSysCache(p_result);
5819 ReleaseSysCache(opertup);
5825 * Given a C string, produce a TEXT datum.
5827 * We assume that the input was palloc'd and may be freed.
5830 string_to_text(char *str)
5834 result = cstring_to_text(str);
5840 * Generate a C string representing a relation's reloptions, or NULL if none.
5843 flatten_reloptions(Oid relid)
5845 char *result = NULL;
5850 tuple = SearchSysCache(RELOID,
5851 ObjectIdGetDatum(relid),
5853 if (!HeapTupleIsValid(tuple))
5854 elog(ERROR, "cache lookup failed for relation %u", relid);
5856 reloptions = SysCacheGetAttr(RELOID, tuple,
5857 Anum_pg_class_reloptions, &isnull);
5864 * We want to use array_to_text(reloptions, ', ') --- but
5865 * DirectFunctionCall2(array_to_text) does not work, because
5866 * array_to_text() relies on flinfo to be valid. So use
5869 sep = CStringGetTextDatum(", ");
5870 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
5871 result = TextDatumGetCString(txt);
5874 ReleaseSysCache(tuple);