1 /**********************************************************************
2 * ruleutils.c - Functions to convert stored expressions/querytrees
6 * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.173 2004/06/18 06:13:49 tgl Exp $
8 * This software is copyrighted by Jan Wieck - Hamburg.
10 * The author hereby grants permission to use, copy, modify,
11 * distribute, and license this software and its documentation
12 * for any purpose, provided that existing copyright notices are
13 * retained in all copies and that this notice is included
14 * verbatim in any distributions. No written agreement, license,
15 * or royalty fee is required for any of the authorized uses.
16 * Modifications to this software may be copyrighted by their
17 * author and need not follow the licensing terms described
18 * here, provided that the new terms are clearly indicated on
19 * the first page of each file where they apply.
21 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
22 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
23 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
24 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
25 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
28 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
32 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
33 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
34 * ENHANCEMENTS, OR MODIFICATIONS.
36 **********************************************************************/
43 #include "access/genam.h"
44 #include "catalog/catname.h"
45 #include "catalog/heap.h"
46 #include "catalog/index.h"
47 #include "catalog/indexing.h"
48 #include "catalog/namespace.h"
49 #include "catalog/pg_cast.h"
50 #include "catalog/pg_constraint.h"
51 #include "catalog/pg_index.h"
52 #include "catalog/pg_opclass.h"
53 #include "catalog/pg_operator.h"
54 #include "catalog/pg_shadow.h"
55 #include "catalog/pg_trigger.h"
56 #include "commands/tablespace.h"
57 #include "executor/spi.h"
58 #include "lib/stringinfo.h"
59 #include "nodes/makefuncs.h"
60 #include "optimizer/clauses.h"
61 #include "optimizer/tlist.h"
62 #include "parser/keywords.h"
63 #include "parser/parse_expr.h"
64 #include "parser/parse_func.h"
65 #include "parser/parse_oper.h"
66 #include "parser/parse_type.h"
67 #include "parser/parsetree.h"
68 #include "rewrite/rewriteManip.h"
69 #include "rewrite/rewriteSupport.h"
70 #include "utils/array.h"
71 #include "utils/fmgroids.h"
72 #include "utils/lsyscache.h"
73 #include "utils/typcache.h"
77 * Pretty formatting constants
82 #define PRETTYINDENT_STD 8
83 #define PRETTYINDENT_JOIN 13
84 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
85 #define PRETTYINDENT_VAR 4
88 #define PRETTYFLAG_PAREN 1
89 #define PRETTYFLAG_INDENT 2
91 /* macro to test if pretty action needed */
92 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
93 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
101 /* Context info needed for invoking a recursive querytree display routine */
104 StringInfo buf; /* output buffer to append to */
105 List *namespaces; /* List of deparse_namespace nodes */
106 int prettyFlags; /* enabling of pretty-print functions */
107 int indentLevel; /* current indent level for prettyprint */
108 bool varprefix; /* TRUE to print prefixes on Vars */
112 * Each level of query context around a subtree needs a level of Var namespace.
113 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
114 * the current context's namespaces list.
116 * The rangetable is the list of actual RTEs from the query tree.
118 * For deparsing plan trees, we allow two special RTE entries that are not
119 * part of the rtable list (mainly because they don't have consecutively
124 List *rtable; /* List of RangeTblEntry nodes */
125 int outer_varno; /* varno for outer_rte */
126 RangeTblEntry *outer_rte; /* special RangeTblEntry, or NULL */
127 int inner_varno; /* varno for inner_rte */
128 RangeTblEntry *inner_rte; /* special RangeTblEntry, or NULL */
136 static void *plan_getrulebyoid = NULL;
137 static char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
138 static void *plan_getviewrule = NULL;
139 static char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
145 * Most of these functions used to use fixed-size buffers to build their
146 * results. Now, they take an (already initialized) StringInfo object
147 * as a parameter, and append their text output to its contents.
150 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
151 bool forceprefix, bool showimplicit,
152 int prettyFlags, int startIndent);
153 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
154 static void decompile_column_index_array(Datum column_index_array, Oid relId,
156 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
157 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
159 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
161 static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
163 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
165 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
167 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
168 TupleDesc resultDesc, int prettyFlags, int startIndent);
169 static void get_select_query_def(Query *query, deparse_context *context,
170 TupleDesc resultDesc);
171 static void get_insert_query_def(Query *query, deparse_context *context);
172 static void get_update_query_def(Query *query, deparse_context *context);
173 static void get_delete_query_def(Query *query, deparse_context *context);
174 static void get_utility_query_def(Query *query, deparse_context *context);
175 static void get_basic_select_query(Query *query, deparse_context *context,
176 TupleDesc resultDesc);
177 static void get_setop_query(Node *setOp, Query *query,
178 deparse_context *context,
179 TupleDesc resultDesc);
180 static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist,
182 deparse_context *context);
183 static void get_names_for_var(Var *var, deparse_context *context,
184 char **schemaname, char **refname, char **attname);
185 static RangeTblEntry *find_rte_by_refname(const char *refname,
186 deparse_context *context);
187 static const char *get_simple_binary_op_name(OpExpr *expr);
188 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
189 static void appendStringInfoSpaces(StringInfo buf, int count);
190 static void appendContextKeyword(deparse_context *context, const char *str,
191 int indentBefore, int indentAfter, int indentPlus);
192 static void get_rule_expr(Node *node, deparse_context *context,
194 static void get_oper_expr(OpExpr *expr, deparse_context *context);
195 static void get_func_expr(FuncExpr *expr, deparse_context *context,
197 static void get_agg_expr(Aggref *aggref, deparse_context *context);
198 static void get_const_expr(Const *constval, deparse_context *context);
199 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
200 static void get_from_clause(Query *query, deparse_context *context);
201 static void get_from_clause_item(Node *jtnode, Query *query,
202 deparse_context *context);
203 static void get_from_clause_coldeflist(List *coldeflist,
204 deparse_context *context);
205 static void get_opclass_name(Oid opclass, Oid actual_datatype,
207 static Node *processIndirection(Node *node, deparse_context *context);
208 static void printSubscripts(ArrayRef *aref, deparse_context *context);
209 static char *generate_relation_name(Oid relid);
210 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes);
211 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
212 static void print_operator_name(StringInfo buf, List *opname);
213 static text *string_to_text(char *str);
215 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
219 * get_ruledef - Do it all and return a text
220 * that could be used as a statement
221 * to recreate the rule
225 pg_get_ruledef(PG_FUNCTION_ARGS)
227 Oid ruleoid = PG_GETARG_OID(0);
229 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
234 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
236 Oid ruleoid = PG_GETARG_OID(0);
237 bool pretty = PG_GETARG_BOOL(1);
240 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
241 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
246 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
256 * Do this first so that string is alloc'd in outer context not SPI's.
258 initStringInfo(&buf);
261 * Connect to SPI manager
263 if (SPI_connect() != SPI_OK_CONNECT)
264 elog(ERROR, "SPI_connect failed");
267 * On the first call prepare the plan to lookup pg_rewrite. We read
268 * pg_rewrite over the SPI manager instead of using the syscache to be
269 * checked for read access on pg_rewrite.
271 if (plan_getrulebyoid == NULL)
276 argtypes[0] = OIDOID;
277 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
279 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
280 plan_getrulebyoid = SPI_saveplan(plan);
284 * Get the pg_rewrite tuple for this rule
286 args[0] = ObjectIdGetDatum(ruleoid);
288 spirc = SPI_execp(plan_getrulebyoid, args, nulls, 1);
289 if (spirc != SPI_OK_SELECT)
290 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
291 if (SPI_processed != 1)
292 appendStringInfo(&buf, "-");
296 * Get the rules definition and put it into executors memory
298 ruletup = SPI_tuptable->vals[0];
299 rulettc = SPI_tuptable->tupdesc;
300 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
304 * Disconnect from SPI manager
306 if (SPI_finish() != SPI_OK_FINISH)
307 elog(ERROR, "SPI_finish failed");
314 * get_viewdef - Mainly the same thing, but we
315 * only return the SELECT part of a view
319 pg_get_viewdef(PG_FUNCTION_ARGS)
322 Oid viewoid = PG_GETARG_OID(0);
324 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
329 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
332 Oid viewoid = PG_GETARG_OID(0);
333 bool pretty = PG_GETARG_BOOL(1);
336 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
337 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
341 pg_get_viewdef_name(PG_FUNCTION_ARGS)
343 /* By qualified name */
344 text *viewname = PG_GETARG_TEXT_P(0);
348 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname,
350 viewoid = RangeVarGetRelid(viewrel, false);
352 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
357 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
359 /* By qualified name */
360 text *viewname = PG_GETARG_TEXT_P(0);
361 bool pretty = PG_GETARG_BOOL(1);
366 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
367 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname,
369 viewoid = RangeVarGetRelid(viewrel, false);
371 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
375 * Common code for by-OID and by-name variants of pg_get_viewdef
378 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
388 * Do this first so that string is alloc'd in outer context not SPI's.
390 initStringInfo(&buf);
393 * Connect to SPI manager
395 if (SPI_connect() != SPI_OK_CONNECT)
396 elog(ERROR, "SPI_connect failed");
399 * On the first call prepare the plan to lookup pg_rewrite. We read
400 * pg_rewrite over the SPI manager instead of using the syscache to be
401 * checked for read access on pg_rewrite.
403 if (plan_getviewrule == NULL)
408 argtypes[0] = OIDOID;
409 argtypes[1] = NAMEOID;
410 plan = SPI_prepare(query_getviewrule, 2, argtypes);
412 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
413 plan_getviewrule = SPI_saveplan(plan);
417 * Get the pg_rewrite tuple for the view's SELECT rule
419 args[0] = ObjectIdGetDatum(viewoid);
420 args[1] = PointerGetDatum(ViewSelectRuleName);
423 spirc = SPI_execp(plan_getviewrule, args, nulls, 2);
424 if (spirc != SPI_OK_SELECT)
425 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
426 if (SPI_processed != 1)
427 appendStringInfo(&buf, "Not a view");
431 * Get the rules definition and put it into executors memory
433 ruletup = SPI_tuptable->vals[0];
434 rulettc = SPI_tuptable->tupdesc;
435 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
439 * Disconnect from SPI manager
441 if (SPI_finish() != SPI_OK_FINISH)
442 elog(ERROR, "SPI_finish failed");
448 * get_triggerdef - Get the definition of a trigger
452 pg_get_triggerdef(PG_FUNCTION_ARGS)
454 Oid trigid = PG_GETARG_OID(0);
456 Form_pg_trigger trigrec;
465 * Fetch the pg_trigger tuple by the Oid of the trigger
467 tgrel = heap_openr(TriggerRelationName, AccessShareLock);
469 ScanKeyInit(&skey[0],
470 ObjectIdAttributeNumber,
471 BTEqualStrategyNumber, F_OIDEQ,
472 ObjectIdGetDatum(trigid));
474 tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
475 SnapshotNow, 1, skey);
477 ht_trig = systable_getnext(tgscan);
479 if (!HeapTupleIsValid(ht_trig))
480 elog(ERROR, "could not find tuple for trigger %u", trigid);
482 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
485 * Start the trigger definition. Note that the trigger's name should
486 * never be schema-qualified, but the trigger rel's name may be.
488 initStringInfo(&buf);
490 tgname = NameStr(trigrec->tgname);
491 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
492 trigrec->tgisconstraint ? "CONSTRAINT " : "",
493 quote_identifier(tgname));
495 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
496 appendStringInfo(&buf, "BEFORE");
498 appendStringInfo(&buf, "AFTER");
499 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
501 appendStringInfo(&buf, " INSERT");
504 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
507 appendStringInfo(&buf, " OR DELETE");
509 appendStringInfo(&buf, " DELETE");
512 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
515 appendStringInfo(&buf, " OR UPDATE");
517 appendStringInfo(&buf, " UPDATE");
519 appendStringInfo(&buf, " ON %s ",
520 generate_relation_name(trigrec->tgrelid));
522 if (trigrec->tgisconstraint)
524 if (trigrec->tgconstrrelid != InvalidOid)
525 appendStringInfo(&buf, "FROM %s ",
526 generate_relation_name(trigrec->tgconstrrelid));
527 if (!trigrec->tgdeferrable)
528 appendStringInfo(&buf, "NOT ");
529 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
530 if (trigrec->tginitdeferred)
531 appendStringInfo(&buf, "DEFERRED ");
533 appendStringInfo(&buf, "IMMEDIATE ");
537 if (TRIGGER_FOR_ROW(trigrec->tgtype))
538 appendStringInfo(&buf, "FOR EACH ROW ");
540 appendStringInfo(&buf, "FOR EACH STATEMENT ");
542 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
543 generate_function_name(trigrec->tgfoid, 0, NULL));
545 if (trigrec->tgnargs > 0)
552 val = (bytea *) fastgetattr(ht_trig,
553 Anum_pg_trigger_tgargs,
554 tgrel->rd_att, &isnull);
556 elog(ERROR, "tgargs is null for trigger %u", trigid);
557 p = (char *) VARDATA(val);
558 for (i = 0; i < trigrec->tgnargs; i++)
561 appendStringInfo(&buf, ", ");
562 appendStringInfoChar(&buf, '\'');
565 /* escape quotes and backslashes */
566 if (*p == '\'' || *p == '\\')
567 appendStringInfoChar(&buf, '\\');
568 appendStringInfoChar(&buf, *p++);
571 appendStringInfoChar(&buf, '\'');
575 /* We deliberately do not put semi-colon at end */
576 appendStringInfo(&buf, ")");
579 systable_endscan(tgscan);
581 heap_close(tgrel, AccessShareLock);
583 PG_RETURN_TEXT_P(string_to_text(buf.data));
587 * get_indexdef - Get the definition of an index
589 * In the extended version, there is a colno argument as well as pretty bool.
590 * if colno == 0, we want a complete index definition.
591 * if colno > 0, we only want the Nth index key's variable or expression.
595 pg_get_indexdef(PG_FUNCTION_ARGS)
597 Oid indexrelid = PG_GETARG_OID(0);
599 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, 0)));
603 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
605 Oid indexrelid = PG_GETARG_OID(0);
606 int32 colno = PG_GETARG_INT32(1);
607 bool pretty = PG_GETARG_BOOL(2);
610 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
611 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, prettyFlags)));
614 /* Internal version that returns a palloc'd C string */
616 pg_get_indexdef_string(Oid indexrelid)
618 return pg_get_indexdef_worker(indexrelid, 0, 0);
622 pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
627 Form_pg_index idxrec;
628 Form_pg_class idxrelrec;
631 ListCell *indexpr_item;
641 * Fetch the pg_index tuple by the Oid of the index
643 ht_idx = SearchSysCache(INDEXRELID,
644 ObjectIdGetDatum(indexrelid),
646 if (!HeapTupleIsValid(ht_idx))
647 elog(ERROR, "cache lookup failed for index %u", indexrelid);
648 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
650 indrelid = idxrec->indrelid;
651 Assert(indexrelid == idxrec->indexrelid);
654 * Fetch the pg_class tuple of the index relation
656 ht_idxrel = SearchSysCache(RELOID,
657 ObjectIdGetDatum(indexrelid),
659 if (!HeapTupleIsValid(ht_idxrel))
660 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
661 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
664 * Fetch the pg_am tuple of the index' access method
666 ht_am = SearchSysCache(AMOID,
667 ObjectIdGetDatum(idxrelrec->relam),
669 if (!HeapTupleIsValid(ht_am))
670 elog(ERROR, "cache lookup failed for access method %u",
672 amrec = (Form_pg_am) GETSTRUCT(ht_am);
675 * Get the index expressions, if any. (NOTE: we do not use the
676 * relcache versions of the expressions and predicate, because we want
677 * to display non-const-folded expressions.)
679 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
685 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
686 Anum_pg_index_indexprs, &isnull);
688 exprsString = DatumGetCString(DirectFunctionCall1(textout,
690 indexprs = (List *) stringToNode(exprsString);
696 indexpr_item = list_head(indexprs);
698 context = deparse_context_for(get_rel_name(indrelid), indrelid);
701 * Start the index definition. Note that the index's name should
702 * never be schema-qualified, but the indexed rel's name may be.
704 initStringInfo(&buf);
707 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
708 idxrec->indisunique ? "UNIQUE " : "",
709 quote_identifier(NameStr(idxrelrec->relname)),
710 generate_relation_name(indrelid),
711 quote_identifier(NameStr(amrec->amname)));
714 * Report the indexed attributes
717 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
719 AttrNumber attnum = idxrec->indkey[keyno];
722 appendStringInfo(&buf, sep);
727 /* Simple index column */
730 attname = get_relid_attribute_name(indrelid, attnum);
731 if (!colno || colno == keyno + 1)
732 appendStringInfoString(&buf, quote_identifier(attname));
733 keycoltype = get_atttype(indrelid, attnum);
737 /* expressional index */
740 if (indexpr_item == NULL)
741 elog(ERROR, "too few entries in indexprs list");
742 indexkey = (Node *) lfirst(indexpr_item);
743 indexpr_item = lnext(indexpr_item);
745 str = deparse_expression_pretty(indexkey, context, false, false,
747 if (!colno || colno == keyno + 1)
749 /* Need parens if it's not a bare function call */
750 if (indexkey && IsA(indexkey, FuncExpr) &&
751 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
752 appendStringInfoString(&buf, str);
754 appendStringInfo(&buf, "(%s)", str);
756 keycoltype = exprType(indexkey);
760 * Add the operator class name
763 get_opclass_name(idxrec->indclass[keyno], keycoltype,
769 appendStringInfoChar(&buf, ')');
772 * If the index is in a different tablespace from its parent,
775 if (OidIsValid(idxrelrec->reltablespace) &&
776 idxrelrec->reltablespace != get_rel_tablespace(indrelid))
778 char *spcname = get_tablespace_name(idxrelrec->reltablespace);
780 if (spcname) /* just paranoia... */
782 appendStringInfo(&buf, " TABLESPACE %s",
783 quote_identifier(spcname));
789 * If it's a partial index, decompile and append the predicate
791 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
798 /* Convert text string to node tree */
799 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
800 Anum_pg_index_indpred, &isnull);
802 predString = DatumGetCString(DirectFunctionCall1(textout,
804 node = (Node *) stringToNode(predString);
808 str = deparse_expression_pretty(node, context, false, false,
810 appendStringInfo(&buf, " WHERE %s", str);
815 ReleaseSysCache(ht_idx);
816 ReleaseSysCache(ht_idxrel);
817 ReleaseSysCache(ht_am);
824 * pg_get_constraintdef
826 * Returns the definition for the constraint, ie, everything that needs to
827 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
830 pg_get_constraintdef(PG_FUNCTION_ARGS)
832 Oid constraintId = PG_GETARG_OID(0);
834 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
839 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
841 Oid constraintId = PG_GETARG_OID(0);
842 bool pretty = PG_GETARG_BOOL(1);
845 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
846 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
847 false, prettyFlags)));
850 /* Internal version that returns a palloc'd C string */
852 pg_get_constraintdef_string(Oid constraintId)
854 return pg_get_constraintdef_worker(constraintId, true, 0);
858 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
866 Form_pg_constraint conForm;
869 * Fetch the pg_constraint row. There's no syscache for pg_constraint
870 * so we must do it the hard way.
872 conDesc = heap_openr(ConstraintRelationName, AccessShareLock);
874 ScanKeyInit(&skey[0],
875 ObjectIdAttributeNumber,
876 BTEqualStrategyNumber, F_OIDEQ,
877 ObjectIdGetDatum(constraintId));
879 conscan = systable_beginscan(conDesc, ConstraintOidIndex, true,
880 SnapshotNow, 1, skey);
882 tup = systable_getnext(conscan);
883 if (!HeapTupleIsValid(tup))
884 elog(ERROR, "could not find tuple for constraint %u", constraintId);
885 conForm = (Form_pg_constraint) GETSTRUCT(tup);
887 initStringInfo(&buf);
889 if (fullCommand && OidIsValid(conForm->conrelid))
891 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
892 generate_relation_name(conForm->conrelid),
893 quote_identifier(NameStr(conForm->conname)));
896 switch (conForm->contype)
898 case CONSTRAINT_FOREIGN:
904 /* Start off the constraint definition */
905 appendStringInfo(&buf, "FOREIGN KEY (");
907 /* Fetch and build referencing-column list */
908 val = heap_getattr(tup, Anum_pg_constraint_conkey,
909 RelationGetDescr(conDesc), &isnull);
911 elog(ERROR, "null conkey for constraint %u",
914 decompile_column_index_array(val, conForm->conrelid, &buf);
916 /* add foreign relation name */
917 appendStringInfo(&buf, ") REFERENCES %s(",
918 generate_relation_name(conForm->confrelid));
920 /* Fetch and build referenced-column list */
921 val = heap_getattr(tup, Anum_pg_constraint_confkey,
922 RelationGetDescr(conDesc), &isnull);
924 elog(ERROR, "null confkey for constraint %u",
927 decompile_column_index_array(val, conForm->confrelid, &buf);
929 appendStringInfo(&buf, ")");
932 switch (conForm->confmatchtype)
934 case FKCONSTR_MATCH_FULL:
935 string = " MATCH FULL";
937 case FKCONSTR_MATCH_PARTIAL:
938 string = " MATCH PARTIAL";
940 case FKCONSTR_MATCH_UNSPECIFIED:
944 elog(ERROR, "unrecognized confmatchtype: %d",
945 conForm->confmatchtype);
946 string = ""; /* keep compiler quiet */
949 appendStringInfoString(&buf, string);
951 /* Add ON UPDATE and ON DELETE clauses, if needed */
952 switch (conForm->confupdtype)
954 case FKCONSTR_ACTION_NOACTION:
955 string = NULL; /* suppress default */
957 case FKCONSTR_ACTION_RESTRICT:
960 case FKCONSTR_ACTION_CASCADE:
963 case FKCONSTR_ACTION_SETNULL:
966 case FKCONSTR_ACTION_SETDEFAULT:
967 string = "SET DEFAULT";
970 elog(ERROR, "unrecognized confupdtype: %d",
971 conForm->confupdtype);
972 string = NULL; /* keep compiler quiet */
976 appendStringInfo(&buf, " ON UPDATE %s", string);
978 switch (conForm->confdeltype)
980 case FKCONSTR_ACTION_NOACTION:
981 string = NULL; /* suppress default */
983 case FKCONSTR_ACTION_RESTRICT:
986 case FKCONSTR_ACTION_CASCADE:
989 case FKCONSTR_ACTION_SETNULL:
992 case FKCONSTR_ACTION_SETDEFAULT:
993 string = "SET DEFAULT";
996 elog(ERROR, "unrecognized confdeltype: %d",
997 conForm->confdeltype);
998 string = NULL; /* keep compiler quiet */
1002 appendStringInfo(&buf, " ON DELETE %s", string);
1004 if (conForm->condeferrable)
1005 appendStringInfo(&buf, " DEFERRABLE");
1006 if (conForm->condeferred)
1007 appendStringInfo(&buf, " INITIALLY DEFERRED");
1011 case CONSTRAINT_PRIMARY:
1012 case CONSTRAINT_UNIQUE:
1017 /* Start off the constraint definition */
1018 if (conForm->contype == CONSTRAINT_PRIMARY)
1019 appendStringInfo(&buf, "PRIMARY KEY (");
1021 appendStringInfo(&buf, "UNIQUE (");
1023 /* Fetch and build target column list */
1024 val = heap_getattr(tup, Anum_pg_constraint_conkey,
1025 RelationGetDescr(conDesc), &isnull);
1027 elog(ERROR, "null conkey for constraint %u",
1030 decompile_column_index_array(val, conForm->conrelid, &buf);
1032 appendStringInfo(&buf, ")");
1036 case CONSTRAINT_CHECK:
1045 /* Fetch constraint expression in parsetree form */
1046 val = heap_getattr(tup, Anum_pg_constraint_conbin,
1047 RelationGetDescr(conDesc), &isnull);
1049 elog(ERROR, "null conbin for constraint %u",
1052 conbin = DatumGetCString(DirectFunctionCall1(textout, val));
1053 expr = stringToNode(conbin);
1055 /* Set up deparsing context for Var nodes in constraint */
1056 if (conForm->conrelid != InvalidOid)
1058 /* relation constraint */
1059 context = deparse_context_for(get_rel_name(conForm->conrelid),
1064 /* domain constraint --- can't have Vars */
1068 consrc = deparse_expression_pretty(expr, context, false, false,
1072 * Now emit the constraint definition. There are cases where
1073 * the constraint expression will be fully parenthesized and
1074 * we don't need the outer parens ... but there are other
1075 * cases where we do need 'em. Be conservative for now.
1077 * Note that simply checking for leading '(' and trailing ')'
1078 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1080 appendStringInfo(&buf, "CHECK (%s)", consrc);
1085 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1090 systable_endscan(conscan);
1091 heap_close(conDesc, AccessShareLock);
1098 * Convert an int16[] Datum into a comma-separated list of column names
1099 * for the indicated relation; append the list to buf.
1102 decompile_column_index_array(Datum column_index_array, Oid relId,
1109 /* Extract data from array of int16 */
1110 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1111 INT2OID, 2, true, 's',
1114 for (j = 0; j < nKeys; j++)
1118 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1121 appendStringInfoString(buf, quote_identifier(colName));
1123 appendStringInfo(buf, ", %s", quote_identifier(colName));
1129 * get_expr - Decompile an expression tree
1131 * Input: an expression tree in nodeToString form, and a relation OID
1133 * Output: reverse-listed expression
1135 * Currently, the expression can only refer to a single relation, namely
1136 * the one specified by the second parameter. This is sufficient for
1137 * partial indexes, column default expressions, etc.
1141 pg_get_expr(PG_FUNCTION_ARGS)
1143 text *expr = PG_GETARG_TEXT_P(0);
1144 Oid relid = PG_GETARG_OID(1);
1147 /* Get the name for the relation */
1148 relname = get_rel_name(relid);
1149 if (relname == NULL)
1150 PG_RETURN_NULL(); /* should we raise an error? */
1152 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1156 pg_get_expr_ext(PG_FUNCTION_ARGS)
1158 text *expr = PG_GETARG_TEXT_P(0);
1159 Oid relid = PG_GETARG_OID(1);
1160 bool pretty = PG_GETARG_BOOL(2);
1164 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1166 /* Get the name for the relation */
1167 relname = get_rel_name(relid);
1168 if (relname == NULL)
1169 PG_RETURN_NULL(); /* should we raise an error? */
1171 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1175 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1182 /* Convert input TEXT object to C string */
1183 exprstr = DatumGetCString(DirectFunctionCall1(textout,
1184 PointerGetDatum(expr)));
1186 /* Convert expression to node tree */
1187 node = (Node *) stringToNode(exprstr);
1190 context = deparse_context_for(relname, relid);
1191 str = deparse_expression_pretty(node, context, false, false,
1199 * get_userbyid - Get a user name by usesysid and
1200 * fallback to 'unknown (UID=n)'
1204 pg_get_userbyid(PG_FUNCTION_ARGS)
1206 int32 uid = PG_GETARG_INT32(0);
1209 Form_pg_shadow user_rec;
1212 * Allocate space for the result
1214 result = (Name) palloc(NAMEDATALEN);
1215 memset(NameStr(*result), 0, NAMEDATALEN);
1218 * Get the pg_shadow entry and print the result
1220 usertup = SearchSysCache(SHADOWSYSID,
1221 ObjectIdGetDatum(uid),
1223 if (HeapTupleIsValid(usertup))
1225 user_rec = (Form_pg_shadow) GETSTRUCT(usertup);
1226 StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);
1227 ReleaseSysCache(usertup);
1230 sprintf(NameStr(*result), "unknown (UID=%d)", uid);
1232 PG_RETURN_NAME(result);
1236 * deparse_expression - General utility for deparsing expressions
1238 * calls deparse_expression_pretty with all prettyPrinting disabled
1241 deparse_expression(Node *expr, List *dpcontext,
1242 bool forceprefix, bool showimplicit)
1244 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1245 showimplicit, 0, 0);
1249 * deparse_expression_pretty - General utility for deparsing expressions
1251 * expr is the node tree to be deparsed. It must be a transformed expression
1252 * tree (ie, not the raw output of gram.y).
1254 * dpcontext is a list of deparse_namespace nodes representing the context
1255 * for interpreting Vars in the node tree.
1257 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1259 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1261 * tries to pretty up the output according to prettyFlags and startIndent.
1263 * The result is a palloc'd string.
1267 deparse_expression_pretty(Node *expr, List *dpcontext,
1268 bool forceprefix, bool showimplicit,
1269 int prettyFlags, int startIndent)
1272 deparse_context context;
1274 initStringInfo(&buf);
1276 context.namespaces = dpcontext;
1277 context.varprefix = forceprefix;
1278 context.prettyFlags = prettyFlags;
1279 context.indentLevel = startIndent;
1281 get_rule_expr(expr, &context, showimplicit);
1287 * deparse_context_for - Build deparse context for a single relation
1289 * Given the reference name (alias) and OID of a relation, build deparsing
1290 * context for an expression referencing only that relation (as varno 1,
1291 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1295 deparse_context_for(const char *aliasname, Oid relid)
1297 deparse_namespace *dpns;
1300 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1302 /* Build a minimal RTE for the rel */
1303 rte = makeNode(RangeTblEntry);
1304 rte->rtekind = RTE_RELATION;
1306 rte->eref = makeAlias(aliasname, NIL);
1308 rte->inFromCl = true;
1310 /* Build one-element rtable */
1311 dpns->rtable = list_make1(rte);
1312 dpns->outer_varno = dpns->inner_varno = 0;
1313 dpns->outer_rte = dpns->inner_rte = NULL;
1315 /* Return a one-deep namespace stack */
1316 return list_make1(dpns);
1320 * deparse_context_for_plan - Build deparse context for a plan node
1322 * We assume we are dealing with an upper-level plan node having either
1323 * one or two referenceable children (pass innercontext = NULL if only one).
1324 * The passed-in Nodes should be made using deparse_context_for_subplan
1325 * and/or deparse_context_for_relation. The resulting context will work
1326 * for deparsing quals, tlists, etc of the plan node.
1328 * An rtable list can also be passed in case plain Vars might be seen.
1329 * This is not needed for true upper-level expressions, but is helpful for
1330 * Sort nodes and similar cases with slightly bogus targetlists.
1333 deparse_context_for_plan(int outer_varno, Node *outercontext,
1334 int inner_varno, Node *innercontext,
1337 deparse_namespace *dpns;
1339 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1341 dpns->rtable = rtable;
1342 dpns->outer_varno = outer_varno;
1343 dpns->outer_rte = (RangeTblEntry *) outercontext;
1344 dpns->inner_varno = inner_varno;
1345 dpns->inner_rte = (RangeTblEntry *) innercontext;
1347 /* Return a one-deep namespace stack */
1348 return list_make1(dpns);
1352 * deparse_context_for_rte - Build deparse context for 1 relation
1354 * Helper routine to build one of the inputs for deparse_context_for_plan.
1356 * The returned node is actually the given RangeTblEntry, but we declare it
1357 * as just Node to discourage callers from assuming anything.
1360 deparse_context_for_rte(RangeTblEntry *rte)
1362 return (Node *) rte;
1366 * deparse_context_for_subplan - Build deparse context for a plan node
1368 * Helper routine to build one of the inputs for deparse_context_for_plan.
1369 * Pass the tlist of the subplan node, plus the query rangetable.
1371 * The returned node is actually a RangeTblEntry, but we declare it as just
1372 * Node to discourage callers from assuming anything.
1375 deparse_context_for_subplan(const char *name, List *tlist,
1378 RangeTblEntry *rte = makeNode(RangeTblEntry);
1381 int rtablelength = list_length(rtable);
1387 TargetEntry *tle = lfirst(tl);
1388 Resdom *resdom = tle->resdom;
1391 Assert(resdom->resno == nattrs);
1392 if (resdom->resname)
1394 attrs = lappend(attrs, makeString(resdom->resname));
1397 if (tle->expr && IsA(tle->expr, Var))
1399 Var *var = (Var *) tle->expr;
1401 /* varno/varattno won't be any good, but varnoold might be */
1402 if (var->varnoold > 0 && var->varnoold <= rtablelength)
1404 RangeTblEntry *varrte = rt_fetch(var->varnoold, rtable);
1407 varname = get_rte_attribute_name(varrte, var->varoattno);
1408 attrs = lappend(attrs, makeString(varname));
1412 /* Fallback if can't get name */
1413 snprintf(buf, sizeof(buf), "?column%d?", resdom->resno);
1414 attrs = lappend(attrs, makeString(pstrdup(buf)));
1417 rte->rtekind = RTE_SPECIAL; /* XXX */
1418 rte->relid = InvalidOid;
1419 rte->eref = makeAlias(name, attrs);
1421 rte->inFromCl = true;
1423 return (Node *) rte;
1427 * make_ruledef - reconstruct the CREATE RULE command
1428 * for a given pg_rewrite tuple
1432 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1442 List *actions = NIL;
1448 * Get the attribute values from the rules tuple
1450 fno = SPI_fnumber(rulettc, "rulename");
1451 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1453 rulename = NameStr(*(DatumGetName(dat)));
1455 fno = SPI_fnumber(rulettc, "ev_type");
1456 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1458 ev_type = DatumGetChar(dat);
1460 fno = SPI_fnumber(rulettc, "ev_class");
1461 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1463 ev_class = DatumGetObjectId(dat);
1465 fno = SPI_fnumber(rulettc, "ev_attr");
1466 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1468 ev_attr = DatumGetInt16(dat);
1470 fno = SPI_fnumber(rulettc, "is_instead");
1471 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1473 is_instead = DatumGetBool(dat);
1475 /* these could be nulls */
1476 fno = SPI_fnumber(rulettc, "ev_qual");
1477 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1479 fno = SPI_fnumber(rulettc, "ev_action");
1480 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1481 if (ev_action != NULL)
1482 actions = (List *) stringToNode(ev_action);
1485 * Build the rules definition text
1487 appendStringInfo(buf, "CREATE RULE %s AS",
1488 quote_identifier(rulename));
1490 if (prettyFlags & PRETTYFLAG_INDENT)
1491 appendStringInfoString(buf, "\n ON ");
1493 appendStringInfoString(buf, " ON ");
1495 /* The event the rule is fired for */
1499 appendStringInfo(buf, "SELECT");
1503 appendStringInfo(buf, "UPDATE");
1507 appendStringInfo(buf, "INSERT");
1511 appendStringInfo(buf, "DELETE");
1516 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1517 errmsg("rule \"%s\" has unsupported event type %d",
1518 rulename, ev_type)));
1522 /* The relation the rule is fired on */
1523 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class));
1525 appendStringInfo(buf, ".%s",
1526 quote_identifier(get_relid_attribute_name(ev_class,
1529 /* If the rule has an event qualification, add it */
1530 if (ev_qual == NULL)
1532 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
1536 deparse_context context;
1537 deparse_namespace dpns;
1539 if (prettyFlags & PRETTYFLAG_INDENT)
1540 appendStringInfoString(buf, "\n ");
1541 appendStringInfo(buf, " WHERE ");
1543 qual = stringToNode(ev_qual);
1546 * We need to make a context for recognizing any Vars in the qual
1547 * (which can only be references to OLD and NEW). Use the rtable
1548 * of the first query in the action list for this purpose.
1550 query = (Query *) linitial(actions);
1553 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
1554 * into the SELECT, and that's what we need to look at. (Ugly
1555 * kluge ... try to fix this when we redesign querytrees.)
1557 query = getInsertSelectQuery(query, NULL);
1560 context.namespaces = list_make1(&dpns);
1561 context.varprefix = (list_length(query->rtable) != 1);
1562 context.prettyFlags = prettyFlags;
1563 context.indentLevel = PRETTYINDENT_STD;
1564 dpns.rtable = query->rtable;
1565 dpns.outer_varno = dpns.inner_varno = 0;
1566 dpns.outer_rte = dpns.inner_rte = NULL;
1568 get_rule_expr(qual, &context, false);
1571 appendStringInfo(buf, " DO ");
1573 /* The INSTEAD keyword (if so) */
1575 appendStringInfo(buf, "INSTEAD ");
1577 /* Finally the rules actions */
1578 if (list_length(actions) > 1)
1583 appendStringInfo(buf, "(");
1584 foreach(action, actions)
1586 query = (Query *) lfirst(action);
1587 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
1589 appendStringInfo(buf, ";\n");
1591 appendStringInfo(buf, "; ");
1593 appendStringInfo(buf, ");");
1595 else if (list_length(actions) == 0)
1597 appendStringInfo(buf, "NOTHING;");
1603 query = (Query *) linitial(actions);
1604 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
1605 appendStringInfo(buf, ";");
1611 * make_viewdef - reconstruct the SELECT part of a
1616 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1626 List *actions = NIL;
1627 Relation ev_relation;
1632 * Get the attribute values from the rules tuple
1634 fno = SPI_fnumber(rulettc, "ev_type");
1635 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1637 fno = SPI_fnumber(rulettc, "ev_class");
1638 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1640 fno = SPI_fnumber(rulettc, "ev_attr");
1641 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1643 fno = SPI_fnumber(rulettc, "is_instead");
1644 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1646 fno = SPI_fnumber(rulettc, "ev_qual");
1647 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1649 fno = SPI_fnumber(rulettc, "ev_action");
1650 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1651 if (ev_action != NULL)
1652 actions = (List *) stringToNode(ev_action);
1654 if (list_length(actions) != 1)
1656 appendStringInfo(buf, "Not a view");
1660 query = (Query *) linitial(actions);
1662 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
1663 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
1665 appendStringInfo(buf, "Not a view");
1669 ev_relation = heap_open(ev_class, AccessShareLock);
1671 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
1673 appendStringInfo(buf, ";");
1675 heap_close(ev_relation, AccessShareLock);
1680 * get_query_def - Parse back one query parsetree
1682 * If resultDesc is not NULL, then it is the output tuple descriptor for
1683 * the view represented by a SELECT query.
1687 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
1688 TupleDesc resultDesc, int prettyFlags, int startIndent)
1690 deparse_context context;
1691 deparse_namespace dpns;
1694 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
1695 context.varprefix = (parentnamespace != NIL ||
1696 list_length(query->rtable) != 1);
1697 context.prettyFlags = prettyFlags;
1698 context.indentLevel = startIndent;
1700 dpns.rtable = query->rtable;
1701 dpns.outer_varno = dpns.inner_varno = 0;
1702 dpns.outer_rte = dpns.inner_rte = NULL;
1704 switch (query->commandType)
1707 get_select_query_def(query, &context, resultDesc);
1711 get_update_query_def(query, &context);
1715 get_insert_query_def(query, &context);
1719 get_delete_query_def(query, &context);
1723 appendStringInfo(buf, "NOTHING");
1727 get_utility_query_def(query, &context);
1731 elog(ERROR, "unrecognized query command type: %d",
1732 query->commandType);
1739 * get_select_query_def - Parse back a SELECT parsetree
1743 get_select_query_def(Query *query, deparse_context *context,
1744 TupleDesc resultDesc)
1746 StringInfo buf = context->buf;
1752 * If the Query node has a setOperations tree, then it's the top level
1753 * of a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT
1754 * fields are interesting in the top query itself.
1756 if (query->setOperations)
1758 get_setop_query(query->setOperations, query, context, resultDesc);
1759 /* ORDER BY clauses must be simple in this case */
1764 get_basic_select_query(query, context, resultDesc);
1765 force_colno = false;
1768 /* Add the ORDER BY clause if given */
1769 if (query->sortClause != NIL)
1771 appendContextKeyword(context, " ORDER BY ",
1772 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
1774 foreach(l, query->sortClause)
1776 SortClause *srt = (SortClause *) lfirst(l);
1779 TypeCacheEntry *typentry;
1781 appendStringInfo(buf, sep);
1782 sortexpr = get_rule_sortgroupclause(srt, query->targetList,
1783 force_colno, context);
1784 sortcoltype = exprType(sortexpr);
1785 /* See whether operator is default < or > for datatype */
1786 typentry = lookup_type_cache(sortcoltype,
1787 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
1788 if (srt->sortop == typentry->lt_opr)
1789 /* ASC is default, so emit nothing */ ;
1790 else if (srt->sortop == typentry->gt_opr)
1791 appendStringInfo(buf, " DESC");
1793 appendStringInfo(buf, " USING %s",
1794 generate_operator_name(srt->sortop,
1801 /* Add the LIMIT clause if given */
1802 if (query->limitOffset != NULL)
1804 appendContextKeyword(context, " OFFSET ",
1805 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
1806 get_rule_expr(query->limitOffset, context, false);
1808 if (query->limitCount != NULL)
1810 appendContextKeyword(context, " LIMIT ",
1811 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
1812 if (IsA(query->limitCount, Const) &&
1813 ((Const *) query->limitCount)->constisnull)
1814 appendStringInfo(buf, "ALL");
1816 get_rule_expr(query->limitCount, context, false);
1821 get_basic_select_query(Query *query, deparse_context *context,
1822 TupleDesc resultDesc)
1824 StringInfo buf = context->buf;
1830 * Build up the query string - first we say SELECT
1832 if (PRETTY_INDENT(context))
1834 context->indentLevel += PRETTYINDENT_STD;
1835 appendStringInfoChar(buf, ' ');
1837 appendStringInfo(buf, "SELECT");
1839 /* Add the DISTINCT clause if given */
1840 if (query->distinctClause != NIL)
1842 if (has_distinct_on_clause(query))
1844 appendStringInfo(buf, " DISTINCT ON (");
1846 foreach(l, query->distinctClause)
1848 SortClause *srt = (SortClause *) lfirst(l);
1850 appendStringInfo(buf, sep);
1851 get_rule_sortgroupclause(srt, query->targetList,
1855 appendStringInfo(buf, ")");
1858 appendStringInfo(buf, " DISTINCT");
1861 /* Then we tell what to select (the targetlist) */
1864 foreach(l, query->targetList)
1866 TargetEntry *tle = (TargetEntry *) lfirst(l);
1869 if (tle->resdom->resjunk)
1870 continue; /* ignore junk entries */
1872 appendStringInfo(buf, sep);
1876 get_rule_expr((Node *) tle->expr, context, true);
1879 * Figure out what the result column should be called. In the
1880 * context of a view, use the view's tuple descriptor (so as to
1881 * pick up the effects of any column RENAME that's been done on
1882 * the view). Otherwise, just use what we can find in the TLE.
1884 if (resultDesc && colno <= resultDesc->natts)
1885 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
1887 colname = tle->resdom->resname;
1889 if (colname) /* resname could be NULL */
1891 /* Check if we must say AS ... */
1894 if (!IsA(tle->expr, Var))
1895 tell_as = (strcmp(colname, "?column?") != 0);
1898 Var *var = (Var *) (tle->expr);
1903 get_names_for_var(var, context,
1904 &schemaname, &refname, &attname);
1905 tell_as = (attname == NULL ||
1906 strcmp(attname, colname) != 0);
1911 appendStringInfo(buf, " AS %s", quote_identifier(colname));
1915 /* Add the FROM clause if needed */
1916 get_from_clause(query, context);
1918 /* Add the WHERE clause if given */
1919 if (query->jointree->quals != NULL)
1921 appendContextKeyword(context, " WHERE ",
1922 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
1923 get_rule_expr(query->jointree->quals, context, false);
1926 /* Add the GROUP BY clause if given */
1927 if (query->groupClause != NULL)
1929 appendContextKeyword(context, " GROUP BY ",
1930 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
1932 foreach(l, query->groupClause)
1934 GroupClause *grp = (GroupClause *) lfirst(l);
1936 appendStringInfo(buf, sep);
1937 get_rule_sortgroupclause(grp, query->targetList,
1943 /* Add the HAVING clause if given */
1944 if (query->havingQual != NULL)
1946 appendContextKeyword(context, " HAVING ",
1947 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
1948 get_rule_expr(query->havingQual, context, false);
1953 get_setop_query(Node *setOp, Query *query, deparse_context *context,
1954 TupleDesc resultDesc)
1956 StringInfo buf = context->buf;
1958 if (IsA(setOp, RangeTblRef))
1960 RangeTblRef *rtr = (RangeTblRef *) setOp;
1961 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
1962 Query *subquery = rte->subquery;
1964 Assert(subquery != NULL);
1965 get_query_def(subquery, buf, context->namespaces, resultDesc,
1966 context->prettyFlags, context->indentLevel);
1968 else if (IsA(setOp, SetOperationStmt))
1970 SetOperationStmt *op = (SetOperationStmt *) setOp;
1973 need_paren = (PRETTY_PAREN(context) ?
1974 !IsA(op->rarg, RangeTblRef) : true);
1976 if (!PRETTY_PAREN(context))
1977 appendStringInfoString(buf, "((");
1979 get_setop_query(op->larg, query, context, resultDesc);
1981 if (!PRETTY_PAREN(context))
1982 appendStringInfoChar(buf, ')');
1983 if (!PRETTY_INDENT(context))
1984 appendStringInfoChar(buf, ' ');
1988 appendContextKeyword(context, "UNION ",
1989 -PRETTYINDENT_STD, 0, 0);
1991 case SETOP_INTERSECT:
1992 appendContextKeyword(context, "INTERSECT ",
1993 -PRETTYINDENT_STD, 0, 0);
1996 appendContextKeyword(context, "EXCEPT ",
1997 -PRETTYINDENT_STD, 0, 0);
2000 elog(ERROR, "unrecognized set op: %d",
2004 appendStringInfo(buf, "ALL ");
2006 if (PRETTY_INDENT(context))
2007 appendStringInfoChar(buf, '\n');
2009 if (PRETTY_PAREN(context))
2013 appendStringInfoChar(buf, '(');
2014 if (PRETTY_INDENT(context))
2015 appendStringInfoChar(buf, '\n');
2019 appendStringInfoChar(buf, '(');
2021 get_setop_query(op->rarg, query, context, resultDesc);
2023 if (PRETTY_PAREN(context))
2026 appendStringInfoChar(buf, ')');
2029 appendStringInfoString(buf, "))");
2033 elog(ERROR, "unrecognized node type: %d",
2034 (int) nodeTag(setOp));
2039 * Display a sort/group clause.
2041 * Also returns the expression tree, so caller need not find it again.
2044 get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno,
2045 deparse_context *context)
2047 StringInfo buf = context->buf;
2051 tle = get_sortgroupclause_tle(srt, tlist);
2052 expr = (Node *) tle->expr;
2055 * Use column-number form if requested by caller or if expression is a
2056 * constant --- a constant is ambiguous (and will be misinterpreted by
2057 * findTargetlistEntry()) if we dump it explicitly.
2059 if (force_colno || (expr && IsA(expr, Const)))
2061 Assert(!tle->resdom->resjunk);
2062 appendStringInfo(buf, "%d", tle->resdom->resno);
2065 get_rule_expr(expr, context, true);
2071 * get_insert_query_def - Parse back an INSERT parsetree
2075 get_insert_query_def(Query *query, deparse_context *context)
2077 StringInfo buf = context->buf;
2078 RangeTblEntry *select_rte = NULL;
2082 List *strippedexprs;
2085 * If it's an INSERT ... SELECT there will be a single subquery RTE
2088 foreach(l, query->rtable)
2090 rte = (RangeTblEntry *) lfirst(l);
2091 if (rte->rtekind != RTE_SUBQUERY)
2094 elog(ERROR, "too many RTEs in INSERT");
2099 * Start the query with INSERT INTO relname
2101 rte = rt_fetch(query->resultRelation, query->rtable);
2102 Assert(rte->rtekind == RTE_RELATION);
2104 if (PRETTY_INDENT(context))
2106 context->indentLevel += PRETTYINDENT_STD;
2107 appendStringInfoChar(buf, ' ');
2109 appendStringInfo(buf, "INSERT INTO %s (",
2110 generate_relation_name(rte->relid));
2113 * Add the insert-column-names list, and make a list of the actual
2114 * assignment source expressions.
2116 strippedexprs = NIL;
2118 foreach(l, query->targetList)
2120 TargetEntry *tle = (TargetEntry *) lfirst(l);
2122 if (tle->resdom->resjunk)
2123 continue; /* ignore junk entries */
2125 appendStringInfo(buf, sep);
2129 * Put out name of target column; look in the catalogs, not at
2130 * tle->resname, since resname will fail to track RENAME.
2132 appendStringInfoString(buf,
2133 quote_identifier(get_relid_attribute_name(rte->relid,
2134 tle->resdom->resno)));
2137 * Print any indirection needed (subfields or subscripts), and strip
2138 * off the top-level nodes representing the indirection assignments.
2140 strippedexprs = lappend(strippedexprs,
2141 processIndirection((Node *) tle->expr,
2144 appendStringInfo(buf, ") ");
2146 /* Add the VALUES or the SELECT */
2147 if (select_rte == NULL)
2149 appendContextKeyword(context, "VALUES (",
2150 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
2152 foreach(l, strippedexprs)
2154 Node *expr = lfirst(l);
2156 appendStringInfo(buf, sep);
2158 get_rule_expr(expr, context, false);
2160 appendStringInfoChar(buf, ')');
2163 get_query_def(select_rte->subquery, buf, NIL, NULL,
2164 context->prettyFlags, context->indentLevel);
2169 * get_update_query_def - Parse back an UPDATE parsetree
2173 get_update_query_def(Query *query, deparse_context *context)
2175 StringInfo buf = context->buf;
2181 * Start the query with UPDATE relname SET
2183 rte = rt_fetch(query->resultRelation, query->rtable);
2184 Assert(rte->rtekind == RTE_RELATION);
2185 if (PRETTY_INDENT(context))
2187 appendStringInfoChar(buf, ' ');
2188 context->indentLevel += PRETTYINDENT_STD;
2190 appendStringInfo(buf, "UPDATE %s%s SET ",
2192 generate_relation_name(rte->relid));
2194 /* Add the comma separated list of 'attname = value' */
2196 foreach(l, query->targetList)
2198 TargetEntry *tle = (TargetEntry *) lfirst(l);
2201 if (tle->resdom->resjunk)
2202 continue; /* ignore junk entries */
2204 appendStringInfo(buf, sep);
2208 * Put out name of target column; look in the catalogs, not at
2209 * tle->resname, since resname will fail to track RENAME.
2211 appendStringInfoString(buf,
2212 quote_identifier(get_relid_attribute_name(rte->relid,
2213 tle->resdom->resno)));
2216 * Print any indirection needed (subfields or subscripts), and strip
2217 * off the top-level nodes representing the indirection assignments.
2219 expr = processIndirection((Node *) tle->expr, context);
2221 appendStringInfo(buf, " = ");
2223 get_rule_expr(expr, context, false);
2226 /* Add the FROM clause if needed */
2227 get_from_clause(query, context);
2229 /* Finally add a WHERE clause if given */
2230 if (query->jointree->quals != NULL)
2232 appendContextKeyword(context, " WHERE ",
2233 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2234 get_rule_expr(query->jointree->quals, context, false);
2240 * get_delete_query_def - Parse back a DELETE parsetree
2244 get_delete_query_def(Query *query, deparse_context *context)
2246 StringInfo buf = context->buf;
2250 * Start the query with DELETE FROM relname
2252 rte = rt_fetch(query->resultRelation, query->rtable);
2253 Assert(rte->rtekind == RTE_RELATION);
2254 if (PRETTY_INDENT(context))
2256 context->indentLevel += PRETTYINDENT_STD;
2257 appendStringInfoChar(buf, ' ');
2259 appendStringInfo(buf, "DELETE FROM %s%s",
2261 generate_relation_name(rte->relid));
2263 /* Add a WHERE clause if given */
2264 if (query->jointree->quals != NULL)
2266 appendContextKeyword(context, " WHERE ",
2267 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2268 get_rule_expr(query->jointree->quals, context, false);
2274 * get_utility_query_def - Parse back a UTILITY parsetree
2278 get_utility_query_def(Query *query, deparse_context *context)
2280 StringInfo buf = context->buf;
2282 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
2284 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
2286 appendContextKeyword(context, "",
2287 0, PRETTYINDENT_STD, 1);
2288 appendStringInfo(buf, "NOTIFY %s",
2289 quote_qualified_identifier(stmt->relation->schemaname,
2290 stmt->relation->relname));
2294 /* Currently only NOTIFY utility commands can appear in rules */
2295 elog(ERROR, "unexpected utility statement type");
2301 * Get the schemaname, refname and attname for a (possibly nonlocal) Var.
2303 * schemaname is usually returned as NULL. It will be non-null only if
2304 * use of the unqualified refname would find the wrong RTE.
2306 * refname will be returned as NULL if the Var references an unnamed join.
2307 * In this case the Var *must* be displayed without any qualification.
2309 * attname will be returned as NULL if the Var represents a whole tuple
2310 * of the relation. (Typically we'd want to display the Var as "foo.*",
2311 * but it's convenient to return NULL to make it easier for callers to
2312 * distinguish this case.)
2315 get_names_for_var(Var *var, deparse_context *context,
2316 char **schemaname, char **refname, char **attname)
2318 deparse_namespace *dpns;
2321 /* Find appropriate nesting depth */
2322 if (var->varlevelsup >= list_length(context->namespaces))
2323 elog(ERROR, "bogus varlevelsup: %d", var->varlevelsup);
2324 dpns = (deparse_namespace *) list_nth(context->namespaces,
2327 /* Find the relevant RTE */
2328 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
2329 rte = rt_fetch(var->varno, dpns->rtable);
2330 else if (var->varno == dpns->outer_varno)
2331 rte = dpns->outer_rte;
2332 else if (var->varno == dpns->inner_varno)
2333 rte = dpns->inner_rte;
2337 elog(ERROR, "bogus varno: %d", var->varno);
2340 *schemaname = NULL; /* default assumptions */
2341 *refname = rte->eref->aliasname;
2343 /* Exceptions occur only if the RTE is alias-less */
2344 if (rte->alias == NULL)
2346 if (rte->rtekind == RTE_RELATION)
2349 * It's possible that use of the bare refname would find
2350 * another more-closely-nested RTE, or be ambiguous, in which
2351 * case we need to specify the schemaname to avoid these
2354 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
2356 get_namespace_name(get_rel_namespace(rte->relid));
2358 else if (rte->rtekind == RTE_JOIN)
2360 /* Unnamed join has neither schemaname nor refname */
2365 if (var->varattno == InvalidAttrNumber)
2368 *attname = get_rte_attribute_name(rte, var->varattno);
2372 * find_rte_by_refname - look up an RTE by refname in a deparse context
2374 * Returns NULL if there is no matching RTE or the refname is ambiguous.
2376 * NOTE: this code is not really correct since it does not take account of
2377 * the fact that not all the RTEs in a rangetable may be visible from the
2378 * point where a Var reference appears. For the purposes we need, however,
2379 * the only consequence of a false match is that we might stick a schema
2380 * qualifier on a Var that doesn't really need it. So it seems close
2383 static RangeTblEntry *
2384 find_rte_by_refname(const char *refname, deparse_context *context)
2386 RangeTblEntry *result = NULL;
2389 foreach(nslist, context->namespaces)
2391 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
2394 foreach(rtlist, dpns->rtable)
2396 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
2398 if (strcmp(rte->eref->aliasname, refname) == 0)
2401 return NULL; /* it's ambiguous */
2405 if (dpns->outer_rte &&
2406 strcmp(dpns->outer_rte->eref->aliasname, refname) == 0)
2409 return NULL; /* it's ambiguous */
2410 result = dpns->outer_rte;
2412 if (dpns->inner_rte &&
2413 strcmp(dpns->inner_rte->eref->aliasname, refname) == 0)
2416 return NULL; /* it's ambiguous */
2417 result = dpns->inner_rte;
2427 * get_simple_binary_op_name
2429 * helper function for isSimpleNode
2430 * will return single char binary operator name, or NULL if it's not
2433 get_simple_binary_op_name(OpExpr *expr)
2435 List *args = expr->args;
2437 if (list_length(args) == 2)
2439 /* binary operator */
2440 Node *arg1 = (Node *) linitial(args);
2441 Node *arg2 = (Node *) lsecond(args);
2444 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
2445 if (strlen(op) == 1)
2453 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
2455 * true : simple in the context of parent node's type
2456 * false : not simple
2459 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
2464 switch (nodeTag(node))
2469 case T_CoerceToDomainValue:
2470 case T_SetToDefault:
2471 /* single words: always simple */
2477 case T_CoalesceExpr:
2481 /* function-like: name(..) or name[..] */
2484 /* CASE keywords act as parentheses */
2491 * appears simple since . has top precedence, unless parent is
2492 * T_FieldSelect itself!
2494 return (IsA(parentNode, FieldSelect) ? false : true);
2499 * treat like FieldSelect (probably doesn't matter)
2501 return (IsA(parentNode, FieldStore) ? false : true);
2503 case T_CoerceToDomain:
2504 /* maybe simple, check args */
2505 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
2508 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
2513 /* depends on parent node type; needs further checking */
2514 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
2517 const char *parentOp;
2520 bool is_lopriparent;
2521 bool is_hipriparent;
2523 op = get_simple_binary_op_name((OpExpr *) node);
2527 /* We know only the basic operators + - and * / % */
2528 is_lopriop = (strchr("+-", *op) != NULL);
2529 is_hipriop = (strchr("*/%", *op) != NULL);
2530 if (!(is_lopriop || is_hipriop))
2533 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
2537 is_lopriparent = (strchr("+-", *parentOp) != NULL);
2538 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
2539 if (!(is_lopriparent || is_hipriparent))
2542 if (is_hipriop && is_lopriparent)
2543 return true; /* op binds tighter than parent */
2545 if (is_lopriop && is_hipriparent)
2549 * Operators are same priority --- can skip parens
2550 * only if we have (a - b) - c, not a - (b - c).
2552 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
2557 /* else do the same stuff as for T_SubLink et al. */
2564 case T_DistinctExpr:
2565 switch (nodeTag(parentNode))
2569 /* special handling for casts */
2570 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
2572 if (type == COERCE_EXPLICIT_CAST ||
2573 type == COERCE_IMPLICIT_CAST)
2575 return true; /* own parentheses */
2577 case T_BoolExpr: /* lower precedence */
2578 case T_ArrayRef: /* other separators */
2579 case T_ArrayExpr: /* other separators */
2580 case T_RowExpr: /* other separators */
2581 case T_CoalesceExpr: /* own parentheses */
2582 case T_NullIfExpr: /* other separators */
2583 case T_Aggref: /* own parentheses */
2584 case T_CaseExpr: /* other separators */
2591 switch (nodeTag(parentNode))
2594 if (prettyFlags & PRETTYFLAG_PAREN)
2597 BoolExprType parentType;
2599 type = ((BoolExpr *) node)->boolop;
2600 parentType = ((BoolExpr *) parentNode)->boolop;
2605 if (parentType == AND_EXPR || parentType == OR_EXPR)
2609 if (parentType == OR_EXPR)
2617 /* special handling for casts */
2618 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
2620 if (type == COERCE_EXPLICIT_CAST ||
2621 type == COERCE_IMPLICIT_CAST)
2623 return true; /* own parentheses */
2625 case T_ArrayRef: /* other separators */
2626 case T_ArrayExpr: /* other separators */
2627 case T_RowExpr: /* other separators */
2628 case T_CoalesceExpr: /* own parentheses */
2629 case T_NullIfExpr: /* other separators */
2630 case T_Aggref: /* own parentheses */
2631 case T_CaseExpr: /* other separators */
2640 /* those we don't know: in dubio complexo */
2646 * appendStringInfoSpaces - append spaces to buffer
2649 appendStringInfoSpaces(StringInfo buf, int count)
2652 appendStringInfoChar(buf, ' ');
2656 * appendContextKeyword - append a keyword to buffer
2658 * If prettyPrint is enabled, perform a line break, and adjust indentation.
2659 * Otherwise, just append the keyword.
2662 appendContextKeyword(deparse_context *context, const char *str,
2663 int indentBefore, int indentAfter, int indentPlus)
2665 if (PRETTY_INDENT(context))
2667 context->indentLevel += indentBefore;
2668 if (context->indentLevel < 0)
2669 context->indentLevel = 0;
2671 appendStringInfoChar(context->buf, '\n');
2672 appendStringInfoSpaces(context->buf,
2673 context->indentLevel + indentPlus);
2676 appendStringInfoString(context->buf, str);
2678 if (PRETTY_INDENT(context))
2680 context->indentLevel += indentAfter;
2681 if (context->indentLevel < 0)
2682 context->indentLevel = 0;
2687 * get_rule_expr_paren - deparse expr using get_rule_expr,
2688 * embracing the string with parentheses if necessary for prettyPrint.
2690 * Never embrace if prettyFlags=0, because it's done in the calling node.
2692 * Any node that does *not* embrace its argument node by sql syntax (with
2693 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
2694 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
2698 get_rule_expr_paren(Node *node, deparse_context *context,
2699 bool showimplicit, Node *parentNode)
2703 need_paren = PRETTY_PAREN(context) &&
2704 !isSimpleNode(node, parentNode, context->prettyFlags);
2707 appendStringInfoChar(context->buf, '(');
2709 get_rule_expr(node, context, showimplicit);
2712 appendStringInfoChar(context->buf, ')');
2717 * get_rule_expr - Parse back an expression
2719 * Note: showimplicit determines whether we display any implicit cast that
2720 * is present at the top of the expression tree. It is a passed argument,
2721 * not a field of the context struct, because we change the value as we
2722 * recurse down into the expression. In general we suppress implicit casts
2723 * when the result type is known with certainty (eg, the arguments of an
2724 * OR must be boolean). We display implicit casts for arguments of functions
2725 * and operators, since this is needed to be certain that the same function
2726 * or operator will be chosen when the expression is re-parsed.
2730 get_rule_expr(Node *node, deparse_context *context,
2733 StringInfo buf = context->buf;
2739 * Each level of get_rule_expr must emit an indivisible term
2740 * (parenthesized if necessary) to ensure result is reparsed into the
2741 * same expression tree.
2743 * There might be some work left here to support additional node types.
2745 switch (nodeTag(node))
2749 Var *var = (Var *) node;
2754 get_names_for_var(var, context,
2755 &schemaname, &refname, &attname);
2756 if (refname && (context->varprefix || attname == NULL))
2759 appendStringInfo(buf, "%s.",
2760 quote_identifier(schemaname));
2762 if (strcmp(refname, "*NEW*") == 0)
2763 appendStringInfo(buf, "new.");
2764 else if (strcmp(refname, "*OLD*") == 0)
2765 appendStringInfo(buf, "old.");
2767 appendStringInfo(buf, "%s.",
2768 quote_identifier(refname));
2771 appendStringInfoString(buf, quote_identifier(attname));
2773 appendStringInfo(buf, "*");
2778 get_const_expr((Const *) node, context);
2783 Param *param = (Param *) node;
2785 switch (param->paramkind)
2788 appendStringInfo(buf, "$%s", param->paramname);
2792 appendStringInfo(buf, "$%d", param->paramid);
2795 appendStringInfo(buf, "(param)");
2802 get_agg_expr((Aggref *) node, context);
2807 ArrayRef *aref = (ArrayRef *) node;
2811 * Parenthesize the argument unless it's a simple Var or
2812 * a FieldSelect. (In particular, if it's another ArrayRef,
2813 * we *must* parenthesize to avoid confusion.)
2815 need_parens = !IsA(aref->refexpr, Var) &&
2816 !IsA(aref->refexpr, FieldSelect);
2818 appendStringInfoChar(buf, '(');
2819 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
2821 appendStringInfoChar(buf, ')');
2822 printSubscripts(aref, context);
2824 * Array assignment nodes should have been handled in
2825 * processIndirection().
2827 if (aref->refassgnexpr)
2828 elog(ERROR, "unexpected refassgnexpr");
2833 get_func_expr((FuncExpr *) node, context, showimplicit);
2837 get_oper_expr((OpExpr *) node, context);
2840 case T_DistinctExpr:
2842 DistinctExpr *expr = (DistinctExpr *) node;
2843 List *args = expr->args;
2844 Node *arg1 = (Node *) linitial(args);
2845 Node *arg2 = (Node *) lsecond(args);
2847 if (!PRETTY_PAREN(context))
2848 appendStringInfoChar(buf, '(');
2849 get_rule_expr_paren(arg1, context, true, node);
2850 appendStringInfo(buf, " IS DISTINCT FROM ");
2851 get_rule_expr_paren(arg2, context, true, node);
2852 if (!PRETTY_PAREN(context))
2853 appendStringInfoChar(buf, ')');
2857 case T_ScalarArrayOpExpr:
2859 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
2860 List *args = expr->args;
2861 Node *arg1 = (Node *) linitial(args);
2862 Node *arg2 = (Node *) lsecond(args);
2864 if (!PRETTY_PAREN(context))
2865 appendStringInfoChar(buf, '(');
2866 get_rule_expr_paren(arg1, context, true, node);
2867 appendStringInfo(buf, " %s %s (",
2868 generate_operator_name(expr->opno,
2870 get_element_type(exprType(arg2))),
2871 expr->useOr ? "ANY" : "ALL");
2872 get_rule_expr_paren(arg2, context, true, node);
2873 appendStringInfoChar(buf, ')');
2874 if (!PRETTY_PAREN(context))
2875 appendStringInfoChar(buf, ')');
2881 BoolExpr *expr = (BoolExpr *) node;
2882 Node *first_arg = linitial(expr->args);
2883 ListCell *arg = lnext(list_head(expr->args));
2885 switch (expr->boolop)
2888 if (!PRETTY_PAREN(context))
2889 appendStringInfoChar(buf, '(');
2890 get_rule_expr_paren(first_arg, context,
2894 appendStringInfo(buf, " AND ");
2895 get_rule_expr_paren((Node *) lfirst(arg), context,
2899 if (!PRETTY_PAREN(context))
2900 appendStringInfoChar(buf, ')');
2904 if (!PRETTY_PAREN(context))
2905 appendStringInfoChar(buf, '(');
2906 get_rule_expr_paren(first_arg, context,
2910 appendStringInfo(buf, " OR ");
2911 get_rule_expr_paren((Node *) lfirst(arg), context,
2915 if (!PRETTY_PAREN(context))
2916 appendStringInfoChar(buf, ')');
2920 if (!PRETTY_PAREN(context))
2921 appendStringInfoChar(buf, '(');
2922 appendStringInfo(buf, "NOT ");
2923 get_rule_expr_paren(first_arg, context,
2925 if (!PRETTY_PAREN(context))
2926 appendStringInfoChar(buf, ')');
2930 elog(ERROR, "unrecognized boolop: %d",
2931 (int) expr->boolop);
2937 get_sublink_expr((SubLink *) node, context);
2943 * We cannot see an already-planned subplan in rule
2944 * deparsing, only while EXPLAINing a query plan. For now,
2947 if (((SubPlan *) node)->useHashTable)
2948 appendStringInfo(buf, "(hashed subplan)");
2950 appendStringInfo(buf, "(subplan)");
2956 FieldSelect *fselect = (FieldSelect *) node;
2957 Oid argType = exprType((Node *) fselect->arg);
2962 /* lookup arg type and get the field name */
2963 typrelid = get_typ_typrelid(argType);
2964 if (!OidIsValid(typrelid))
2965 elog(ERROR, "argument type %s of FieldSelect is not a tuple type",
2966 format_type_be(argType));
2967 fieldname = get_relid_attribute_name(typrelid,
2970 * Parenthesize the argument unless it's an ArrayRef or
2971 * another FieldSelect. Note in particular that it would be
2972 * WRONG to not parenthesize a Var argument; simplicity is not
2973 * the issue here, having the right number of names is.
2975 need_parens = !IsA(fselect->arg, ArrayRef) &&
2976 !IsA(fselect->arg, FieldSelect);
2978 appendStringInfoChar(buf, '(');
2979 get_rule_expr((Node *) fselect->arg, context, true);
2981 appendStringInfoChar(buf, ')');
2982 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
2988 * We shouldn't see FieldStore here; it should have been
2989 * stripped off by processIndirection().
2991 elog(ERROR, "unexpected FieldStore");
2996 RelabelType *relabel = (RelabelType *) node;
2997 Node *arg = (Node *) relabel->arg;
2999 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
3002 /* don't show the implicit cast */
3003 get_rule_expr_paren(arg, context, false, node);
3007 if (!PRETTY_PAREN(context))
3008 appendStringInfoChar(buf, '(');
3009 get_rule_expr_paren(arg, context, false, node);
3010 if (!PRETTY_PAREN(context))
3011 appendStringInfoChar(buf, ')');
3012 appendStringInfo(buf, "::%s",
3013 format_type_with_typemod(relabel->resulttype,
3014 relabel->resulttypmod));
3021 CaseExpr *caseexpr = (CaseExpr *) node;
3024 appendContextKeyword(context, "CASE",
3025 0, PRETTYINDENT_VAR, 0);
3028 appendStringInfoChar(buf, ' ');
3029 get_rule_expr((Node *) caseexpr->arg, context, true);
3031 foreach(temp, caseexpr->args)
3033 CaseWhen *when = (CaseWhen *) lfirst(temp);
3035 if (!PRETTY_INDENT(context))
3036 appendStringInfoChar(buf, ' ');
3037 appendContextKeyword(context, "WHEN ",
3041 /* Show only the RHS of "CaseTestExpr = RHS" */
3044 Assert(IsA(when->expr, OpExpr));
3045 rhs = (Node *) lsecond(((OpExpr *) when->expr)->args);
3046 get_rule_expr(rhs, context, false);
3049 get_rule_expr((Node *) when->expr, context, false);
3050 appendStringInfo(buf, " THEN ");
3051 get_rule_expr((Node *) when->result, context, true);
3053 if (!PRETTY_INDENT(context))
3054 appendStringInfoChar(buf, ' ');
3055 appendContextKeyword(context, "ELSE ",
3057 get_rule_expr((Node *) caseexpr->defresult, context, true);
3058 if (!PRETTY_INDENT(context))
3059 appendStringInfoChar(buf, ' ');
3060 appendContextKeyword(context, "END",
3061 -PRETTYINDENT_VAR, 0, 0);
3067 ArrayExpr *arrayexpr = (ArrayExpr *) node;
3071 appendStringInfo(buf, "ARRAY[");
3073 foreach(element, arrayexpr->elements)
3075 Node *e = (Node *) lfirst(element);
3077 appendStringInfo(buf, sep);
3078 get_rule_expr(e, context, true);
3081 appendStringInfo(buf, "]");
3087 RowExpr *rowexpr = (RowExpr *) node;
3092 * SQL99 allows "ROW" to be omitted when list_length(args) > 1,
3093 * but for simplicity we always print it.
3095 appendStringInfo(buf, "ROW(");
3097 foreach(arg, rowexpr->args)
3099 Node *e = (Node *) lfirst(arg);
3101 appendStringInfo(buf, sep);
3102 get_rule_expr(e, context, true);
3105 appendStringInfo(buf, ")");
3106 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
3107 appendStringInfo(buf, "::%s",
3108 format_type_with_typemod(rowexpr->row_typeid, -1));
3112 case T_CoalesceExpr:
3114 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
3118 appendStringInfo(buf, "COALESCE(");
3120 foreach(arg, coalesceexpr->args)
3122 Node *e = (Node *) lfirst(arg);
3124 appendStringInfo(buf, sep);
3125 get_rule_expr(e, context, true);
3128 appendStringInfo(buf, ")");
3134 NullIfExpr *nullifexpr = (NullIfExpr *) node;
3138 appendStringInfo(buf, "NULLIF(");
3140 foreach(arg, nullifexpr->args)
3142 Node *e = (Node *) lfirst(arg);
3144 appendStringInfo(buf, sep);
3145 get_rule_expr(e, context, true);
3148 appendStringInfo(buf, ")");
3154 NullTest *ntest = (NullTest *) node;
3156 if (!PRETTY_PAREN(context))
3157 appendStringInfoChar(buf, '(');
3158 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
3159 switch (ntest->nulltesttype)
3162 appendStringInfo(buf, " IS NULL");
3165 appendStringInfo(buf, " IS NOT NULL");
3168 elog(ERROR, "unrecognized nulltesttype: %d",
3169 (int) ntest->nulltesttype);
3171 if (!PRETTY_PAREN(context))
3172 appendStringInfoChar(buf, ')');
3178 BooleanTest *btest = (BooleanTest *) node;
3180 if (!PRETTY_PAREN(context))
3181 appendStringInfoChar(buf, '(');
3182 get_rule_expr_paren((Node *) btest->arg, context, false, node);
3183 switch (btest->booltesttype)
3186 appendStringInfo(buf, " IS TRUE");
3189 appendStringInfo(buf, " IS NOT TRUE");
3192 appendStringInfo(buf, " IS FALSE");
3195 appendStringInfo(buf, " IS NOT FALSE");
3198 appendStringInfo(buf, " IS UNKNOWN");
3200 case IS_NOT_UNKNOWN:
3201 appendStringInfo(buf, " IS NOT UNKNOWN");
3204 elog(ERROR, "unrecognized booltesttype: %d",
3205 (int) btest->booltesttype);
3207 if (!PRETTY_PAREN(context))
3208 appendStringInfoChar(buf, ')');
3212 case T_CoerceToDomain:
3214 CoerceToDomain *ctest = (CoerceToDomain *) node;
3215 Node *arg = (Node *) ctest->arg;
3217 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
3220 /* don't show the implicit cast */
3221 get_rule_expr(arg, context, false);
3225 if (!PRETTY_PAREN(context))
3226 appendStringInfoChar(buf, '(');
3227 get_rule_expr_paren(arg, context, false, node);
3228 if (!PRETTY_PAREN(context))
3229 appendStringInfoChar(buf, ')');
3230 appendStringInfo(buf, "::%s",
3231 format_type_with_typemod(ctest->resulttype,
3232 ctest->resulttypmod));
3237 case T_CoerceToDomainValue:
3238 appendStringInfo(buf, "VALUE");
3241 case T_SetToDefault:
3242 appendStringInfo(buf, "DEFAULT");
3246 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
3253 * get_oper_expr - Parse back an OpExpr node
3256 get_oper_expr(OpExpr *expr, deparse_context *context)
3258 StringInfo buf = context->buf;
3259 Oid opno = expr->opno;
3260 List *args = expr->args;
3262 if (!PRETTY_PAREN(context))
3263 appendStringInfoChar(buf, '(');
3264 if (list_length(args) == 2)
3266 /* binary operator */
3267 Node *arg1 = (Node *) linitial(args);
3268 Node *arg2 = (Node *) lsecond(args);
3270 get_rule_expr_paren(arg1, context, true, (Node *) expr);
3271 appendStringInfo(buf, " %s ",
3272 generate_operator_name(opno,
3275 get_rule_expr_paren(arg2, context, true, (Node *) expr);
3279 /* unary operator --- but which side? */
3280 Node *arg = (Node *) linitial(args);
3282 Form_pg_operator optup;
3284 tp = SearchSysCache(OPEROID,
3285 ObjectIdGetDatum(opno),
3287 if (!HeapTupleIsValid(tp))
3288 elog(ERROR, "cache lookup failed for operator %u", opno);
3289 optup = (Form_pg_operator) GETSTRUCT(tp);
3290 switch (optup->oprkind)
3293 appendStringInfo(buf, "%s ",
3294 generate_operator_name(opno,
3297 get_rule_expr_paren(arg, context, true, (Node *) expr);
3300 get_rule_expr_paren(arg, context, true, (Node *) expr);
3301 appendStringInfo(buf, " %s",
3302 generate_operator_name(opno,
3307 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
3309 ReleaseSysCache(tp);
3311 if (!PRETTY_PAREN(context))
3312 appendStringInfoChar(buf, ')');
3316 * get_func_expr - Parse back a FuncExpr node
3319 get_func_expr(FuncExpr *expr, deparse_context *context,
3322 StringInfo buf = context->buf;
3323 Oid funcoid = expr->funcid;
3324 Oid argtypes[FUNC_MAX_ARGS];
3330 * If the function call came from an implicit coercion, then just show
3331 * the first argument --- unless caller wants to see implicit
3334 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
3336 get_rule_expr_paren((Node *) linitial(expr->args), context,
3337 false, (Node *) expr);
3342 * If the function call came from a cast, then show the first argument
3343 * plus an explicit cast operation.
3345 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
3346 expr->funcformat == COERCE_IMPLICIT_CAST)
3348 Node *arg = linitial(expr->args);
3349 Oid rettype = expr->funcresulttype;
3350 int32 coercedTypmod;
3352 /* Get the typmod if this is a length-coercion function */
3353 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
3355 if (!PRETTY_PAREN(context))
3356 appendStringInfoChar(buf, '(');
3357 get_rule_expr_paren(arg, context, false, (Node *) expr);
3358 if (!PRETTY_PAREN(context))
3359 appendStringInfoChar(buf, ')');
3360 appendStringInfo(buf, "::%s",
3361 format_type_with_typemod(rettype, coercedTypmod));
3367 * Normal function: display as proname(args). First we need to
3368 * extract the argument datatypes.
3371 foreach(l, expr->args)
3373 Assert(nargs < FUNC_MAX_ARGS);
3374 argtypes[nargs] = exprType((Node *) lfirst(l));
3378 appendStringInfo(buf, "%s(",
3379 generate_function_name(funcoid, nargs, argtypes));
3382 foreach(l, expr->args)
3384 appendStringInfo(buf, sep);
3386 get_rule_expr((Node *) lfirst(l), context, true);
3388 appendStringInfoChar(buf, ')');
3392 * get_agg_expr - Parse back an Aggref node
3395 get_agg_expr(Aggref *aggref, deparse_context *context)
3397 StringInfo buf = context->buf;
3398 Oid argtype = exprType((Node *) aggref->target);
3400 appendStringInfo(buf, "%s(%s",
3401 generate_function_name(aggref->aggfnoid, 1, &argtype),
3402 aggref->aggdistinct ? "DISTINCT " : "");
3403 if (aggref->aggstar)
3404 appendStringInfo(buf, "*");
3406 get_rule_expr((Node *) aggref->target, context, true);
3407 appendStringInfoChar(buf, ')');
3414 * Make a string representation of a Const
3418 get_const_expr(Const *constval, deparse_context *context)
3420 StringInfo buf = context->buf;
3426 bool isfloat = false;
3429 if (constval->constisnull)
3432 * Always label the type of a NULL constant to prevent
3433 * misdecisions about type when reparsing.
3435 appendStringInfo(buf, "NULL::%s",
3436 format_type_with_typemod(constval->consttype, -1));
3440 getTypeOutputInfo(constval->consttype,
3441 &typoutput, &typioparam, &typIsVarlena);
3443 extval = DatumGetCString(OidFunctionCall3(typoutput,
3444 constval->constvalue,
3445 ObjectIdGetDatum(typioparam),
3446 Int32GetDatum(-1)));
3448 switch (constval->consttype)
3459 * These types are printed without quotes unless they
3460 * contain values that aren't accepted by the scanner
3461 * unquoted (e.g., 'NaN'). Note that strtod() and friends
3462 * might accept NaN, so we can't use that to test.
3464 * In reality we only need to defend against infinity and
3465 * NaN, so we need not get too crazy about pattern
3468 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
3470 appendStringInfoString(buf, extval);
3471 if (strcspn(extval, "eE.") != strlen(extval))
3472 isfloat = true; /* it looks like a float */
3475 appendStringInfo(buf, "'%s'", extval);
3481 appendStringInfo(buf, "B'%s'", extval);
3485 if (strcmp(extval, "t") == 0)
3486 appendStringInfo(buf, "true");
3488 appendStringInfo(buf, "false");
3494 * We must quote any funny characters in the constant's
3495 * representation. XXX Any MULTIBYTE considerations here?
3497 appendStringInfoChar(buf, '\'');
3498 for (valptr = extval; *valptr; valptr++)
3502 if (ch == '\'' || ch == '\\')
3504 appendStringInfoChar(buf, '\\');
3505 appendStringInfoChar(buf, ch);
3507 else if (((unsigned char) ch) < ((unsigned char) ' '))
3508 appendStringInfo(buf, "\\%03o", (int) ch);
3510 appendStringInfoChar(buf, ch);
3512 appendStringInfoChar(buf, '\'');
3519 * Append ::typename unless the constant will be implicitly typed as
3520 * the right type when it is read in. XXX this code has to be kept in
3521 * sync with the behavior of the parser, especially make_const.
3523 switch (constval->consttype)
3528 /* These types can be left unlabeled */
3532 /* Float-looking constants will be typed as numeric */
3533 needlabel = !isfloat;
3540 appendStringInfo(buf, "::%s",
3541 format_type_with_typemod(constval->consttype, -1));
3546 * get_sublink_expr - Parse back a sublink
3550 get_sublink_expr(SubLink *sublink, deparse_context *context)
3552 StringInfo buf = context->buf;
3553 Query *query = (Query *) (sublink->subselect);
3558 if (sublink->subLinkType == ARRAY_SUBLINK)
3559 appendStringInfo(buf, "ARRAY(");
3561 appendStringInfoChar(buf, '(');
3563 if (sublink->lefthand != NIL)
3565 need_paren = (list_length(sublink->lefthand) > 1);
3567 appendStringInfoChar(buf, '(');
3570 foreach(l, sublink->lefthand)
3572 appendStringInfo(buf, sep);
3574 get_rule_expr((Node *) lfirst(l), context, true);
3578 appendStringInfo(buf, ") ");
3580 appendStringInfoChar(buf, ' ');
3586 * XXX we regurgitate the originally given operator name, with or
3587 * without schema qualification. This is not necessarily 100% right
3588 * but it's the best we can do, since the operators actually used
3589 * might not all be in the same schema.
3591 switch (sublink->subLinkType)
3593 case EXISTS_SUBLINK:
3594 appendStringInfo(buf, "EXISTS ");
3598 if (list_length(sublink->operName) == 1 &&
3599 strcmp(strVal(linitial(sublink->operName)), "=") == 0)
3601 /* Represent = ANY as IN */
3602 appendStringInfo(buf, "IN ");
3606 print_operator_name(buf, sublink->operName);
3607 appendStringInfo(buf, " ANY ");
3612 print_operator_name(buf, sublink->operName);
3613 appendStringInfo(buf, " ALL ");
3616 case MULTIEXPR_SUBLINK:
3617 print_operator_name(buf, sublink->operName);
3618 appendStringInfoChar(buf, ' ');
3627 elog(ERROR, "unrecognized sublink type: %d",
3628 (int) sublink->subLinkType);
3633 appendStringInfoChar(buf, '(');
3635 get_query_def(query, buf, context->namespaces, NULL,
3636 context->prettyFlags, context->indentLevel);
3639 appendStringInfo(buf, "))");
3641 appendStringInfoChar(buf, ')');
3646 * get_from_clause - Parse back a FROM clause
3650 get_from_clause(Query *query, deparse_context *context)
3652 StringInfo buf = context->buf;
3657 * We use the query's jointree as a guide to what to print. However,
3658 * we must ignore auto-added RTEs that are marked not inFromCl. (These
3659 * can only appear at the top level of the jointree, so it's
3660 * sufficient to check here.) Also ignore the rule pseudo-RTEs for NEW
3663 foreach(l, query->jointree->fromlist)
3665 Node *jtnode = (Node *) lfirst(l);
3667 if (IsA(jtnode, RangeTblRef))
3669 int varno = ((RangeTblRef *) jtnode)->rtindex;
3670 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
3674 if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
3676 if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
3682 appendContextKeyword(context, " FROM ",
3683 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3687 appendStringInfoString(buf, ", ");
3689 get_from_clause_item(jtnode, query, context);
3694 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
3696 StringInfo buf = context->buf;
3698 if (IsA(jtnode, RangeTblRef))
3700 int varno = ((RangeTblRef *) jtnode)->rtindex;
3701 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
3702 List *coldeflist = NIL;
3703 bool gavealias = false;
3705 switch (rte->rtekind)
3708 /* Normal relation RTE */
3709 appendStringInfo(buf, "%s%s",
3711 generate_relation_name(rte->relid));
3715 appendStringInfoChar(buf, '(');
3716 get_query_def(rte->subquery, buf, context->namespaces, NULL,
3717 context->prettyFlags, context->indentLevel);
3718 appendStringInfoChar(buf, ')');
3722 get_rule_expr(rte->funcexpr, context, true);
3723 /* might need to emit column list for RECORD function */
3724 coldeflist = rte->coldeflist;
3727 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
3730 if (rte->alias != NULL)
3732 appendStringInfo(buf, " %s",
3733 quote_identifier(rte->alias->aliasname));
3735 if (rte->alias->colnames != NIL && coldeflist == NIL)
3739 appendStringInfoChar(buf, '(');
3740 foreach(col, rte->alias->colnames)
3742 if (col != list_head(rte->alias->colnames))
3743 appendStringInfo(buf, ", ");
3744 appendStringInfoString(buf,
3745 quote_identifier(strVal(lfirst(col))));
3747 appendStringInfoChar(buf, ')');
3750 else if (rte->rtekind == RTE_RELATION &&
3751 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
3754 * Apparently the rel has been renamed since the rule was
3755 * made. Emit a fake alias clause so that variable references
3756 * will still work. This is not a 100% solution but should
3757 * work in most reasonable situations.
3759 appendStringInfo(buf, " %s",
3760 quote_identifier(rte->eref->aliasname));
3763 if (coldeflist != NIL)
3766 appendStringInfo(buf, " AS ");
3767 get_from_clause_coldeflist(coldeflist, context);
3770 else if (IsA(jtnode, JoinExpr))
3772 JoinExpr *j = (JoinExpr *) jtnode;
3773 bool need_paren_on_right;
3775 need_paren_on_right = PRETTY_PAREN(context) &&
3776 !IsA(j->rarg, RangeTblRef);
3778 if (!PRETTY_PAREN(context) || j->alias != NULL)
3779 appendStringInfoChar(buf, '(');
3781 get_from_clause_item(j->larg, query, context);
3785 if (!PRETTY_INDENT(context))
3786 appendStringInfoChar(buf, ' ');
3787 switch (j->jointype)
3790 appendContextKeyword(context, "NATURAL JOIN ",
3792 PRETTYINDENT_JOIN, 0);
3795 appendContextKeyword(context, "NATURAL LEFT JOIN ",
3797 PRETTYINDENT_JOIN, 0);
3800 appendContextKeyword(context, "NATURAL FULL JOIN ",
3802 PRETTYINDENT_JOIN, 0);
3805 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
3807 PRETTYINDENT_JOIN, 0);
3810 appendContextKeyword(context, "NATURAL UNION JOIN ",
3812 PRETTYINDENT_JOIN, 0);
3815 elog(ERROR, "unrecognized join type: %d",
3821 switch (j->jointype)
3825 appendContextKeyword(context, " JOIN ",
3827 PRETTYINDENT_JOIN, 2);
3829 appendContextKeyword(context, " CROSS JOIN ",
3831 PRETTYINDENT_JOIN, 1);
3834 appendContextKeyword(context, " LEFT JOIN ",
3836 PRETTYINDENT_JOIN, 2);
3839 appendContextKeyword(context, " FULL JOIN ",
3841 PRETTYINDENT_JOIN, 2);
3844 appendContextKeyword(context, " RIGHT JOIN ",
3846 PRETTYINDENT_JOIN, 2);
3849 appendContextKeyword(context, " UNION JOIN ",
3851 PRETTYINDENT_JOIN, 2);
3854 elog(ERROR, "unrecognized join type: %d",
3859 if (need_paren_on_right)
3860 appendStringInfoChar(buf, '(');
3861 get_from_clause_item(j->rarg, query, context);
3862 if (need_paren_on_right)
3863 appendStringInfoChar(buf, ')');
3865 context->indentLevel -= PRETTYINDENT_JOIN_ON;
3873 appendStringInfo(buf, " USING (");
3874 foreach(col, j->using)
3876 if (col != list_head(j->using))
3877 appendStringInfo(buf, ", ");
3878 appendStringInfoString(buf,
3879 quote_identifier(strVal(lfirst(col))));
3881 appendStringInfoChar(buf, ')');
3885 appendStringInfo(buf, " ON ");
3886 if (!PRETTY_PAREN(context))
3887 appendStringInfoChar(buf, '(');
3888 get_rule_expr(j->quals, context, false);
3889 if (!PRETTY_PAREN(context))
3890 appendStringInfoChar(buf, ')');
3893 if (!PRETTY_PAREN(context) || j->alias != NULL)
3894 appendStringInfoChar(buf, ')');
3896 /* Yes, it's correct to put alias after the right paren ... */
3897 if (j->alias != NULL)
3899 appendStringInfo(buf, " %s",
3900 quote_identifier(j->alias->aliasname));
3901 if (j->alias->colnames != NIL)
3905 appendStringInfoChar(buf, '(');
3906 foreach(col, j->alias->colnames)
3908 if (col != list_head(j->alias->colnames))
3909 appendStringInfo(buf, ", ");
3910 appendStringInfoString(buf,
3911 quote_identifier(strVal(lfirst(col))));
3913 appendStringInfoChar(buf, ')');
3918 elog(ERROR, "unrecognized node type: %d",
3919 (int) nodeTag(jtnode));
3923 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
3925 * The coldeflist is appended immediately (no space) to buf. Caller is
3926 * responsible for ensuring that an alias or AS is present before it.
3929 get_from_clause_coldeflist(List *coldeflist, deparse_context *context)
3931 StringInfo buf = context->buf;
3935 appendStringInfoChar(buf, '(');
3937 foreach(col, coldeflist)
3939 ColumnDef *n = lfirst(col);
3944 attname = n->colname;
3945 atttypeid = typenameTypeId(n->typename);
3946 atttypmod = n->typename->typmod;
3949 appendStringInfo(buf, ", ");
3950 appendStringInfo(buf, "%s %s",
3951 quote_identifier(attname),
3952 format_type_with_typemod(atttypeid, atttypmod));
3956 appendStringInfoChar(buf, ')');
3960 * get_opclass_name - fetch name of an index operator class
3962 * The opclass name is appended (after a space) to buf.
3964 * Output is suppressed if the opclass is the default for the given
3965 * actual_datatype. (If you don't want this behavior, just pass
3966 * InvalidOid for actual_datatype.)
3969 get_opclass_name(Oid opclass, Oid actual_datatype,
3973 Form_pg_opclass opcrec;
3978 /* Domains use their base type's default opclass */
3979 if (OidIsValid(actual_datatype))
3980 actual_datatype = getBaseType(actual_datatype);
3982 ht_opc = SearchSysCache(CLAOID,
3983 ObjectIdGetDatum(opclass),
3985 if (!HeapTupleIsValid(ht_opc))
3986 elog(ERROR, "cache lookup failed for opclass %u", opclass);
3987 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
3989 /* Special case for ARRAY_OPS: pretend it is default for any array type */
3990 if (OidIsValid(actual_datatype))
3992 if (opcrec->opcintype == ANYARRAYOID &&
3993 OidIsValid(get_element_type(actual_datatype)))
3994 actual_datatype = opcrec->opcintype;
3997 /* Must force use of opclass name if not in search path */
3998 isvisible = OpclassIsVisible(opclass);
4000 if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault ||
4003 /* Okay, we need the opclass name. Do we need to qualify it? */
4004 opcname = NameStr(opcrec->opcname);
4006 appendStringInfo(buf, " %s", quote_identifier(opcname));
4009 nspname = get_namespace_name(opcrec->opcnamespace);
4010 appendStringInfo(buf, " %s.%s",
4011 quote_identifier(nspname),
4012 quote_identifier(opcname));
4015 ReleaseSysCache(ht_opc);
4019 * processIndirection - take care of array and subfield assignment
4021 * We strip any top-level FieldStore or assignment ArrayRef nodes that
4022 * appear in the input, printing out the appropriate decoration for the
4023 * base column name (that the caller just printed). We return the
4024 * subexpression that's to be assigned.
4027 processIndirection(Node *node, deparse_context *context)
4029 StringInfo buf = context->buf;
4035 if (IsA(node, FieldStore))
4037 FieldStore *fstore = (FieldStore *) node;
4041 /* lookup tuple type */
4042 typrelid = get_typ_typrelid(fstore->resulttype);
4043 if (!OidIsValid(typrelid))
4044 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
4045 format_type_be(fstore->resulttype));
4047 * Get the field name. Note we assume here that there's only
4048 * one field being assigned to. This is okay in stored rules
4049 * but could be wrong in executable target lists. Presently no
4050 * problem since explain.c doesn't print plan targetlists, but
4051 * someday may have to think of something ...
4053 fieldname = get_relid_attribute_name(typrelid,
4054 linitial_int(fstore->fieldnums));
4055 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4057 * We ignore arg since it should be an uninteresting reference
4058 * to the target column or subcolumn.
4060 node = (Node *) linitial(fstore->newvals);
4062 else if (IsA(node, ArrayRef))
4064 ArrayRef *aref = (ArrayRef *) node;
4066 if (aref->refassgnexpr == NULL)
4068 printSubscripts(aref, context);
4070 * We ignore refexpr since it should be an uninteresting reference
4071 * to the target column or subcolumn.
4073 node = (Node *) aref->refassgnexpr;
4083 printSubscripts(ArrayRef *aref, deparse_context *context)
4085 StringInfo buf = context->buf;
4086 ListCell *lowlist_item;
4087 ListCell *uplist_item;
4089 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
4090 foreach(uplist_item, aref->refupperindexpr)
4092 appendStringInfoChar(buf, '[');
4095 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
4096 appendStringInfoChar(buf, ':');
4097 lowlist_item = lnext(lowlist_item);
4099 get_rule_expr((Node *) lfirst(uplist_item), context, false);
4100 appendStringInfoChar(buf, ']');
4105 * quote_identifier - Quote an identifier only if needed
4107 * When quotes are needed, we palloc the required space; slightly
4108 * space-wasteful but well worth it for notational simplicity.
4111 quote_identifier(const char *ident)
4114 * Can avoid quoting if ident starts with a lowercase letter or
4115 * underscore and contains only lowercase letters, digits, and
4116 * underscores, *and* is not any SQL keyword. Otherwise, supply
4126 * would like to use <ctype.h> macros here, but they might yield
4127 * unwanted locale-specific results...
4129 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
4131 for (ptr = ident; *ptr; ptr++)
4135 if ((ch >= 'a' && ch <= 'z') ||
4136 (ch >= '0' && ch <= '9') ||
4152 * Check for keyword. This test is overly strong, since many of
4153 * the "keywords" known to the parser are usable as column names,
4154 * but the parser doesn't provide any easy way to test for whether
4155 * an identifier is safe or not... so be safe not sorry.
4157 * Note: ScanKeywordLookup() does case-insensitive comparison, but
4158 * that's fine, since we already know we have all-lower-case.
4160 if (ScanKeywordLookup(ident) != NULL)
4165 return ident; /* no change needed */
4167 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
4171 for (ptr = ident; *ptr; ptr++)
4186 * quote_qualified_identifier - Quote a possibly-qualified identifier
4188 * Return a name of the form namespace.ident, or just ident if namespace
4189 * is NULL, quoting each component if necessary. The result is palloc'd.
4192 quote_qualified_identifier(const char *namespace,
4197 initStringInfo(&buf);
4199 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
4200 appendStringInfoString(&buf, quote_identifier(ident));
4205 * generate_relation_name
4206 * Compute the name to display for a relation specified by OID
4208 * The result includes all necessary quoting and schema-prefixing.
4211 generate_relation_name(Oid relid)
4214 Form_pg_class reltup;
4218 tp = SearchSysCache(RELOID,
4219 ObjectIdGetDatum(relid),
4221 if (!HeapTupleIsValid(tp))
4222 elog(ERROR, "cache lookup failed for relation %u", relid);
4223 reltup = (Form_pg_class) GETSTRUCT(tp);
4225 /* Qualify the name if not visible in search path */
4226 if (RelationIsVisible(relid))
4229 nspname = get_namespace_name(reltup->relnamespace);
4231 result = quote_qualified_identifier(nspname, NameStr(reltup->relname));
4233 ReleaseSysCache(tp);
4239 * generate_function_name
4240 * Compute the name to display for a function specified by OID,
4241 * given that it is being called with the specified actual arg types.
4242 * (Arg types matter because of ambiguous-function resolution rules.)
4244 * The result includes all necessary quoting and schema-prefixing.
4247 generate_function_name(Oid funcid, int nargs, Oid *argtypes)
4250 Form_pg_proc procform;
4254 FuncDetailCode p_result;
4258 Oid *p_true_typeids;
4260 proctup = SearchSysCache(PROCOID,
4261 ObjectIdGetDatum(funcid),
4263 if (!HeapTupleIsValid(proctup))
4264 elog(ERROR, "cache lookup failed for function %u", funcid);
4265 procform = (Form_pg_proc) GETSTRUCT(proctup);
4266 proname = NameStr(procform->proname);
4267 Assert(nargs == procform->pronargs);
4270 * The idea here is to schema-qualify only if the parser would fail to
4271 * resolve the correct function given the unqualified func name with
4272 * the specified argtypes.
4274 p_result = func_get_detail(list_make1(makeString(proname)),
4275 NIL, nargs, argtypes,
4276 &p_funcid, &p_rettype,
4277 &p_retset, &p_true_typeids);
4278 if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
4282 nspname = get_namespace_name(procform->pronamespace);
4284 result = quote_qualified_identifier(nspname, proname);
4286 ReleaseSysCache(proctup);
4292 * generate_operator_name
4293 * Compute the name to display for an operator specified by OID,
4294 * given that it is being called with the specified actual arg types.
4295 * (Arg types matter because of ambiguous-operator resolution rules.
4296 * Pass InvalidOid for unused arg of a unary operator.)
4298 * The result includes all necessary quoting and schema-prefixing,
4299 * plus the OPERATOR() decoration needed to use a qualified operator name
4303 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
4307 Form_pg_operator operform;
4312 initStringInfo(&buf);
4314 opertup = SearchSysCache(OPEROID,
4315 ObjectIdGetDatum(operid),
4317 if (!HeapTupleIsValid(opertup))
4318 elog(ERROR, "cache lookup failed for operator %u", operid);
4319 operform = (Form_pg_operator) GETSTRUCT(opertup);
4320 oprname = NameStr(operform->oprname);
4323 * The idea here is to schema-qualify only if the parser would fail to
4324 * resolve the correct operator given the unqualified op name with the
4325 * specified argtypes.
4327 switch (operform->oprkind)
4330 p_result = oper(list_make1(makeString(oprname)), arg1, arg2, true);
4333 p_result = left_oper(list_make1(makeString(oprname)), arg2, true);
4336 p_result = right_oper(list_make1(makeString(oprname)), arg1, true);
4339 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
4340 p_result = NULL; /* keep compiler quiet */
4344 if (p_result != NULL && oprid(p_result) == operid)
4348 nspname = get_namespace_name(operform->oprnamespace);
4349 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
4352 appendStringInfoString(&buf, oprname);
4355 appendStringInfoChar(&buf, ')');
4357 if (p_result != NULL)
4358 ReleaseSysCache(p_result);
4360 ReleaseSysCache(opertup);
4366 * Print out a possibly-qualified operator name
4369 print_operator_name(StringInfo buf, List *opname)
4371 ListCell *op = list_head(opname);
4372 int nnames = list_length(opname);
4375 appendStringInfoString(buf, strVal(lfirst(op)));
4378 appendStringInfo(buf, "OPERATOR(");
4379 while (nnames-- > 1)
4381 appendStringInfo(buf, "%s.",
4382 quote_identifier(strVal(lfirst(op))));
4385 appendStringInfo(buf, "%s)", strVal(lfirst(op)));
4390 * Given a C string, produce a TEXT datum.
4392 * We assume that the input was palloc'd and may be freed.
4395 string_to_text(char *str)
4398 int slen = strlen(str);
4401 tlen = slen + VARHDRSZ;
4402 result = (text *) palloc(tlen);
4403 VARATT_SIZEP(result) = tlen;
4404 memcpy(VARDATA(result), str, slen);