PostgreSQL Source Code  git master
ruleutils.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * ruleutils.c
4  * Functions to convert stored expressions/querytrees back to
5  * source text
6  *
7  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/utils/adt/ruleutils.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 
22 #include "access/amapi.h"
23 #include "access/htup_details.h"
24 #include "access/relation.h"
25 #include "access/sysattr.h"
26 #include "access/table.h"
27 #include "catalog/dependency.h"
28 #include "catalog/indexing.h"
29 #include "catalog/pg_aggregate.h"
30 #include "catalog/pg_am.h"
31 #include "catalog/pg_authid.h"
32 #include "catalog/pg_collation.h"
33 #include "catalog/pg_constraint.h"
34 #include "catalog/pg_depend.h"
35 #include "catalog/pg_language.h"
36 #include "catalog/pg_opclass.h"
37 #include "catalog/pg_operator.h"
39 #include "catalog/pg_proc.h"
41 #include "catalog/pg_trigger.h"
42 #include "catalog/pg_type.h"
43 #include "commands/defrem.h"
44 #include "commands/tablespace.h"
45 #include "common/keywords.h"
46 #include "executor/spi.h"
47 #include "funcapi.h"
48 #include "mb/pg_wchar.h"
49 #include "miscadmin.h"
50 #include "nodes/makefuncs.h"
51 #include "nodes/nodeFuncs.h"
52 #include "nodes/pathnodes.h"
53 #include "optimizer/optimizer.h"
54 #include "parser/parse_agg.h"
55 #include "parser/parse_func.h"
56 #include "parser/parse_node.h"
57 #include "parser/parse_oper.h"
58 #include "parser/parser.h"
59 #include "parser/parsetree.h"
60 #include "rewrite/rewriteHandler.h"
61 #include "rewrite/rewriteManip.h"
62 #include "rewrite/rewriteSupport.h"
63 #include "utils/array.h"
64 #include "utils/builtins.h"
65 #include "utils/fmgroids.h"
66 #include "utils/guc.h"
67 #include "utils/hsearch.h"
68 #include "utils/lsyscache.h"
69 #include "utils/partcache.h"
70 #include "utils/rel.h"
71 #include "utils/ruleutils.h"
72 #include "utils/snapmgr.h"
73 #include "utils/syscache.h"
74 #include "utils/typcache.h"
75 #include "utils/varlena.h"
76 #include "utils/xml.h"
77 
78 /* ----------
79  * Pretty formatting constants
80  * ----------
81  */
82 
83 /* Indent counts */
84 #define PRETTYINDENT_STD 8
85 #define PRETTYINDENT_JOIN 4
86 #define PRETTYINDENT_VAR 4
87 
88 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
89 
90 /* Pretty flags */
91 #define PRETTYFLAG_PAREN 0x0001
92 #define PRETTYFLAG_INDENT 0x0002
93 #define PRETTYFLAG_SCHEMA 0x0004
94 
95 /* Default line length for pretty-print wrapping: 0 means wrap always */
96 #define WRAP_COLUMN_DEFAULT 0
97 
98 /* macros to test if pretty action needed */
99 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
100 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
101 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
102 
103 
104 /* ----------
105  * Local data types
106  * ----------
107  */
108 
109 /* Context info needed for invoking a recursive querytree display routine */
110 typedef struct
111 {
112  StringInfo buf; /* output buffer to append to */
113  List *namespaces; /* List of deparse_namespace nodes */
114  List *windowClause; /* Current query level's WINDOW clause */
115  List *windowTList; /* targetlist for resolving WINDOW clause */
116  int prettyFlags; /* enabling of pretty-print functions */
117  int wrapColumn; /* max line length, or -1 for no limit */
118  int indentLevel; /* current indent level for pretty-print */
119  bool varprefix; /* true to print prefixes on Vars */
120  ParseExprKind special_exprkind; /* set only for exprkinds needing special
121  * handling */
122  Bitmapset *appendparents; /* if not null, map child Vars of these relids
123  * back to the parent rel */
125 
126 /*
127  * Each level of query context around a subtree needs a level of Var namespace.
128  * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
129  * the current context's namespaces list.
130  *
131  * rtable is the list of actual RTEs from the Query or PlannedStmt.
132  * rtable_names holds the alias name to be used for each RTE (either a C
133  * string, or NULL for nameless RTEs such as unnamed joins).
134  * rtable_columns holds the column alias names to be used for each RTE.
135  *
136  * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
137  * in the PlannedStmt case).
138  * ctes is a list of CommonTableExpr nodes (only used in the Query case).
139  * appendrels, if not null (it's only used in the PlannedStmt case), is an
140  * array of AppendRelInfo nodes, indexed by child relid. We use that to map
141  * child-table Vars to their inheritance parents.
142  *
143  * In some cases we need to make names of merged JOIN USING columns unique
144  * across the whole query, not only per-RTE. If so, unique_using is true
145  * and using_names is a list of C strings representing names already assigned
146  * to USING columns.
147  *
148  * When deparsing plan trees, there is always just a single item in the
149  * deparse_namespace list (since a plan tree never contains Vars with
150  * varlevelsup > 0). We store the Plan node that is the immediate
151  * parent of the expression to be deparsed, as well as a list of that
152  * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
153  * as well as their targetlists, and the index tlist if the current plan node
154  * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
155  * from the current Plan node, but it seems notationally clearer to set them
156  * up as separate fields.)
157  */
158 typedef struct
159 {
160  List *rtable; /* List of RangeTblEntry nodes */
161  List *rtable_names; /* Parallel list of names for RTEs */
162  List *rtable_columns; /* Parallel list of deparse_columns structs */
163  List *subplans; /* List of Plan trees for SubPlans */
164  List *ctes; /* List of CommonTableExpr nodes */
165  AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
166  /* Workspace for column alias assignment: */
167  bool unique_using; /* Are we making USING names globally unique */
168  List *using_names; /* List of assigned names for USING columns */
169  /* Remaining fields are used only when deparsing a Plan tree: */
170  Plan *plan; /* immediate parent of current expression */
171  List *ancestors; /* ancestors of plan */
172  Plan *outer_plan; /* outer subnode, or NULL if none */
173  Plan *inner_plan; /* inner subnode, or NULL if none */
174  List *outer_tlist; /* referent for OUTER_VAR Vars */
175  List *inner_tlist; /* referent for INNER_VAR Vars */
176  List *index_tlist; /* referent for INDEX_VAR Vars */
178 
179 /*
180  * Per-relation data about column alias names.
181  *
182  * Selecting aliases is unreasonably complicated because of the need to dump
183  * rules/views whose underlying tables may have had columns added, deleted, or
184  * renamed since the query was parsed. We must nonetheless print the rule/view
185  * in a form that can be reloaded and will produce the same results as before.
186  *
187  * For each RTE used in the query, we must assign column aliases that are
188  * unique within that RTE. SQL does not require this of the original query,
189  * but due to factors such as *-expansion we need to be able to uniquely
190  * reference every column in a decompiled query. As long as we qualify all
191  * column references, per-RTE uniqueness is sufficient for that.
192  *
193  * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
194  * since they just inherit column names from their input RTEs, and we can't
195  * rename the columns at the join level. Most of the time this isn't an issue
196  * because we don't need to reference the join's output columns as such; we
197  * can reference the input columns instead. That approach can fail for merged
198  * JOIN USING columns, however, so when we have one of those in an unnamed
199  * join, we have to make that column's alias globally unique across the whole
200  * query to ensure it can be referenced unambiguously.
201  *
202  * Another problem is that a JOIN USING clause requires the columns to be
203  * merged to have the same aliases in both input RTEs, and that no other
204  * columns in those RTEs or their children conflict with the USING names.
205  * To handle that, we do USING-column alias assignment in a recursive
206  * traversal of the query's jointree. When descending through a JOIN with
207  * USING, we preassign the USING column names to the child columns, overriding
208  * other rules for column alias assignment. We also mark each RTE with a list
209  * of all USING column names selected for joins containing that RTE, so that
210  * when we assign other columns' aliases later, we can avoid conflicts.
211  *
212  * Another problem is that if a JOIN's input tables have had columns added or
213  * deleted since the query was parsed, we must generate a column alias list
214  * for the join that matches the current set of input columns --- otherwise, a
215  * change in the number of columns in the left input would throw off matching
216  * of aliases to columns of the right input. Thus, positions in the printable
217  * column alias list are not necessarily one-for-one with varattnos of the
218  * JOIN, so we need a separate new_colnames[] array for printing purposes.
219  */
220 typedef struct
221 {
222  /*
223  * colnames is an array containing column aliases to use for columns that
224  * existed when the query was parsed. Dropped columns have NULL entries.
225  * This array can be directly indexed by varattno to get a Var's name.
226  *
227  * Non-NULL entries are guaranteed unique within the RTE, *except* when
228  * this is for an unnamed JOIN RTE. In that case we merely copy up names
229  * from the two input RTEs.
230  *
231  * During the recursive descent in set_using_names(), forcible assignment
232  * of a child RTE's column name is represented by pre-setting that element
233  * of the child's colnames array. So at that stage, NULL entries in this
234  * array just mean that no name has been preassigned, not necessarily that
235  * the column is dropped.
236  */
237  int num_cols; /* length of colnames[] array */
238  char **colnames; /* array of C strings and NULLs */
239 
240  /*
241  * new_colnames is an array containing column aliases to use for columns
242  * that would exist if the query was re-parsed against the current
243  * definitions of its base tables. This is what to print as the column
244  * alias list for the RTE. This array does not include dropped columns,
245  * but it will include columns added since original parsing. Indexes in
246  * it therefore have little to do with current varattno values. As above,
247  * entries are unique unless this is for an unnamed JOIN RTE. (In such an
248  * RTE, we never actually print this array, but we must compute it anyway
249  * for possible use in computing column names of upper joins.) The
250  * parallel array is_new_col marks which of these columns are new since
251  * original parsing. Entries with is_new_col false must match the
252  * non-NULL colnames entries one-for-one.
253  */
254  int num_new_cols; /* length of new_colnames[] array */
255  char **new_colnames; /* array of C strings */
256  bool *is_new_col; /* array of bool flags */
257 
258  /* This flag tells whether we should actually print a column alias list */
260 
261  /* This list has all names used as USING names in joins above this RTE */
262  List *parentUsing; /* names assigned to parent merged columns */
263 
264  /*
265  * If this struct is for a JOIN RTE, we fill these fields during the
266  * set_using_names() pass to describe its relationship to its child RTEs.
267  *
268  * leftattnos and rightattnos are arrays with one entry per existing
269  * output column of the join (hence, indexable by join varattno). For a
270  * simple reference to a column of the left child, leftattnos[i] is the
271  * child RTE's attno and rightattnos[i] is zero; and conversely for a
272  * column of the right child. But for merged columns produced by JOIN
273  * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
274  * Note that a simple reference might be to a child RTE column that's been
275  * dropped; but that's OK since the column could not be used in the query.
276  *
277  * If it's a JOIN USING, usingNames holds the alias names selected for the
278  * merged columns (these might be different from the original USING list,
279  * if we had to modify names to achieve uniqueness).
280  */
281  int leftrti; /* rangetable index of left child */
282  int rightrti; /* rangetable index of right child */
283  int *leftattnos; /* left-child varattnos of join cols, or 0 */
284  int *rightattnos; /* right-child varattnos of join cols, or 0 */
285  List *usingNames; /* names assigned to merged columns */
287 
288 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
289 #define deparse_columns_fetch(rangetable_index, dpns) \
290  ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
291 
292 /*
293  * Entry in set_rtable_names' hash table
294  */
295 typedef struct
296 {
297  char name[NAMEDATALEN]; /* Hash key --- must be first */
298  int counter; /* Largest addition used so far for name */
299 } NameHashEntry;
300 
301 /* Callback signature for resolve_special_varno() */
302 typedef void (*rsv_callback) (Node *node, deparse_context *context,
303  void *callback_arg);
304 
305 
306 /* ----------
307  * Global data
308  * ----------
309  */
311 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
313 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
314 
315 /* GUC parameters */
317 
318 
319 /* ----------
320  * Local functions
321  *
322  * Most of these functions used to use fixed-size buffers to build their
323  * results. Now, they take an (already initialized) StringInfo object
324  * as a parameter, and append their text output to its contents.
325  * ----------
326  */
327 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
328  bool forceprefix, bool showimplicit,
329  int prettyFlags, int startIndent);
330 static char *pg_get_viewdef_worker(Oid viewoid,
331  int prettyFlags, int wrapColumn);
332 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
333 static int decompile_column_index_array(Datum column_index_array, Oid relId,
334  StringInfo buf);
335 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
336 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
337  const Oid *excludeOps,
338  bool attrsOnly, bool keysOnly,
339  bool showTblSpc, bool inherits,
340  int prettyFlags, bool missing_ok);
341 static char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok);
342 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
343  bool attrsOnly, bool missing_ok);
344 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
345  int prettyFlags, bool missing_ok);
346 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
347  int prettyFlags);
349  bool print_table_args, bool print_defaults);
350 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
351 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
352 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
353  Bitmapset *rels_used);
354 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
355  List *parent_namespaces);
356 static void set_simple_column_names(deparse_namespace *dpns);
357 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
358 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
359  List *parentUsing);
361  RangeTblEntry *rte,
362  deparse_columns *colinfo);
364  deparse_columns *colinfo);
365 static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
366  deparse_columns *colinfo);
367 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
368  deparse_columns *colinfo);
369 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
370 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
371  deparse_columns *colinfo);
372 static char *get_rtable_name(int rtindex, deparse_context *context);
373 static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
374 static void push_child_plan(deparse_namespace *dpns, Plan *plan,
375  deparse_namespace *save_dpns);
376 static void pop_child_plan(deparse_namespace *dpns,
377  deparse_namespace *save_dpns);
378 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
379  deparse_namespace *save_dpns);
380 static void pop_ancestor_plan(deparse_namespace *dpns,
381  deparse_namespace *save_dpns);
382 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
383  int prettyFlags);
384 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
385  int prettyFlags, int wrapColumn);
386 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
387  TupleDesc resultDesc,
388  int prettyFlags, int wrapColumn, int startIndent);
389 static void get_values_def(List *values_lists, deparse_context *context);
390 static void get_with_clause(Query *query, deparse_context *context);
391 static void get_select_query_def(Query *query, deparse_context *context,
392  TupleDesc resultDesc);
393 static void get_insert_query_def(Query *query, deparse_context *context);
394 static void get_update_query_def(Query *query, deparse_context *context);
395 static void get_update_query_targetlist_def(Query *query, List *targetList,
396  deparse_context *context,
397  RangeTblEntry *rte);
398 static void get_delete_query_def(Query *query, deparse_context *context);
399 static void get_utility_query_def(Query *query, deparse_context *context);
400 static void get_basic_select_query(Query *query, deparse_context *context,
401  TupleDesc resultDesc);
402 static void get_target_list(List *targetList, deparse_context *context,
403  TupleDesc resultDesc);
404 static void get_setop_query(Node *setOp, Query *query,
405  deparse_context *context,
406  TupleDesc resultDesc);
407 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
408  bool force_colno,
409  deparse_context *context);
410 static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
411  bool omit_parens, deparse_context *context);
412 static void get_rule_orderby(List *orderList, List *targetList,
413  bool force_colno, deparse_context *context);
414 static void get_rule_windowclause(Query *query, deparse_context *context);
415 static void get_rule_windowspec(WindowClause *wc, List *targetList,
416  deparse_context *context);
417 static char *get_variable(Var *var, int levelsup, bool istoplevel,
418  deparse_context *context);
419 static void get_special_variable(Node *node, deparse_context *context,
420  void *callback_arg);
421 static void resolve_special_varno(Node *node, deparse_context *context,
422  rsv_callback callback, void *callback_arg);
423 static Node *find_param_referent(Param *param, deparse_context *context,
424  deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
425 static void get_parameter(Param *param, deparse_context *context);
426 static const char *get_simple_binary_op_name(OpExpr *expr);
427 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
428 static void appendContextKeyword(deparse_context *context, const char *str,
429  int indentBefore, int indentAfter, int indentPlus);
431 static void get_rule_expr(Node *node, deparse_context *context,
432  bool showimplicit);
433 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
434  bool showimplicit);
435 static void get_rule_expr_funccall(Node *node, deparse_context *context,
436  bool showimplicit);
437 static bool looks_like_function(Node *node);
438 static void get_oper_expr(OpExpr *expr, deparse_context *context);
439 static void get_func_expr(FuncExpr *expr, deparse_context *context,
440  bool showimplicit);
441 static void get_agg_expr(Aggref *aggref, deparse_context *context,
442  Aggref *original_aggref);
443 static void get_agg_combine_expr(Node *node, deparse_context *context,
444  void *callback_arg);
445 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
446 static void get_coercion_expr(Node *arg, deparse_context *context,
447  Oid resulttype, int32 resulttypmod,
448  Node *parentNode);
449 static void get_const_expr(Const *constval, deparse_context *context,
450  int showtype);
451 static void get_const_collation(Const *constval, deparse_context *context);
452 static void simple_quote_literal(StringInfo buf, const char *val);
453 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
454 static void get_tablefunc(TableFunc *tf, deparse_context *context,
455  bool showimplicit);
456 static void get_from_clause(Query *query, const char *prefix,
457  deparse_context *context);
458 static void get_from_clause_item(Node *jtnode, Query *query,
459  deparse_context *context);
460 static void get_column_alias_list(deparse_columns *colinfo,
461  deparse_context *context);
462 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
463  deparse_columns *colinfo,
464  deparse_context *context);
465 static void get_tablesample_def(TableSampleClause *tablesample,
466  deparse_context *context);
467 static void get_opclass_name(Oid opclass, Oid actual_datatype,
468  StringInfo buf);
469 static Node *processIndirection(Node *node, deparse_context *context);
470 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
471 static char *get_relation_name(Oid relid);
472 static char *generate_relation_name(Oid relid, List *namespaces);
473 static char *generate_qualified_relation_name(Oid relid);
474 static char *generate_function_name(Oid funcid, int nargs,
475  List *argnames, Oid *argtypes,
476  bool has_variadic, bool *use_variadic_p,
477  ParseExprKind special_exprkind);
478 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
479 static void add_cast_to(StringInfo buf, Oid typid);
480 static char *generate_qualified_type_name(Oid typid);
481 static text *string_to_text(char *str);
482 static char *flatten_reloptions(Oid relid);
483 
484 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
485 
486 
487 /* ----------
488  * pg_get_ruledef - Do it all and return a text
489  * that could be used as a statement
490  * to recreate the rule
491  * ----------
492  */
493 Datum
495 {
496  Oid ruleoid = PG_GETARG_OID(0);
497  int prettyFlags;
498  char *res;
499 
500  prettyFlags = PRETTYFLAG_INDENT;
501 
502  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
503 
504  if (res == NULL)
505  PG_RETURN_NULL();
506 
508 }
509 
510 
511 Datum
513 {
514  Oid ruleoid = PG_GETARG_OID(0);
515  bool pretty = PG_GETARG_BOOL(1);
516  int prettyFlags;
517  char *res;
518 
520 
521  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
522 
523  if (res == NULL)
524  PG_RETURN_NULL();
525 
527 }
528 
529 
530 static char *
531 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
532 {
533  Datum args[1];
534  char nulls[1];
535  int spirc;
536  HeapTuple ruletup;
537  TupleDesc rulettc;
539 
540  /*
541  * Do this first so that string is alloc'd in outer context not SPI's.
542  */
543  initStringInfo(&buf);
544 
545  /*
546  * Connect to SPI manager
547  */
548  if (SPI_connect() != SPI_OK_CONNECT)
549  elog(ERROR, "SPI_connect failed");
550 
551  /*
552  * On the first call prepare the plan to lookup pg_rewrite. We read
553  * pg_rewrite over the SPI manager instead of using the syscache to be
554  * checked for read access on pg_rewrite.
555  */
556  if (plan_getrulebyoid == NULL)
557  {
558  Oid argtypes[1];
559  SPIPlanPtr plan;
560 
561  argtypes[0] = OIDOID;
562  plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
563  if (plan == NULL)
564  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
565  SPI_keepplan(plan);
566  plan_getrulebyoid = plan;
567  }
568 
569  /*
570  * Get the pg_rewrite tuple for this rule
571  */
572  args[0] = ObjectIdGetDatum(ruleoid);
573  nulls[0] = ' ';
574  spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
575  if (spirc != SPI_OK_SELECT)
576  elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
577  if (SPI_processed != 1)
578  {
579  /*
580  * There is no tuple data available here, just keep the output buffer
581  * empty.
582  */
583  }
584  else
585  {
586  /*
587  * Get the rule's definition and put it into executor's memory
588  */
589  ruletup = SPI_tuptable->vals[0];
590  rulettc = SPI_tuptable->tupdesc;
591  make_ruledef(&buf, ruletup, rulettc, prettyFlags);
592  }
593 
594  /*
595  * Disconnect from SPI manager
596  */
597  if (SPI_finish() != SPI_OK_FINISH)
598  elog(ERROR, "SPI_finish failed");
599 
600  if (buf.len == 0)
601  return NULL;
602 
603  return buf.data;
604 }
605 
606 
607 /* ----------
608  * pg_get_viewdef - Mainly the same thing, but we
609  * only return the SELECT part of a view
610  * ----------
611  */
612 Datum
614 {
615  /* By OID */
616  Oid viewoid = PG_GETARG_OID(0);
617  int prettyFlags;
618  char *res;
619 
620  prettyFlags = PRETTYFLAG_INDENT;
621 
622  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
623 
624  if (res == NULL)
625  PG_RETURN_NULL();
626 
628 }
629 
630 
631 Datum
633 {
634  /* By OID */
635  Oid viewoid = PG_GETARG_OID(0);
636  bool pretty = PG_GETARG_BOOL(1);
637  int prettyFlags;
638  char *res;
639 
641 
642  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
643 
644  if (res == NULL)
645  PG_RETURN_NULL();
646 
648 }
649 
650 Datum
652 {
653  /* By OID */
654  Oid viewoid = PG_GETARG_OID(0);
655  int wrap = PG_GETARG_INT32(1);
656  int prettyFlags;
657  char *res;
658 
659  /* calling this implies we want pretty printing */
661 
662  res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
663 
664  if (res == NULL)
665  PG_RETURN_NULL();
666 
668 }
669 
670 Datum
672 {
673  /* By qualified name */
674  text *viewname = PG_GETARG_TEXT_PP(0);
675  int prettyFlags;
676  RangeVar *viewrel;
677  Oid viewoid;
678  char *res;
679 
680  prettyFlags = PRETTYFLAG_INDENT;
681 
682  /* Look up view name. Can't lock it - we might not have privileges. */
684  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
685 
686  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
687 
688  if (res == NULL)
689  PG_RETURN_NULL();
690 
692 }
693 
694 
695 Datum
697 {
698  /* By qualified name */
699  text *viewname = PG_GETARG_TEXT_PP(0);
700  bool pretty = PG_GETARG_BOOL(1);
701  int prettyFlags;
702  RangeVar *viewrel;
703  Oid viewoid;
704  char *res;
705 
707 
708  /* Look up view name. Can't lock it - we might not have privileges. */
710  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
711 
712  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
713 
714  if (res == NULL)
715  PG_RETURN_NULL();
716 
718 }
719 
720 /*
721  * Common code for by-OID and by-name variants of pg_get_viewdef
722  */
723 static char *
724 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
725 {
726  Datum args[2];
727  char nulls[2];
728  int spirc;
729  HeapTuple ruletup;
730  TupleDesc rulettc;
732 
733  /*
734  * Do this first so that string is alloc'd in outer context not SPI's.
735  */
736  initStringInfo(&buf);
737 
738  /*
739  * Connect to SPI manager
740  */
741  if (SPI_connect() != SPI_OK_CONNECT)
742  elog(ERROR, "SPI_connect failed");
743 
744  /*
745  * On the first call prepare the plan to lookup pg_rewrite. We read
746  * pg_rewrite over the SPI manager instead of using the syscache to be
747  * checked for read access on pg_rewrite.
748  */
749  if (plan_getviewrule == NULL)
750  {
751  Oid argtypes[2];
752  SPIPlanPtr plan;
753 
754  argtypes[0] = OIDOID;
755  argtypes[1] = NAMEOID;
756  plan = SPI_prepare(query_getviewrule, 2, argtypes);
757  if (plan == NULL)
758  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
759  SPI_keepplan(plan);
760  plan_getviewrule = plan;
761  }
762 
763  /*
764  * Get the pg_rewrite tuple for the view's SELECT rule
765  */
766  args[0] = ObjectIdGetDatum(viewoid);
768  nulls[0] = ' ';
769  nulls[1] = ' ';
770  spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
771  if (spirc != SPI_OK_SELECT)
772  elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
773  if (SPI_processed != 1)
774  {
775  /*
776  * There is no tuple data available here, just keep the output buffer
777  * empty.
778  */
779  }
780  else
781  {
782  /*
783  * Get the rule's definition and put it into executor's memory
784  */
785  ruletup = SPI_tuptable->vals[0];
786  rulettc = SPI_tuptable->tupdesc;
787  make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
788  }
789 
790  /*
791  * Disconnect from SPI manager
792  */
793  if (SPI_finish() != SPI_OK_FINISH)
794  elog(ERROR, "SPI_finish failed");
795 
796  if (buf.len == 0)
797  return NULL;
798 
799  return buf.data;
800 }
801 
802 /* ----------
803  * pg_get_triggerdef - Get the definition of a trigger
804  * ----------
805  */
806 Datum
808 {
809  Oid trigid = PG_GETARG_OID(0);
810  char *res;
811 
812  res = pg_get_triggerdef_worker(trigid, false);
813 
814  if (res == NULL)
815  PG_RETURN_NULL();
816 
818 }
819 
820 Datum
822 {
823  Oid trigid = PG_GETARG_OID(0);
824  bool pretty = PG_GETARG_BOOL(1);
825  char *res;
826 
827  res = pg_get_triggerdef_worker(trigid, pretty);
828 
829  if (res == NULL)
830  PG_RETURN_NULL();
831 
833 }
834 
835 static char *
836 pg_get_triggerdef_worker(Oid trigid, bool pretty)
837 {
838  HeapTuple ht_trig;
839  Form_pg_trigger trigrec;
841  Relation tgrel;
842  ScanKeyData skey[1];
843  SysScanDesc tgscan;
844  int findx = 0;
845  char *tgname;
846  char *tgoldtable;
847  char *tgnewtable;
848  Datum value;
849  bool isnull;
850 
851  /*
852  * Fetch the pg_trigger tuple by the Oid of the trigger
853  */
854  tgrel = table_open(TriggerRelationId, AccessShareLock);
855 
856  ScanKeyInit(&skey[0],
857  Anum_pg_trigger_oid,
858  BTEqualStrategyNumber, F_OIDEQ,
859  ObjectIdGetDatum(trigid));
860 
861  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
862  NULL, 1, skey);
863 
864  ht_trig = systable_getnext(tgscan);
865 
866  if (!HeapTupleIsValid(ht_trig))
867  {
868  systable_endscan(tgscan);
870  return NULL;
871  }
872 
873  trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
874 
875  /*
876  * Start the trigger definition. Note that the trigger's name should never
877  * be schema-qualified, but the trigger rel's name may be.
878  */
879  initStringInfo(&buf);
880 
881  tgname = NameStr(trigrec->tgname);
882  appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
883  OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
884  quote_identifier(tgname));
885 
886  if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
887  appendStringInfoString(&buf, "BEFORE");
888  else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
889  appendStringInfoString(&buf, "AFTER");
890  else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
891  appendStringInfoString(&buf, "INSTEAD OF");
892  else
893  elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
894 
895  if (TRIGGER_FOR_INSERT(trigrec->tgtype))
896  {
897  appendStringInfoString(&buf, " INSERT");
898  findx++;
899  }
900  if (TRIGGER_FOR_DELETE(trigrec->tgtype))
901  {
902  if (findx > 0)
903  appendStringInfoString(&buf, " OR DELETE");
904  else
905  appendStringInfoString(&buf, " DELETE");
906  findx++;
907  }
908  if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
909  {
910  if (findx > 0)
911  appendStringInfoString(&buf, " OR UPDATE");
912  else
913  appendStringInfoString(&buf, " UPDATE");
914  findx++;
915  /* tgattr is first var-width field, so OK to access directly */
916  if (trigrec->tgattr.dim1 > 0)
917  {
918  int i;
919 
920  appendStringInfoString(&buf, " OF ");
921  for (i = 0; i < trigrec->tgattr.dim1; i++)
922  {
923  char *attname;
924 
925  if (i > 0)
926  appendStringInfoString(&buf, ", ");
927  attname = get_attname(trigrec->tgrelid,
928  trigrec->tgattr.values[i], false);
930  }
931  }
932  }
933  if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
934  {
935  if (findx > 0)
936  appendStringInfoString(&buf, " OR TRUNCATE");
937  else
938  appendStringInfoString(&buf, " TRUNCATE");
939  findx++;
940  }
941 
942  /*
943  * In non-pretty mode, always schema-qualify the target table name for
944  * safety. In pretty mode, schema-qualify only if not visible.
945  */
946  appendStringInfo(&buf, " ON %s ",
947  pretty ?
948  generate_relation_name(trigrec->tgrelid, NIL) :
949  generate_qualified_relation_name(trigrec->tgrelid));
950 
951  if (OidIsValid(trigrec->tgconstraint))
952  {
953  if (OidIsValid(trigrec->tgconstrrelid))
954  appendStringInfo(&buf, "FROM %s ",
955  generate_relation_name(trigrec->tgconstrrelid, NIL));
956  if (!trigrec->tgdeferrable)
957  appendStringInfoString(&buf, "NOT ");
958  appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
959  if (trigrec->tginitdeferred)
960  appendStringInfoString(&buf, "DEFERRED ");
961  else
962  appendStringInfoString(&buf, "IMMEDIATE ");
963  }
964 
965  value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
966  tgrel->rd_att, &isnull);
967  if (!isnull)
968  tgoldtable = NameStr(*DatumGetName(value));
969  else
970  tgoldtable = NULL;
971  value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
972  tgrel->rd_att, &isnull);
973  if (!isnull)
974  tgnewtable = NameStr(*DatumGetName(value));
975  else
976  tgnewtable = NULL;
977  if (tgoldtable != NULL || tgnewtable != NULL)
978  {
979  appendStringInfoString(&buf, "REFERENCING ");
980  if (tgoldtable != NULL)
981  appendStringInfo(&buf, "OLD TABLE AS %s ",
982  quote_identifier(tgoldtable));
983  if (tgnewtable != NULL)
984  appendStringInfo(&buf, "NEW TABLE AS %s ",
985  quote_identifier(tgnewtable));
986  }
987 
988  if (TRIGGER_FOR_ROW(trigrec->tgtype))
989  appendStringInfoString(&buf, "FOR EACH ROW ");
990  else
991  appendStringInfoString(&buf, "FOR EACH STATEMENT ");
992 
993  /* If the trigger has a WHEN qualification, add that */
994  value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
995  tgrel->rd_att, &isnull);
996  if (!isnull)
997  {
998  Node *qual;
999  char relkind;
1000  deparse_context context;
1001  deparse_namespace dpns;
1002  RangeTblEntry *oldrte;
1003  RangeTblEntry *newrte;
1004 
1005  appendStringInfoString(&buf, "WHEN (");
1006 
1007  qual = stringToNode(TextDatumGetCString(value));
1008 
1009  relkind = get_rel_relkind(trigrec->tgrelid);
1010 
1011  /* Build minimal OLD and NEW RTEs for the rel */
1012  oldrte = makeNode(RangeTblEntry);
1013  oldrte->rtekind = RTE_RELATION;
1014  oldrte->relid = trigrec->tgrelid;
1015  oldrte->relkind = relkind;
1016  oldrte->rellockmode = AccessShareLock;
1017  oldrte->alias = makeAlias("old", NIL);
1018  oldrte->eref = oldrte->alias;
1019  oldrte->lateral = false;
1020  oldrte->inh = false;
1021  oldrte->inFromCl = true;
1022 
1023  newrte = makeNode(RangeTblEntry);
1024  newrte->rtekind = RTE_RELATION;
1025  newrte->relid = trigrec->tgrelid;
1026  newrte->relkind = relkind;
1027  newrte->rellockmode = AccessShareLock;
1028  newrte->alias = makeAlias("new", NIL);
1029  newrte->eref = newrte->alias;
1030  newrte->lateral = false;
1031  newrte->inh = false;
1032  newrte->inFromCl = true;
1033 
1034  /* Build two-element rtable */
1035  memset(&dpns, 0, sizeof(dpns));
1036  dpns.rtable = list_make2(oldrte, newrte);
1037  dpns.subplans = NIL;
1038  dpns.ctes = NIL;
1039  dpns.appendrels = NULL;
1040  set_rtable_names(&dpns, NIL, NULL);
1041  set_simple_column_names(&dpns);
1042 
1043  /* Set up context with one-deep namespace stack */
1044  context.buf = &buf;
1045  context.namespaces = list_make1(&dpns);
1046  context.windowClause = NIL;
1047  context.windowTList = NIL;
1048  context.varprefix = true;
1050  context.wrapColumn = WRAP_COLUMN_DEFAULT;
1051  context.indentLevel = PRETTYINDENT_STD;
1052  context.special_exprkind = EXPR_KIND_NONE;
1053  context.appendparents = NULL;
1054 
1055  get_rule_expr(qual, &context, false);
1056 
1057  appendStringInfoString(&buf, ") ");
1058  }
1059 
1060  appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
1061  generate_function_name(trigrec->tgfoid, 0,
1062  NIL, NULL,
1063  false, NULL, EXPR_KIND_NONE));
1064 
1065  if (trigrec->tgnargs > 0)
1066  {
1067  char *p;
1068  int i;
1069 
1070  value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
1071  tgrel->rd_att, &isnull);
1072  if (isnull)
1073  elog(ERROR, "tgargs is null for trigger %u", trigid);
1074  p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
1075  for (i = 0; i < trigrec->tgnargs; i++)
1076  {
1077  if (i > 0)
1078  appendStringInfoString(&buf, ", ");
1079  simple_quote_literal(&buf, p);
1080  /* advance p to next string embedded in tgargs */
1081  while (*p)
1082  p++;
1083  p++;
1084  }
1085  }
1086 
1087  /* We deliberately do not put semi-colon at end */
1088  appendStringInfoChar(&buf, ')');
1089 
1090  /* Clean up */
1091  systable_endscan(tgscan);
1092 
1093  table_close(tgrel, AccessShareLock);
1094 
1095  return buf.data;
1096 }
1097 
1098 /* ----------
1099  * pg_get_indexdef - Get the definition of an index
1100  *
1101  * In the extended version, there is a colno argument as well as pretty bool.
1102  * if colno == 0, we want a complete index definition.
1103  * if colno > 0, we only want the Nth index key's variable or expression.
1104  *
1105  * Note that the SQL-function versions of this omit any info about the
1106  * index tablespace; this is intentional because pg_dump wants it that way.
1107  * However pg_get_indexdef_string() includes the index tablespace.
1108  * ----------
1109  */
1110 Datum
1112 {
1113  Oid indexrelid = PG_GETARG_OID(0);
1114  int prettyFlags;
1115  char *res;
1116 
1117  prettyFlags = PRETTYFLAG_INDENT;
1118 
1119  res = pg_get_indexdef_worker(indexrelid, 0, NULL,
1120  false, false,
1121  false, false,
1122  prettyFlags, true);
1123 
1124  if (res == NULL)
1125  PG_RETURN_NULL();
1126 
1128 }
1129 
1130 Datum
1132 {
1133  Oid indexrelid = PG_GETARG_OID(0);
1134  int32 colno = PG_GETARG_INT32(1);
1135  bool pretty = PG_GETARG_BOOL(2);
1136  int prettyFlags;
1137  char *res;
1138 
1140 
1141  res = pg_get_indexdef_worker(indexrelid, colno, NULL,
1142  colno != 0, false,
1143  false, false,
1144  prettyFlags, true);
1145 
1146  if (res == NULL)
1147  PG_RETURN_NULL();
1148 
1150 }
1151 
1152 /*
1153  * Internal version for use by ALTER TABLE.
1154  * Includes a tablespace clause in the result.
1155  * Returns a palloc'd C string; no pretty-printing.
1156  */
1157 char *
1159 {
1160  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1161  false, false,
1162  true, true,
1163  0, false);
1164 }
1165 
1166 /* Internal version that just reports the key-column definitions */
1167 char *
1168 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1169 {
1170  int prettyFlags;
1171 
1173 
1174  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1175  true, true,
1176  false, false,
1177  prettyFlags, false);
1178 }
1179 
1180 /*
1181  * Internal workhorse to decompile an index definition.
1182  *
1183  * This is now used for exclusion constraints as well: if excludeOps is not
1184  * NULL then it points to an array of exclusion operator OIDs.
1185  */
1186 static char *
1187 pg_get_indexdef_worker(Oid indexrelid, int colno,
1188  const Oid *excludeOps,
1189  bool attrsOnly, bool keysOnly,
1190  bool showTblSpc, bool inherits,
1191  int prettyFlags, bool missing_ok)
1192 {
1193  /* might want a separate isConstraint parameter later */
1194  bool isConstraint = (excludeOps != NULL);
1195  HeapTuple ht_idx;
1196  HeapTuple ht_idxrel;
1197  HeapTuple ht_am;
1198  Form_pg_index idxrec;
1199  Form_pg_class idxrelrec;
1200  Form_pg_am amrec;
1201  IndexAmRoutine *amroutine;
1202  List *indexprs;
1203  ListCell *indexpr_item;
1204  List *context;
1205  Oid indrelid;
1206  int keyno;
1207  Datum indcollDatum;
1208  Datum indclassDatum;
1209  Datum indoptionDatum;
1210  bool isnull;
1211  oidvector *indcollation;
1212  oidvector *indclass;
1213  int2vector *indoption;
1215  char *str;
1216  char *sep;
1217 
1218  /*
1219  * Fetch the pg_index tuple by the Oid of the index
1220  */
1221  ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1222  if (!HeapTupleIsValid(ht_idx))
1223  {
1224  if (missing_ok)
1225  return NULL;
1226  elog(ERROR, "cache lookup failed for index %u", indexrelid);
1227  }
1228  idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1229 
1230  indrelid = idxrec->indrelid;
1231  Assert(indexrelid == idxrec->indexrelid);
1232 
1233  /* Must get indcollation, indclass, and indoption the hard way */
1234  indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1235  Anum_pg_index_indcollation, &isnull);
1236  Assert(!isnull);
1237  indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1238 
1239  indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1240  Anum_pg_index_indclass, &isnull);
1241  Assert(!isnull);
1242  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1243 
1244  indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1245  Anum_pg_index_indoption, &isnull);
1246  Assert(!isnull);
1247  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1248 
1249  /*
1250  * Fetch the pg_class tuple of the index relation
1251  */
1252  ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1253  if (!HeapTupleIsValid(ht_idxrel))
1254  elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1255  idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1256 
1257  /*
1258  * Fetch the pg_am tuple of the index' access method
1259  */
1260  ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1261  if (!HeapTupleIsValid(ht_am))
1262  elog(ERROR, "cache lookup failed for access method %u",
1263  idxrelrec->relam);
1264  amrec = (Form_pg_am) GETSTRUCT(ht_am);
1265 
1266  /* Fetch the index AM's API struct */
1267  amroutine = GetIndexAmRoutine(amrec->amhandler);
1268 
1269  /*
1270  * Get the index expressions, if any. (NOTE: we do not use the relcache
1271  * versions of the expressions and predicate, because we want to display
1272  * non-const-folded expressions.)
1273  */
1274  if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
1275  {
1276  Datum exprsDatum;
1277  bool isnull;
1278  char *exprsString;
1279 
1280  exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1281  Anum_pg_index_indexprs, &isnull);
1282  Assert(!isnull);
1283  exprsString = TextDatumGetCString(exprsDatum);
1284  indexprs = (List *) stringToNode(exprsString);
1285  pfree(exprsString);
1286  }
1287  else
1288  indexprs = NIL;
1289 
1290  indexpr_item = list_head(indexprs);
1291 
1292  context = deparse_context_for(get_relation_name(indrelid), indrelid);
1293 
1294  /*
1295  * Start the index definition. Note that the index's name should never be
1296  * schema-qualified, but the indexed rel's name may be.
1297  */
1298  initStringInfo(&buf);
1299 
1300  if (!attrsOnly)
1301  {
1302  if (!isConstraint)
1303  appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
1304  idxrec->indisunique ? "UNIQUE " : "",
1305  quote_identifier(NameStr(idxrelrec->relname)),
1306  idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
1307  && !inherits ? "ONLY " : "",
1308  (prettyFlags & PRETTYFLAG_SCHEMA) ?
1309  generate_relation_name(indrelid, NIL) :
1311  quote_identifier(NameStr(amrec->amname)));
1312  else /* currently, must be EXCLUDE constraint */
1313  appendStringInfo(&buf, "EXCLUDE USING %s (",
1314  quote_identifier(NameStr(amrec->amname)));
1315  }
1316 
1317  /*
1318  * Report the indexed attributes
1319  */
1320  sep = "";
1321  for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1322  {
1323  AttrNumber attnum = idxrec->indkey.values[keyno];
1324  Oid keycoltype;
1325  Oid keycolcollation;
1326 
1327  /*
1328  * Ignore non-key attributes if told to.
1329  */
1330  if (keysOnly && keyno >= idxrec->indnkeyatts)
1331  break;
1332 
1333  /* Otherwise, print INCLUDE to divide key and non-key attrs. */
1334  if (!colno && keyno == idxrec->indnkeyatts)
1335  {
1336  appendStringInfoString(&buf, ") INCLUDE (");
1337  sep = "";
1338  }
1339 
1340  if (!colno)
1341  appendStringInfoString(&buf, sep);
1342  sep = ", ";
1343 
1344  if (attnum != 0)
1345  {
1346  /* Simple index column */
1347  char *attname;
1348  int32 keycoltypmod;
1349 
1350  attname = get_attname(indrelid, attnum, false);
1351  if (!colno || colno == keyno + 1)
1352  appendStringInfoString(&buf, quote_identifier(attname));
1353  get_atttypetypmodcoll(indrelid, attnum,
1354  &keycoltype, &keycoltypmod,
1355  &keycolcollation);
1356  }
1357  else
1358  {
1359  /* expressional index */
1360  Node *indexkey;
1361 
1362  if (indexpr_item == NULL)
1363  elog(ERROR, "too few entries in indexprs list");
1364  indexkey = (Node *) lfirst(indexpr_item);
1365  indexpr_item = lnext(indexprs, indexpr_item);
1366  /* Deparse */
1367  str = deparse_expression_pretty(indexkey, context, false, false,
1368  prettyFlags, 0);
1369  if (!colno || colno == keyno + 1)
1370  {
1371  /* Need parens if it's not a bare function call */
1372  if (looks_like_function(indexkey))
1373  appendStringInfoString(&buf, str);
1374  else
1375  appendStringInfo(&buf, "(%s)", str);
1376  }
1377  keycoltype = exprType(indexkey);
1378  keycolcollation = exprCollation(indexkey);
1379  }
1380 
1381  /* Print additional decoration for (selected) key columns */
1382  if (!attrsOnly && keyno < idxrec->indnkeyatts &&
1383  (!colno || colno == keyno + 1))
1384  {
1385  int16 opt = indoption->values[keyno];
1386  Oid indcoll = indcollation->values[keyno];
1387 
1388  /* Add collation, if not default for column */
1389  if (OidIsValid(indcoll) && indcoll != keycolcollation)
1390  appendStringInfo(&buf, " COLLATE %s",
1391  generate_collation_name((indcoll)));
1392 
1393  /* Add the operator class name, if not default */
1394  get_opclass_name(indclass->values[keyno], keycoltype, &buf);
1395 
1396  /* Add options if relevant */
1397  if (amroutine->amcanorder)
1398  {
1399  /* if it supports sort ordering, report DESC and NULLS opts */
1400  if (opt & INDOPTION_DESC)
1401  {
1402  appendStringInfoString(&buf, " DESC");
1403  /* NULLS FIRST is the default in this case */
1404  if (!(opt & INDOPTION_NULLS_FIRST))
1405  appendStringInfoString(&buf, " NULLS LAST");
1406  }
1407  else
1408  {
1409  if (opt & INDOPTION_NULLS_FIRST)
1410  appendStringInfoString(&buf, " NULLS FIRST");
1411  }
1412  }
1413 
1414  /* Add the exclusion operator if relevant */
1415  if (excludeOps != NULL)
1416  appendStringInfo(&buf, " WITH %s",
1417  generate_operator_name(excludeOps[keyno],
1418  keycoltype,
1419  keycoltype));
1420  }
1421  }
1422 
1423  if (!attrsOnly)
1424  {
1425  appendStringInfoChar(&buf, ')');
1426 
1427  /*
1428  * If it has options, append "WITH (options)"
1429  */
1430  str = flatten_reloptions(indexrelid);
1431  if (str)
1432  {
1433  appendStringInfo(&buf, " WITH (%s)", str);
1434  pfree(str);
1435  }
1436 
1437  /*
1438  * Print tablespace, but only if requested
1439  */
1440  if (showTblSpc)
1441  {
1442  Oid tblspc;
1443 
1444  tblspc = get_rel_tablespace(indexrelid);
1445  if (OidIsValid(tblspc))
1446  {
1447  if (isConstraint)
1448  appendStringInfoString(&buf, " USING INDEX");
1449  appendStringInfo(&buf, " TABLESPACE %s",
1451  }
1452  }
1453 
1454  /*
1455  * If it's a partial index, decompile and append the predicate
1456  */
1457  if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
1458  {
1459  Node *node;
1460  Datum predDatum;
1461  bool isnull;
1462  char *predString;
1463 
1464  /* Convert text string to node tree */
1465  predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1466  Anum_pg_index_indpred, &isnull);
1467  Assert(!isnull);
1468  predString = TextDatumGetCString(predDatum);
1469  node = (Node *) stringToNode(predString);
1470  pfree(predString);
1471 
1472  /* Deparse */
1473  str = deparse_expression_pretty(node, context, false, false,
1474  prettyFlags, 0);
1475  if (isConstraint)
1476  appendStringInfo(&buf, " WHERE (%s)", str);
1477  else
1478  appendStringInfo(&buf, " WHERE %s", str);
1479  }
1480  }
1481 
1482  /* Clean up */
1483  ReleaseSysCache(ht_idx);
1484  ReleaseSysCache(ht_idxrel);
1485  ReleaseSysCache(ht_am);
1486 
1487  return buf.data;
1488 }
1489 
1490 /*
1491  * pg_get_statisticsobjdef
1492  * Get the definition of an extended statistics object
1493  */
1494 Datum
1496 {
1497  Oid statextid = PG_GETARG_OID(0);
1498  char *res;
1499 
1500  res = pg_get_statisticsobj_worker(statextid, true);
1501 
1502  if (res == NULL)
1503  PG_RETURN_NULL();
1504 
1506 }
1507 
1508 /*
1509  * Internal workhorse to decompile an extended statistics object.
1510  */
1511 static char *
1512 pg_get_statisticsobj_worker(Oid statextid, bool missing_ok)
1513 {
1514  Form_pg_statistic_ext statextrec;
1515  HeapTuple statexttup;
1517  int colno;
1518  char *nsp;
1519  ArrayType *arr;
1520  char *enabled;
1521  Datum datum;
1522  bool isnull;
1523  bool ndistinct_enabled;
1524  bool dependencies_enabled;
1525  bool mcv_enabled;
1526  int i;
1527 
1528  statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1529 
1530  if (!HeapTupleIsValid(statexttup))
1531  {
1532  if (missing_ok)
1533  return NULL;
1534  elog(ERROR, "cache lookup failed for statistics object %u", statextid);
1535  }
1536 
1537  statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1538 
1539  initStringInfo(&buf);
1540 
1541  nsp = get_namespace_name(statextrec->stxnamespace);
1542  appendStringInfo(&buf, "CREATE STATISTICS %s",
1544  NameStr(statextrec->stxname)));
1545 
1546  /*
1547  * Decode the stxkind column so that we know which stats types to print.
1548  */
1549  datum = SysCacheGetAttr(STATEXTOID, statexttup,
1550  Anum_pg_statistic_ext_stxkind, &isnull);
1551  Assert(!isnull);
1552  arr = DatumGetArrayTypeP(datum);
1553  if (ARR_NDIM(arr) != 1 ||
1554  ARR_HASNULL(arr) ||
1555  ARR_ELEMTYPE(arr) != CHAROID)
1556  elog(ERROR, "stxkind is not a 1-D char array");
1557  enabled = (char *) ARR_DATA_PTR(arr);
1558 
1559  ndistinct_enabled = false;
1560  dependencies_enabled = false;
1561  mcv_enabled = false;
1562 
1563  for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1564  {
1565  if (enabled[i] == STATS_EXT_NDISTINCT)
1566  ndistinct_enabled = true;
1567  if (enabled[i] == STATS_EXT_DEPENDENCIES)
1568  dependencies_enabled = true;
1569  if (enabled[i] == STATS_EXT_MCV)
1570  mcv_enabled = true;
1571  }
1572 
1573  /*
1574  * If any option is disabled, then we'll need to append the types clause
1575  * to show which options are enabled. We omit the types clause on purpose
1576  * when all options are enabled, so a pg_dump/pg_restore will create all
1577  * statistics types on a newer postgres version, if the statistics had all
1578  * options enabled on the original version.
1579  */
1580  if (!ndistinct_enabled || !dependencies_enabled || !mcv_enabled)
1581  {
1582  bool gotone = false;
1583 
1584  appendStringInfoString(&buf, " (");
1585 
1586  if (ndistinct_enabled)
1587  {
1588  appendStringInfoString(&buf, "ndistinct");
1589  gotone = true;
1590  }
1591 
1592  if (dependencies_enabled)
1593  {
1594  appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
1595  gotone = true;
1596  }
1597 
1598  if (mcv_enabled)
1599  appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
1600 
1601  appendStringInfoChar(&buf, ')');
1602  }
1603 
1604  appendStringInfoString(&buf, " ON ");
1605 
1606  for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
1607  {
1608  AttrNumber attnum = statextrec->stxkeys.values[colno];
1609  char *attname;
1610 
1611  if (colno > 0)
1612  appendStringInfoString(&buf, ", ");
1613 
1614  attname = get_attname(statextrec->stxrelid, attnum, false);
1615 
1616  appendStringInfoString(&buf, quote_identifier(attname));
1617  }
1618 
1619  appendStringInfo(&buf, " FROM %s",
1620  generate_relation_name(statextrec->stxrelid, NIL));
1621 
1622  ReleaseSysCache(statexttup);
1623 
1624  return buf.data;
1625 }
1626 
1627 /*
1628  * pg_get_partkeydef
1629  *
1630  * Returns the partition key specification, ie, the following:
1631  *
1632  * PARTITION BY { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
1633  */
1634 Datum
1636 {
1637  Oid relid = PG_GETARG_OID(0);
1638  char *res;
1639 
1640  res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
1641 
1642  if (res == NULL)
1643  PG_RETURN_NULL();
1644 
1646 }
1647 
1648 /* Internal version that just reports the column definitions */
1649 char *
1650 pg_get_partkeydef_columns(Oid relid, bool pretty)
1651 {
1652  int prettyFlags;
1653 
1655 
1656  return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
1657 }
1658 
1659 /*
1660  * Internal workhorse to decompile a partition key definition.
1661  */
1662 static char *
1663 pg_get_partkeydef_worker(Oid relid, int prettyFlags,
1664  bool attrsOnly, bool missing_ok)
1665 {
1667  HeapTuple tuple;
1668  oidvector *partclass;
1669  oidvector *partcollation;
1670  List *partexprs;
1671  ListCell *partexpr_item;
1672  List *context;
1673  Datum datum;
1674  bool isnull;
1676  int keyno;
1677  char *str;
1678  char *sep;
1679 
1680  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
1681  if (!HeapTupleIsValid(tuple))
1682  {
1683  if (missing_ok)
1684  return NULL;
1685  elog(ERROR, "cache lookup failed for partition key of %u", relid);
1686  }
1687 
1688  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
1689 
1690  Assert(form->partrelid == relid);
1691 
1692  /* Must get partclass and partcollation the hard way */
1693  datum = SysCacheGetAttr(PARTRELID, tuple,
1694  Anum_pg_partitioned_table_partclass, &isnull);
1695  Assert(!isnull);
1696  partclass = (oidvector *) DatumGetPointer(datum);
1697 
1698  datum = SysCacheGetAttr(PARTRELID, tuple,
1699  Anum_pg_partitioned_table_partcollation, &isnull);
1700  Assert(!isnull);
1701  partcollation = (oidvector *) DatumGetPointer(datum);
1702 
1703 
1704  /*
1705  * Get the expressions, if any. (NOTE: we do not use the relcache
1706  * versions of the expressions, because we want to display
1707  * non-const-folded expressions.)
1708  */
1709  if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
1710  {
1711  Datum exprsDatum;
1712  bool isnull;
1713  char *exprsString;
1714 
1715  exprsDatum = SysCacheGetAttr(PARTRELID, tuple,
1716  Anum_pg_partitioned_table_partexprs, &isnull);
1717  Assert(!isnull);
1718  exprsString = TextDatumGetCString(exprsDatum);
1719  partexprs = (List *) stringToNode(exprsString);
1720 
1721  if (!IsA(partexprs, List))
1722  elog(ERROR, "unexpected node type found in partexprs: %d",
1723  (int) nodeTag(partexprs));
1724 
1725  pfree(exprsString);
1726  }
1727  else
1728  partexprs = NIL;
1729 
1730  partexpr_item = list_head(partexprs);
1731  context = deparse_context_for(get_relation_name(relid), relid);
1732 
1733  initStringInfo(&buf);
1734 
1735  switch (form->partstrat)
1736  {
1738  if (!attrsOnly)
1739  appendStringInfoString(&buf, "HASH");
1740  break;
1742  if (!attrsOnly)
1743  appendStringInfoString(&buf, "LIST");
1744  break;
1746  if (!attrsOnly)
1747  appendStringInfoString(&buf, "RANGE");
1748  break;
1749  default:
1750  elog(ERROR, "unexpected partition strategy: %d",
1751  (int) form->partstrat);
1752  }
1753 
1754  if (!attrsOnly)
1755  appendStringInfoString(&buf, " (");
1756  sep = "";
1757  for (keyno = 0; keyno < form->partnatts; keyno++)
1758  {
1759  AttrNumber attnum = form->partattrs.values[keyno];
1760  Oid keycoltype;
1761  Oid keycolcollation;
1762  Oid partcoll;
1763 
1764  appendStringInfoString(&buf, sep);
1765  sep = ", ";
1766  if (attnum != 0)
1767  {
1768  /* Simple attribute reference */
1769  char *attname;
1770  int32 keycoltypmod;
1771 
1772  attname = get_attname(relid, attnum, false);
1773  appendStringInfoString(&buf, quote_identifier(attname));
1774  get_atttypetypmodcoll(relid, attnum,
1775  &keycoltype, &keycoltypmod,
1776  &keycolcollation);
1777  }
1778  else
1779  {
1780  /* Expression */
1781  Node *partkey;
1782 
1783  if (partexpr_item == NULL)
1784  elog(ERROR, "too few entries in partexprs list");
1785  partkey = (Node *) lfirst(partexpr_item);
1786  partexpr_item = lnext(partexprs, partexpr_item);
1787 
1788  /* Deparse */
1789  str = deparse_expression_pretty(partkey, context, false, false,
1790  prettyFlags, 0);
1791  /* Need parens if it's not a bare function call */
1792  if (looks_like_function(partkey))
1793  appendStringInfoString(&buf, str);
1794  else
1795  appendStringInfo(&buf, "(%s)", str);
1796 
1797  keycoltype = exprType(partkey);
1798  keycolcollation = exprCollation(partkey);
1799  }
1800 
1801  /* Add collation, if not default for column */
1802  partcoll = partcollation->values[keyno];
1803  if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
1804  appendStringInfo(&buf, " COLLATE %s",
1805  generate_collation_name((partcoll)));
1806 
1807  /* Add the operator class name, if not default */
1808  if (!attrsOnly)
1809  get_opclass_name(partclass->values[keyno], keycoltype, &buf);
1810  }
1811 
1812  if (!attrsOnly)
1813  appendStringInfoChar(&buf, ')');
1814 
1815  /* Clean up */
1816  ReleaseSysCache(tuple);
1817 
1818  return buf.data;
1819 }
1820 
1821 /*
1822  * pg_get_partition_constraintdef
1823  *
1824  * Returns partition constraint expression as a string for the input relation
1825  */
1826 Datum
1828 {
1829  Oid relationId = PG_GETARG_OID(0);
1830  Expr *constr_expr;
1831  int prettyFlags;
1832  List *context;
1833  char *consrc;
1834 
1835  constr_expr = get_partition_qual_relid(relationId);
1836 
1837  /* Quick exit if no partition constraint */
1838  if (constr_expr == NULL)
1839  PG_RETURN_NULL();
1840 
1841  /*
1842  * Deparse and return the constraint expression.
1843  */
1844  prettyFlags = PRETTYFLAG_INDENT;
1845  context = deparse_context_for(get_relation_name(relationId), relationId);
1846  consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
1847  false, prettyFlags, 0);
1848 
1850 }
1851 
1852 /*
1853  * pg_get_partconstrdef_string
1854  *
1855  * Returns the partition constraint as a C-string for the input relation, with
1856  * the given alias. No pretty-printing.
1857  */
1858 char *
1859 pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
1860 {
1861  Expr *constr_expr;
1862  List *context;
1863 
1864  constr_expr = get_partition_qual_relid(partitionId);
1865  context = deparse_context_for(aliasname, partitionId);
1866 
1867  return deparse_expression((Node *) constr_expr, context, true, false);
1868 }
1869 
1870 /*
1871  * pg_get_constraintdef
1872  *
1873  * Returns the definition for the constraint, ie, everything that needs to
1874  * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
1875  */
1876 Datum
1878 {
1879  Oid constraintId = PG_GETARG_OID(0);
1880  int prettyFlags;
1881  char *res;
1882 
1883  prettyFlags = PRETTYFLAG_INDENT;
1884 
1885  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
1886 
1887  if (res == NULL)
1888  PG_RETURN_NULL();
1889 
1891 }
1892 
1893 Datum
1895 {
1896  Oid constraintId = PG_GETARG_OID(0);
1897  bool pretty = PG_GETARG_BOOL(1);
1898  int prettyFlags;
1899  char *res;
1900 
1902 
1903  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
1904 
1905  if (res == NULL)
1906  PG_RETURN_NULL();
1907 
1909 }
1910 
1911 /*
1912  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
1913  */
1914 char *
1916 {
1917  return pg_get_constraintdef_worker(constraintId, true, 0, false);
1918 }
1919 
1920 /*
1921  * As of 9.4, we now use an MVCC snapshot for this.
1922  */
1923 static char *
1924 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
1925  int prettyFlags, bool missing_ok)
1926 {
1927  HeapTuple tup;
1928  Form_pg_constraint conForm;
1930  SysScanDesc scandesc;
1931  ScanKeyData scankey[1];
1933  Relation relation = table_open(ConstraintRelationId, AccessShareLock);
1934 
1935  ScanKeyInit(&scankey[0],
1936  Anum_pg_constraint_oid,
1937  BTEqualStrategyNumber, F_OIDEQ,
1938  ObjectIdGetDatum(constraintId));
1939 
1940  scandesc = systable_beginscan(relation,
1942  true,
1943  snapshot,
1944  1,
1945  scankey);
1946 
1947  /*
1948  * We later use the tuple with SysCacheGetAttr() as if we had obtained it
1949  * via SearchSysCache, which works fine.
1950  */
1951  tup = systable_getnext(scandesc);
1952 
1953  UnregisterSnapshot(snapshot);
1954 
1955  if (!HeapTupleIsValid(tup))
1956  {
1957  if (missing_ok)
1958  {
1959  systable_endscan(scandesc);
1960  table_close(relation, AccessShareLock);
1961  return NULL;
1962  }
1963  elog(ERROR, "could not find tuple for constraint %u", constraintId);
1964  }
1965 
1966  conForm = (Form_pg_constraint) GETSTRUCT(tup);
1967 
1968  initStringInfo(&buf);
1969 
1970  if (fullCommand)
1971  {
1972  if (OidIsValid(conForm->conrelid))
1973  {
1974  /*
1975  * Currently, callers want ALTER TABLE (without ONLY) for CHECK
1976  * constraints, and other types of constraints don't inherit
1977  * anyway so it doesn't matter whether we say ONLY or not. Someday
1978  * we might need to let callers specify whether to put ONLY in the
1979  * command.
1980  */
1981  appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
1982  generate_qualified_relation_name(conForm->conrelid),
1983  quote_identifier(NameStr(conForm->conname)));
1984  }
1985  else
1986  {
1987  /* Must be a domain constraint */
1988  Assert(OidIsValid(conForm->contypid));
1989  appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
1990  generate_qualified_type_name(conForm->contypid),
1991  quote_identifier(NameStr(conForm->conname)));
1992  }
1993  }
1994 
1995  switch (conForm->contype)
1996  {
1997  case CONSTRAINT_FOREIGN:
1998  {
1999  Datum val;
2000  bool isnull;
2001  const char *string;
2002 
2003  /* Start off the constraint definition */
2004  appendStringInfoString(&buf, "FOREIGN KEY (");
2005 
2006  /* Fetch and build referencing-column list */
2007  val = SysCacheGetAttr(CONSTROID, tup,
2008  Anum_pg_constraint_conkey, &isnull);
2009  if (isnull)
2010  elog(ERROR, "null conkey for constraint %u",
2011  constraintId);
2012 
2013  decompile_column_index_array(val, conForm->conrelid, &buf);
2014 
2015  /* add foreign relation name */
2016  appendStringInfo(&buf, ") REFERENCES %s(",
2017  generate_relation_name(conForm->confrelid,
2018  NIL));
2019 
2020  /* Fetch and build referenced-column list */
2021  val = SysCacheGetAttr(CONSTROID, tup,
2022  Anum_pg_constraint_confkey, &isnull);
2023  if (isnull)
2024  elog(ERROR, "null confkey for constraint %u",
2025  constraintId);
2026 
2027  decompile_column_index_array(val, conForm->confrelid, &buf);
2028 
2029  appendStringInfoChar(&buf, ')');
2030 
2031  /* Add match type */
2032  switch (conForm->confmatchtype)
2033  {
2034  case FKCONSTR_MATCH_FULL:
2035  string = " MATCH FULL";
2036  break;
2038  string = " MATCH PARTIAL";
2039  break;
2040  case FKCONSTR_MATCH_SIMPLE:
2041  string = "";
2042  break;
2043  default:
2044  elog(ERROR, "unrecognized confmatchtype: %d",
2045  conForm->confmatchtype);
2046  string = ""; /* keep compiler quiet */
2047  break;
2048  }
2049  appendStringInfoString(&buf, string);
2050 
2051  /* Add ON UPDATE and ON DELETE clauses, if needed */
2052  switch (conForm->confupdtype)
2053  {
2055  string = NULL; /* suppress default */
2056  break;
2058  string = "RESTRICT";
2059  break;
2061  string = "CASCADE";
2062  break;
2064  string = "SET NULL";
2065  break;
2067  string = "SET DEFAULT";
2068  break;
2069  default:
2070  elog(ERROR, "unrecognized confupdtype: %d",
2071  conForm->confupdtype);
2072  string = NULL; /* keep compiler quiet */
2073  break;
2074  }
2075  if (string)
2076  appendStringInfo(&buf, " ON UPDATE %s", string);
2077 
2078  switch (conForm->confdeltype)
2079  {
2081  string = NULL; /* suppress default */
2082  break;
2084  string = "RESTRICT";
2085  break;
2087  string = "CASCADE";
2088  break;
2090  string = "SET NULL";
2091  break;
2093  string = "SET DEFAULT";
2094  break;
2095  default:
2096  elog(ERROR, "unrecognized confdeltype: %d",
2097  conForm->confdeltype);
2098  string = NULL; /* keep compiler quiet */
2099  break;
2100  }
2101  if (string)
2102  appendStringInfo(&buf, " ON DELETE %s", string);
2103 
2104  break;
2105  }
2106  case CONSTRAINT_PRIMARY:
2107  case CONSTRAINT_UNIQUE:
2108  {
2109  Datum val;
2110  bool isnull;
2111  Oid indexId;
2112  int keyatts;
2113  HeapTuple indtup;
2114 
2115  /* Start off the constraint definition */
2116  if (conForm->contype == CONSTRAINT_PRIMARY)
2117  appendStringInfoString(&buf, "PRIMARY KEY (");
2118  else
2119  appendStringInfoString(&buf, "UNIQUE (");
2120 
2121  /* Fetch and build target column list */
2122  val = SysCacheGetAttr(CONSTROID, tup,
2123  Anum_pg_constraint_conkey, &isnull);
2124  if (isnull)
2125  elog(ERROR, "null conkey for constraint %u",
2126  constraintId);
2127 
2128  keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2129 
2130  appendStringInfoChar(&buf, ')');
2131 
2132  indexId = get_constraint_index(constraintId);
2133 
2134  /* Build including column list (from pg_index.indkeys) */
2135  indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2136  if (!HeapTupleIsValid(indtup))
2137  elog(ERROR, "cache lookup failed for index %u", indexId);
2138  val = SysCacheGetAttr(INDEXRELID, indtup,
2139  Anum_pg_index_indnatts, &isnull);
2140  if (isnull)
2141  elog(ERROR, "null indnatts for index %u", indexId);
2142  if (DatumGetInt32(val) > keyatts)
2143  {
2144  Datum cols;
2145  Datum *keys;
2146  int nKeys;
2147  int j;
2148 
2149  appendStringInfoString(&buf, " INCLUDE (");
2150 
2151  cols = SysCacheGetAttr(INDEXRELID, indtup,
2152  Anum_pg_index_indkey, &isnull);
2153  if (isnull)
2154  elog(ERROR, "null indkey for index %u", indexId);
2155 
2157  INT2OID, 2, true, 's',
2158  &keys, NULL, &nKeys);
2159 
2160  for (j = keyatts; j < nKeys; j++)
2161  {
2162  char *colName;
2163 
2164  colName = get_attname(conForm->conrelid,
2165  DatumGetInt16(keys[j]), false);
2166  if (j > keyatts)
2167  appendStringInfoString(&buf, ", ");
2168  appendStringInfoString(&buf, quote_identifier(colName));
2169  }
2170 
2171  appendStringInfoChar(&buf, ')');
2172  }
2173  ReleaseSysCache(indtup);
2174 
2175  /* XXX why do we only print these bits if fullCommand? */
2176  if (fullCommand && OidIsValid(indexId))
2177  {
2178  char *options = flatten_reloptions(indexId);
2179  Oid tblspc;
2180 
2181  if (options)
2182  {
2183  appendStringInfo(&buf, " WITH (%s)", options);
2184  pfree(options);
2185  }
2186 
2187  /*
2188  * Print the tablespace, unless it's the database default.
2189  * This is to help ALTER TABLE usage of this facility,
2190  * which needs this behavior to recreate exact catalog
2191  * state.
2192  */
2193  tblspc = get_rel_tablespace(indexId);
2194  if (OidIsValid(tblspc))
2195  appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2197  }
2198 
2199  break;
2200  }
2201  case CONSTRAINT_CHECK:
2202  {
2203  Datum val;
2204  bool isnull;
2205  char *conbin;
2206  char *consrc;
2207  Node *expr;
2208  List *context;
2209 
2210  /* Fetch constraint expression in parsetree form */
2211  val = SysCacheGetAttr(CONSTROID, tup,
2212  Anum_pg_constraint_conbin, &isnull);
2213  if (isnull)
2214  elog(ERROR, "null conbin for constraint %u",
2215  constraintId);
2216 
2217  conbin = TextDatumGetCString(val);
2218  expr = stringToNode(conbin);
2219 
2220  /* Set up deparsing context for Var nodes in constraint */
2221  if (conForm->conrelid != InvalidOid)
2222  {
2223  /* relation constraint */
2224  context = deparse_context_for(get_relation_name(conForm->conrelid),
2225  conForm->conrelid);
2226  }
2227  else
2228  {
2229  /* domain constraint --- can't have Vars */
2230  context = NIL;
2231  }
2232 
2233  consrc = deparse_expression_pretty(expr, context, false, false,
2234  prettyFlags, 0);
2235 
2236  /*
2237  * Now emit the constraint definition, adding NO INHERIT if
2238  * necessary.
2239  *
2240  * There are cases where the constraint expression will be
2241  * fully parenthesized and we don't need the outer parens ...
2242  * but there are other cases where we do need 'em. Be
2243  * conservative for now.
2244  *
2245  * Note that simply checking for leading '(' and trailing ')'
2246  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2247  */
2248  appendStringInfo(&buf, "CHECK (%s)%s",
2249  consrc,
2250  conForm->connoinherit ? " NO INHERIT" : "");
2251  break;
2252  }
2253  case CONSTRAINT_TRIGGER:
2254 
2255  /*
2256  * There isn't an ALTER TABLE syntax for creating a user-defined
2257  * constraint trigger, but it seems better to print something than
2258  * throw an error; if we throw error then this function couldn't
2259  * safely be applied to all rows of pg_constraint.
2260  */
2261  appendStringInfoString(&buf, "TRIGGER");
2262  break;
2263  case CONSTRAINT_EXCLUSION:
2264  {
2265  Oid indexOid = conForm->conindid;
2266  Datum val;
2267  bool isnull;
2268  Datum *elems;
2269  int nElems;
2270  int i;
2271  Oid *operators;
2272 
2273  /* Extract operator OIDs from the pg_constraint tuple */
2274  val = SysCacheGetAttr(CONSTROID, tup,
2275  Anum_pg_constraint_conexclop,
2276  &isnull);
2277  if (isnull)
2278  elog(ERROR, "null conexclop for constraint %u",
2279  constraintId);
2280 
2282  OIDOID, sizeof(Oid), true, 'i',
2283  &elems, NULL, &nElems);
2284 
2285  operators = (Oid *) palloc(nElems * sizeof(Oid));
2286  for (i = 0; i < nElems; i++)
2287  operators[i] = DatumGetObjectId(elems[i]);
2288 
2289  /* pg_get_indexdef_worker does the rest */
2290  /* suppress tablespace because pg_dump wants it that way */
2292  pg_get_indexdef_worker(indexOid,
2293  0,
2294  operators,
2295  false,
2296  false,
2297  false,
2298  false,
2299  prettyFlags,
2300  false));
2301  break;
2302  }
2303  default:
2304  elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2305  break;
2306  }
2307 
2308  if (conForm->condeferrable)
2309  appendStringInfoString(&buf, " DEFERRABLE");
2310  if (conForm->condeferred)
2311  appendStringInfoString(&buf, " INITIALLY DEFERRED");
2312  if (!conForm->convalidated)
2313  appendStringInfoString(&buf, " NOT VALID");
2314 
2315  /* Cleanup */
2316  systable_endscan(scandesc);
2317  table_close(relation, AccessShareLock);
2318 
2319  return buf.data;
2320 }
2321 
2322 
2323 /*
2324  * Convert an int16[] Datum into a comma-separated list of column names
2325  * for the indicated relation; append the list to buf. Returns the number
2326  * of keys.
2327  */
2328 static int
2329 decompile_column_index_array(Datum column_index_array, Oid relId,
2330  StringInfo buf)
2331 {
2332  Datum *keys;
2333  int nKeys;
2334  int j;
2335 
2336  /* Extract data from array of int16 */
2337  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2338  INT2OID, 2, true, 's',
2339  &keys, NULL, &nKeys);
2340 
2341  for (j = 0; j < nKeys; j++)
2342  {
2343  char *colName;
2344 
2345  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2346 
2347  if (j == 0)
2349  else
2350  appendStringInfo(buf, ", %s", quote_identifier(colName));
2351  }
2352 
2353  return nKeys;
2354 }
2355 
2356 
2357 /* ----------
2358  * pg_get_expr - Decompile an expression tree
2359  *
2360  * Input: an expression tree in nodeToString form, and a relation OID
2361  *
2362  * Output: reverse-listed expression
2363  *
2364  * Currently, the expression can only refer to a single relation, namely
2365  * the one specified by the second parameter. This is sufficient for
2366  * partial indexes, column default expressions, etc. We also support
2367  * Var-free expressions, for which the OID can be InvalidOid.
2368  * ----------
2369  */
2370 Datum
2372 {
2373  text *expr = PG_GETARG_TEXT_PP(0);
2374  Oid relid = PG_GETARG_OID(1);
2375  int prettyFlags;
2376  char *relname;
2377 
2378  prettyFlags = PRETTYFLAG_INDENT;
2379 
2380  if (OidIsValid(relid))
2381  {
2382  /* Get the name for the relation */
2383  relname = get_rel_name(relid);
2384 
2385  /*
2386  * If the OID isn't actually valid, don't throw an error, just return
2387  * NULL. This is a bit questionable, but it's what we've done
2388  * historically, and it can help avoid unwanted failures when
2389  * examining catalog entries for just-deleted relations.
2390  */
2391  if (relname == NULL)
2392  PG_RETURN_NULL();
2393  }
2394  else
2395  relname = NULL;
2396 
2397  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2398 }
2399 
2400 Datum
2402 {
2403  text *expr = PG_GETARG_TEXT_PP(0);
2404  Oid relid = PG_GETARG_OID(1);
2405  bool pretty = PG_GETARG_BOOL(2);
2406  int prettyFlags;
2407  char *relname;
2408 
2410 
2411  if (OidIsValid(relid))
2412  {
2413  /* Get the name for the relation */
2414  relname = get_rel_name(relid);
2415  /* See notes above */
2416  if (relname == NULL)
2417  PG_RETURN_NULL();
2418  }
2419  else
2420  relname = NULL;
2421 
2422  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2423 }
2424 
2425 static text *
2426 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
2427 {
2428  Node *node;
2429  List *context;
2430  char *exprstr;
2431  char *str;
2432 
2433  /* Convert input TEXT object to C string */
2434  exprstr = text_to_cstring(expr);
2435 
2436  /* Convert expression to node tree */
2437  node = (Node *) stringToNode(exprstr);
2438 
2439  pfree(exprstr);
2440 
2441  /* Prepare deparse context if needed */
2442  if (OidIsValid(relid))
2443  context = deparse_context_for(relname, relid);
2444  else
2445  context = NIL;
2446 
2447  /* Deparse */
2448  str = deparse_expression_pretty(node, context, false, false,
2449  prettyFlags, 0);
2450 
2451  return string_to_text(str);
2452 }
2453 
2454 
2455 /* ----------
2456  * pg_get_userbyid - Get a user name by roleid and
2457  * fallback to 'unknown (OID=n)'
2458  * ----------
2459  */
2460 Datum
2462 {
2463  Oid roleid = PG_GETARG_OID(0);
2464  Name result;
2465  HeapTuple roletup;
2466  Form_pg_authid role_rec;
2467 
2468  /*
2469  * Allocate space for the result
2470  */
2471  result = (Name) palloc(NAMEDATALEN);
2472  memset(NameStr(*result), 0, NAMEDATALEN);
2473 
2474  /*
2475  * Get the pg_authid entry and print the result
2476  */
2477  roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2478  if (HeapTupleIsValid(roletup))
2479  {
2480  role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2481  StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
2482  ReleaseSysCache(roletup);
2483  }
2484  else
2485  sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2486 
2487  PG_RETURN_NAME(result);
2488 }
2489 
2490 
2491 /*
2492  * pg_get_serial_sequence
2493  * Get the name of the sequence used by an identity or serial column,
2494  * formatted suitably for passing to setval, nextval or currval.
2495  * First parameter is not treated as double-quoted, second parameter
2496  * is --- see documentation for reason.
2497  */
2498 Datum
2500 {
2501  text *tablename = PG_GETARG_TEXT_PP(0);
2502  text *columnname = PG_GETARG_TEXT_PP(1);
2503  RangeVar *tablerv;
2504  Oid tableOid;
2505  char *column;
2507  Oid sequenceId = InvalidOid;
2508  Relation depRel;
2509  ScanKeyData key[3];
2510  SysScanDesc scan;
2511  HeapTuple tup;
2512 
2513  /* Look up table name. Can't lock it - we might not have privileges. */
2514  tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2515  tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2516 
2517  /* Get the number of the column */
2518  column = text_to_cstring(columnname);
2519 
2520  attnum = get_attnum(tableOid, column);
2521  if (attnum == InvalidAttrNumber)
2522  ereport(ERROR,
2523  (errcode(ERRCODE_UNDEFINED_COLUMN),
2524  errmsg("column \"%s\" of relation \"%s\" does not exist",
2525  column, tablerv->relname)));
2526 
2527  /* Search the dependency table for the dependent sequence */
2528  depRel = table_open(DependRelationId, AccessShareLock);
2529 
2530  ScanKeyInit(&key[0],
2531  Anum_pg_depend_refclassid,
2532  BTEqualStrategyNumber, F_OIDEQ,
2533  ObjectIdGetDatum(RelationRelationId));
2534  ScanKeyInit(&key[1],
2535  Anum_pg_depend_refobjid,
2536  BTEqualStrategyNumber, F_OIDEQ,
2537  ObjectIdGetDatum(tableOid));
2538  ScanKeyInit(&key[2],
2539  Anum_pg_depend_refobjsubid,
2540  BTEqualStrategyNumber, F_INT4EQ,
2541  Int32GetDatum(attnum));
2542 
2543  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2544  NULL, 3, key);
2545 
2546  while (HeapTupleIsValid(tup = systable_getnext(scan)))
2547  {
2548  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2549 
2550  /*
2551  * Look for an auto dependency (serial column) or internal dependency
2552  * (identity column) of a sequence on a column. (We need the relkind
2553  * test because indexes can also have auto dependencies on columns.)
2554  */
2555  if (deprec->classid == RelationRelationId &&
2556  deprec->objsubid == 0 &&
2557  (deprec->deptype == DEPENDENCY_AUTO ||
2558  deprec->deptype == DEPENDENCY_INTERNAL) &&
2559  get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2560  {
2561  sequenceId = deprec->objid;
2562  break;
2563  }
2564  }
2565 
2566  systable_endscan(scan);
2567  table_close(depRel, AccessShareLock);
2568 
2569  if (OidIsValid(sequenceId))
2570  {
2571  char *result;
2572 
2573  result = generate_qualified_relation_name(sequenceId);
2574 
2576  }
2577 
2578  PG_RETURN_NULL();
2579 }
2580 
2581 
2582 /*
2583  * pg_get_functiondef
2584  * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2585  * the specified function.
2586  *
2587  * Note: if you change the output format of this function, be careful not
2588  * to break psql's rules (in \ef and \sf) for identifying the start of the
2589  * function body. To wit: the function body starts on a line that begins
2590  * with "AS ", and no preceding line will look like that.
2591  */
2592 Datum
2594 {
2595  Oid funcid = PG_GETARG_OID(0);
2597  StringInfoData dq;
2598  HeapTuple proctup;
2599  Form_pg_proc proc;
2600  bool isfunction;
2601  Datum tmp;
2602  bool isnull;
2603  const char *prosrc;
2604  const char *name;
2605  const char *nsp;
2606  float4 procost;
2607  int oldlen;
2608 
2609  initStringInfo(&buf);
2610 
2611  /* Look up the function */
2612  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2613  if (!HeapTupleIsValid(proctup))
2614  PG_RETURN_NULL();
2615 
2616  proc = (Form_pg_proc) GETSTRUCT(proctup);
2617  name = NameStr(proc->proname);
2618 
2619  if (proc->prokind == PROKIND_AGGREGATE)
2620  ereport(ERROR,
2621  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2622  errmsg("\"%s\" is an aggregate function", name)));
2623 
2624  isfunction = (proc->prokind != PROKIND_PROCEDURE);
2625 
2626  /*
2627  * We always qualify the function name, to ensure the right function gets
2628  * replaced.
2629  */
2630  nsp = get_namespace_name(proc->pronamespace);
2631  appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2632  isfunction ? "FUNCTION" : "PROCEDURE",
2633  quote_qualified_identifier(nsp, name));
2634  (void) print_function_arguments(&buf, proctup, false, true);
2635  appendStringInfoString(&buf, ")\n");
2636  if (isfunction)
2637  {
2638  appendStringInfoString(&buf, " RETURNS ");
2639  print_function_rettype(&buf, proctup);
2640  appendStringInfoChar(&buf, '\n');
2641  }
2642 
2643  print_function_trftypes(&buf, proctup);
2644 
2645  appendStringInfo(&buf, " LANGUAGE %s\n",
2646  quote_identifier(get_language_name(proc->prolang, false)));
2647 
2648  /* Emit some miscellaneous options on one line */
2649  oldlen = buf.len;
2650 
2651  if (proc->prokind == PROKIND_WINDOW)
2652  appendStringInfoString(&buf, " WINDOW");
2653  switch (proc->provolatile)
2654  {
2655  case PROVOLATILE_IMMUTABLE:
2656  appendStringInfoString(&buf, " IMMUTABLE");
2657  break;
2658  case PROVOLATILE_STABLE:
2659  appendStringInfoString(&buf, " STABLE");
2660  break;
2661  case PROVOLATILE_VOLATILE:
2662  break;
2663  }
2664 
2665  switch (proc->proparallel)
2666  {
2667  case PROPARALLEL_SAFE:
2668  appendStringInfoString(&buf, " PARALLEL SAFE");
2669  break;
2670  case PROPARALLEL_RESTRICTED:
2671  appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2672  break;
2673  case PROPARALLEL_UNSAFE:
2674  break;
2675  }
2676 
2677  if (proc->proisstrict)
2678  appendStringInfoString(&buf, " STRICT");
2679  if (proc->prosecdef)
2680  appendStringInfoString(&buf, " SECURITY DEFINER");
2681  if (proc->proleakproof)
2682  appendStringInfoString(&buf, " LEAKPROOF");
2683 
2684  /* This code for the default cost and rows should match functioncmds.c */
2685  if (proc->prolang == INTERNALlanguageId ||
2686  proc->prolang == ClanguageId)
2687  procost = 1;
2688  else
2689  procost = 100;
2690  if (proc->procost != procost)
2691  appendStringInfo(&buf, " COST %g", proc->procost);
2692 
2693  if (proc->prorows > 0 && proc->prorows != 1000)
2694  appendStringInfo(&buf, " ROWS %g", proc->prorows);
2695 
2696  if (proc->prosupport)
2697  {
2698  Oid argtypes[1];
2699 
2700  /*
2701  * We should qualify the support function's name if it wouldn't be
2702  * resolved by lookup in the current search path.
2703  */
2704  argtypes[0] = INTERNALOID;
2705  appendStringInfo(&buf, " SUPPORT %s",
2706  generate_function_name(proc->prosupport, 1,
2707  NIL, argtypes,
2708  false, NULL, EXPR_KIND_NONE));
2709  }
2710 
2711  if (oldlen != buf.len)
2712  appendStringInfoChar(&buf, '\n');
2713 
2714  /* Emit any proconfig options, one per line */
2715  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
2716  if (!isnull)
2717  {
2718  ArrayType *a = DatumGetArrayTypeP(tmp);
2719  int i;
2720 
2721  Assert(ARR_ELEMTYPE(a) == TEXTOID);
2722  Assert(ARR_NDIM(a) == 1);
2723  Assert(ARR_LBOUND(a)[0] == 1);
2724 
2725  for (i = 1; i <= ARR_DIMS(a)[0]; i++)
2726  {
2727  Datum d;
2728 
2729  d = array_ref(a, 1, &i,
2730  -1 /* varlenarray */ ,
2731  -1 /* TEXT's typlen */ ,
2732  false /* TEXT's typbyval */ ,
2733  'i' /* TEXT's typalign */ ,
2734  &isnull);
2735  if (!isnull)
2736  {
2737  char *configitem = TextDatumGetCString(d);
2738  char *pos;
2739 
2740  pos = strchr(configitem, '=');
2741  if (pos == NULL)
2742  continue;
2743  *pos++ = '\0';
2744 
2745  appendStringInfo(&buf, " SET %s TO ",
2746  quote_identifier(configitem));
2747 
2748  /*
2749  * Variables that are marked GUC_LIST_QUOTE were already fully
2750  * quoted by flatten_set_variable_args() before they were put
2751  * into the proconfig array. However, because the quoting
2752  * rules used there aren't exactly like SQL's, we have to
2753  * break the list value apart and then quote the elements as
2754  * string literals. (The elements may be double-quoted as-is,
2755  * but we can't just feed them to the SQL parser; it would do
2756  * the wrong thing with elements that are zero-length or
2757  * longer than NAMEDATALEN.)
2758  *
2759  * Variables that are not so marked should just be emitted as
2760  * simple string literals. If the variable is not known to
2761  * guc.c, we'll do that; this makes it unsafe to use
2762  * GUC_LIST_QUOTE for extension variables.
2763  */
2764  if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
2765  {
2766  List *namelist;
2767  ListCell *lc;
2768 
2769  /* Parse string into list of identifiers */
2770  if (!SplitGUCList(pos, ',', &namelist))
2771  {
2772  /* this shouldn't fail really */
2773  elog(ERROR, "invalid list syntax in proconfig item");
2774  }
2775  foreach(lc, namelist)
2776  {
2777  char *curname = (char *) lfirst(lc);
2778 
2779  simple_quote_literal(&buf, curname);
2780  if (lnext(namelist, lc))
2781  appendStringInfoString(&buf, ", ");
2782  }
2783  }
2784  else
2785  simple_quote_literal(&buf, pos);
2786  appendStringInfoChar(&buf, '\n');
2787  }
2788  }
2789  }
2790 
2791  /* And finally the function definition ... */
2792  appendStringInfoString(&buf, "AS ");
2793 
2794  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
2795  if (!isnull)
2796  {
2798  appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
2799  }
2800 
2801  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
2802  if (isnull)
2803  elog(ERROR, "null prosrc");
2804  prosrc = TextDatumGetCString(tmp);
2805 
2806  /*
2807  * We always use dollar quoting. Figure out a suitable delimiter.
2808  *
2809  * Since the user is likely to be editing the function body string, we
2810  * shouldn't use a short delimiter that he might easily create a conflict
2811  * with. Hence prefer "$function$"/"$procedure$", but extend if needed.
2812  */
2813  initStringInfo(&dq);
2814  appendStringInfoChar(&dq, '$');
2815  appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
2816  while (strstr(prosrc, dq.data) != NULL)
2817  appendStringInfoChar(&dq, 'x');
2818  appendStringInfoChar(&dq, '$');
2819 
2820  appendBinaryStringInfo(&buf, dq.data, dq.len);
2821  appendStringInfoString(&buf, prosrc);
2822  appendBinaryStringInfo(&buf, dq.data, dq.len);
2823 
2824  appendStringInfoChar(&buf, '\n');
2825 
2826  ReleaseSysCache(proctup);
2827 
2829 }
2830 
2831 /*
2832  * pg_get_function_arguments
2833  * Get a nicely-formatted list of arguments for a function.
2834  * This is everything that would go between the parentheses in
2835  * CREATE FUNCTION.
2836  */
2837 Datum
2839 {
2840  Oid funcid = PG_GETARG_OID(0);
2842  HeapTuple proctup;
2843 
2844  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2845  if (!HeapTupleIsValid(proctup))
2846  PG_RETURN_NULL();
2847 
2848  initStringInfo(&buf);
2849 
2850  (void) print_function_arguments(&buf, proctup, false, true);
2851 
2852  ReleaseSysCache(proctup);
2853 
2855 }
2856 
2857 /*
2858  * pg_get_function_identity_arguments
2859  * Get a formatted list of arguments for a function.
2860  * This is everything that would go between the parentheses in
2861  * ALTER FUNCTION, etc. In particular, don't print defaults.
2862  */
2863 Datum
2865 {
2866  Oid funcid = PG_GETARG_OID(0);
2868  HeapTuple proctup;
2869 
2870  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2871  if (!HeapTupleIsValid(proctup))
2872  PG_RETURN_NULL();
2873 
2874  initStringInfo(&buf);
2875 
2876  (void) print_function_arguments(&buf, proctup, false, false);
2877 
2878  ReleaseSysCache(proctup);
2879 
2881 }
2882 
2883 /*
2884  * pg_get_function_result
2885  * Get a nicely-formatted version of the result type of a function.
2886  * This is what would appear after RETURNS in CREATE FUNCTION.
2887  */
2888 Datum
2890 {
2891  Oid funcid = PG_GETARG_OID(0);
2893  HeapTuple proctup;
2894 
2895  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2896  if (!HeapTupleIsValid(proctup))
2897  PG_RETURN_NULL();
2898 
2899  if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
2900  {
2901  ReleaseSysCache(proctup);
2902  PG_RETURN_NULL();
2903  }
2904 
2905  initStringInfo(&buf);
2906 
2907  print_function_rettype(&buf, proctup);
2908 
2909  ReleaseSysCache(proctup);
2910 
2912 }
2913 
2914 /*
2915  * Guts of pg_get_function_result: append the function's return type
2916  * to the specified buffer.
2917  */
2918 static void
2920 {
2921  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
2922  int ntabargs = 0;
2923  StringInfoData rbuf;
2924 
2925  initStringInfo(&rbuf);
2926 
2927  if (proc->proretset)
2928  {
2929  /* It might be a table function; try to print the arguments */
2930  appendStringInfoString(&rbuf, "TABLE(");
2931  ntabargs = print_function_arguments(&rbuf, proctup, true, false);
2932  if (ntabargs > 0)
2933  appendStringInfoChar(&rbuf, ')');
2934  else
2935  resetStringInfo(&rbuf);
2936  }
2937 
2938  if (ntabargs == 0)
2939  {
2940  /* Not a table function, so do the normal thing */
2941  if (proc->proretset)
2942  appendStringInfoString(&rbuf, "SETOF ");
2943  appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
2944  }
2945 
2946  appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
2947 }
2948 
2949 /*
2950  * Common code for pg_get_function_arguments and pg_get_function_result:
2951  * append the desired subset of arguments to buf. We print only TABLE
2952  * arguments when print_table_args is true, and all the others when it's false.
2953  * We print argument defaults only if print_defaults is true.
2954  * Function return value is the number of arguments printed.
2955  */
2956 static int
2958  bool print_table_args, bool print_defaults)
2959 {
2960  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
2961  int numargs;
2962  Oid *argtypes;
2963  char **argnames;
2964  char *argmodes;
2965  int insertorderbyat = -1;
2966  int argsprinted;
2967  int inputargno;
2968  int nlackdefaults;
2969  List *argdefaults = NIL;
2970  ListCell *nextargdefault = NULL;
2971  int i;
2972 
2973  numargs = get_func_arg_info(proctup,
2974  &argtypes, &argnames, &argmodes);
2975 
2976  nlackdefaults = numargs;
2977  if (print_defaults && proc->pronargdefaults > 0)
2978  {
2979  Datum proargdefaults;
2980  bool isnull;
2981 
2982  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
2983  Anum_pg_proc_proargdefaults,
2984  &isnull);
2985  if (!isnull)
2986  {
2987  char *str;
2988 
2989  str = TextDatumGetCString(proargdefaults);
2990  argdefaults = castNode(List, stringToNode(str));
2991  pfree(str);
2992  nextargdefault = list_head(argdefaults);
2993  /* nlackdefaults counts only *input* arguments lacking defaults */
2994  nlackdefaults = proc->pronargs - list_length(argdefaults);
2995  }
2996  }
2997 
2998  /* Check for special treatment of ordered-set aggregates */
2999  if (proc->prokind == PROKIND_AGGREGATE)
3000  {
3001  HeapTuple aggtup;
3002  Form_pg_aggregate agg;
3003 
3004  aggtup = SearchSysCache1(AGGFNOID, proc->oid);
3005  if (!HeapTupleIsValid(aggtup))
3006  elog(ERROR, "cache lookup failed for aggregate %u",
3007  proc->oid);
3008  agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3009  if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3010  insertorderbyat = agg->aggnumdirectargs;
3011  ReleaseSysCache(aggtup);
3012  }
3013 
3014  argsprinted = 0;
3015  inputargno = 0;
3016  for (i = 0; i < numargs; i++)
3017  {
3018  Oid argtype = argtypes[i];
3019  char *argname = argnames ? argnames[i] : NULL;
3020  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3021  const char *modename;
3022  bool isinput;
3023 
3024  switch (argmode)
3025  {
3026  case PROARGMODE_IN:
3027  modename = "";
3028  isinput = true;
3029  break;
3030  case PROARGMODE_INOUT:
3031  modename = "INOUT ";
3032  isinput = true;
3033  break;
3034  case PROARGMODE_OUT:
3035  modename = "OUT ";
3036  isinput = false;
3037  break;
3038  case PROARGMODE_VARIADIC:
3039  modename = "VARIADIC ";
3040  isinput = true;
3041  break;
3042  case PROARGMODE_TABLE:
3043  modename = "";
3044  isinput = false;
3045  break;
3046  default:
3047  elog(ERROR, "invalid parameter mode '%c'", argmode);
3048  modename = NULL; /* keep compiler quiet */
3049  isinput = false;
3050  break;
3051  }
3052  if (isinput)
3053  inputargno++; /* this is a 1-based counter */
3054 
3055  if (print_table_args != (argmode == PROARGMODE_TABLE))
3056  continue;
3057 
3058  if (argsprinted == insertorderbyat)
3059  {
3060  if (argsprinted)
3061  appendStringInfoChar(buf, ' ');
3062  appendStringInfoString(buf, "ORDER BY ");
3063  }
3064  else if (argsprinted)
3065  appendStringInfoString(buf, ", ");
3066 
3067  appendStringInfoString(buf, modename);
3068  if (argname && argname[0])
3069  appendStringInfo(buf, "%s ", quote_identifier(argname));
3070  appendStringInfoString(buf, format_type_be(argtype));
3071  if (print_defaults && isinput && inputargno > nlackdefaults)
3072  {
3073  Node *expr;
3074 
3075  Assert(nextargdefault != NULL);
3076  expr = (Node *) lfirst(nextargdefault);
3077  nextargdefault = lnext(argdefaults, nextargdefault);
3078 
3079  appendStringInfo(buf, " DEFAULT %s",
3080  deparse_expression(expr, NIL, false, false));
3081  }
3082  argsprinted++;
3083 
3084  /* nasty hack: print the last arg twice for variadic ordered-set agg */
3085  if (argsprinted == insertorderbyat && i == numargs - 1)
3086  {
3087  i--;
3088  /* aggs shouldn't have defaults anyway, but just to be sure ... */
3089  print_defaults = false;
3090  }
3091  }
3092 
3093  return argsprinted;
3094 }
3095 
3096 static bool
3097 is_input_argument(int nth, const char *argmodes)
3098 {
3099  return (!argmodes
3100  || argmodes[nth] == PROARGMODE_IN
3101  || argmodes[nth] == PROARGMODE_INOUT
3102  || argmodes[nth] == PROARGMODE_VARIADIC);
3103 }
3104 
3105 /*
3106  * Append used transformed types to specified buffer
3107  */
3108 static void
3110 {
3111  Oid *trftypes;
3112  int ntypes;
3113 
3114  ntypes = get_func_trftypes(proctup, &trftypes);
3115  if (ntypes > 0)
3116  {
3117  int i;
3118 
3119  appendStringInfoString(buf, "\n TRANSFORM ");
3120  for (i = 0; i < ntypes; i++)
3121  {
3122  if (i != 0)
3123  appendStringInfoString(buf, ", ");
3124  appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3125  }
3126  }
3127 }
3128 
3129 /*
3130  * Get textual representation of a function argument's default value. The
3131  * second argument of this function is the argument number among all arguments
3132  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3133  * how information_schema.sql uses it.
3134  */
3135 Datum
3137 {
3138  Oid funcid = PG_GETARG_OID(0);
3139  int32 nth_arg = PG_GETARG_INT32(1);
3140  HeapTuple proctup;
3141  Form_pg_proc proc;
3142  int numargs;
3143  Oid *argtypes;
3144  char **argnames;
3145  char *argmodes;
3146  int i;
3147  List *argdefaults;
3148  Node *node;
3149  char *str;
3150  int nth_inputarg;
3151  Datum proargdefaults;
3152  bool isnull;
3153  int nth_default;
3154 
3155  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3156  if (!HeapTupleIsValid(proctup))
3157  PG_RETURN_NULL();
3158 
3159  numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3160  if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3161  {
3162  ReleaseSysCache(proctup);
3163  PG_RETURN_NULL();
3164  }
3165 
3166  nth_inputarg = 0;
3167  for (i = 0; i < nth_arg; i++)
3168  if (is_input_argument(i, argmodes))
3169  nth_inputarg++;
3170 
3171  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3172  Anum_pg_proc_proargdefaults,
3173  &isnull);
3174  if (isnull)
3175  {
3176  ReleaseSysCache(proctup);
3177  PG_RETURN_NULL();
3178  }
3179 
3180  str = TextDatumGetCString(proargdefaults);
3181  argdefaults = castNode(List, stringToNode(str));
3182  pfree(str);
3183 
3184  proc = (Form_pg_proc) GETSTRUCT(proctup);
3185 
3186  /*
3187  * Calculate index into proargdefaults: proargdefaults corresponds to the
3188  * last N input arguments, where N = pronargdefaults.
3189  */
3190  nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3191 
3192  if (nth_default < 0 || nth_default >= list_length(argdefaults))
3193  {
3194  ReleaseSysCache(proctup);
3195  PG_RETURN_NULL();
3196  }
3197  node = list_nth(argdefaults, nth_default);
3198  str = deparse_expression(node, NIL, false, false);
3199 
3200  ReleaseSysCache(proctup);
3201 
3203 }
3204 
3205 
3206 /*
3207  * deparse_expression - General utility for deparsing expressions
3208  *
3209  * calls deparse_expression_pretty with all prettyPrinting disabled
3210  */
3211 char *
3212 deparse_expression(Node *expr, List *dpcontext,
3213  bool forceprefix, bool showimplicit)
3214 {
3215  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3216  showimplicit, 0, 0);
3217 }
3218 
3219 /* ----------
3220  * deparse_expression_pretty - General utility for deparsing expressions
3221  *
3222  * expr is the node tree to be deparsed. It must be a transformed expression
3223  * tree (ie, not the raw output of gram.y).
3224  *
3225  * dpcontext is a list of deparse_namespace nodes representing the context
3226  * for interpreting Vars in the node tree. It can be NIL if no Vars are
3227  * expected.
3228  *
3229  * forceprefix is true to force all Vars to be prefixed with their table names.
3230  *
3231  * showimplicit is true to force all implicit casts to be shown explicitly.
3232  *
3233  * Tries to pretty up the output according to prettyFlags and startIndent.
3234  *
3235  * The result is a palloc'd string.
3236  * ----------
3237  */
3238 static char *
3240  bool forceprefix, bool showimplicit,
3241  int prettyFlags, int startIndent)
3242 {
3244  deparse_context context;
3245 
3246  initStringInfo(&buf);
3247  context.buf = &buf;
3248  context.namespaces = dpcontext;
3249  context.windowClause = NIL;
3250  context.windowTList = NIL;
3251  context.varprefix = forceprefix;
3252  context.prettyFlags = prettyFlags;
3253  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3254  context.indentLevel = startIndent;
3255  context.special_exprkind = EXPR_KIND_NONE;
3256  context.appendparents = NULL;
3257 
3258  get_rule_expr(expr, &context, showimplicit);
3259 
3260  return buf.data;
3261 }
3262 
3263 /* ----------
3264  * deparse_context_for - Build deparse context for a single relation
3265  *
3266  * Given the reference name (alias) and OID of a relation, build deparsing
3267  * context for an expression referencing only that relation (as varno 1,
3268  * varlevelsup 0). This is sufficient for many uses of deparse_expression.
3269  * ----------
3270  */
3271 List *
3272 deparse_context_for(const char *aliasname, Oid relid)
3273 {
3274  deparse_namespace *dpns;
3275  RangeTblEntry *rte;
3276 
3277  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3278 
3279  /* Build a minimal RTE for the rel */
3280  rte = makeNode(RangeTblEntry);
3281  rte->rtekind = RTE_RELATION;
3282  rte->relid = relid;
3283  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3285  rte->alias = makeAlias(aliasname, NIL);
3286  rte->eref = rte->alias;
3287  rte->lateral = false;
3288  rte->inh = false;
3289  rte->inFromCl = true;
3290 
3291  /* Build one-element rtable */
3292  dpns->rtable = list_make1(rte);
3293  dpns->subplans = NIL;
3294  dpns->ctes = NIL;
3295  dpns->appendrels = NULL;
3296  set_rtable_names(dpns, NIL, NULL);
3298 
3299  /* Return a one-deep namespace stack */
3300  return list_make1(dpns);
3301 }
3302 
3303 /*
3304  * deparse_context_for_plan_tree - Build deparse context for a Plan tree
3305  *
3306  * When deparsing an expression in a Plan tree, we use the plan's rangetable
3307  * to resolve names of simple Vars. The initialization of column names for
3308  * this is rather expensive if the rangetable is large, and it'll be the same
3309  * for every expression in the Plan tree; so we do it just once and re-use
3310  * the result of this function for each expression. (Note that the result
3311  * is not usable until set_deparse_context_plan() is applied to it.)
3312  *
3313  * In addition to the PlannedStmt, pass the per-RTE alias names
3314  * assigned by a previous call to select_rtable_names_for_explain.
3315  */
3316 List *
3318 {
3319  deparse_namespace *dpns;
3320 
3321  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3322 
3323  /* Initialize fields that stay the same across the whole plan tree */
3324  dpns->rtable = pstmt->rtable;
3325  dpns->rtable_names = rtable_names;
3326  dpns->subplans = pstmt->subplans;
3327  dpns->ctes = NIL;
3328  if (pstmt->appendRelations)
3329  {
3330  /* Set up the array, indexed by child relid */
3331  int ntables = list_length(dpns->rtable);
3332  ListCell *lc;
3333 
3334  dpns->appendrels = (AppendRelInfo **)
3335  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3336  foreach(lc, pstmt->appendRelations)
3337  {
3338  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3339  Index crelid = appinfo->child_relid;
3340 
3341  Assert(crelid > 0 && crelid <= ntables);
3342  Assert(dpns->appendrels[crelid] == NULL);
3343  dpns->appendrels[crelid] = appinfo;
3344  }
3345  }
3346  else
3347  dpns->appendrels = NULL; /* don't need it */
3348 
3349  /*
3350  * Set up column name aliases. We will get rather bogus results for join
3351  * RTEs, but that doesn't matter because plan trees don't contain any join
3352  * alias Vars.
3353  */
3355 
3356  /* Return a one-deep namespace stack */
3357  return list_make1(dpns);
3358 }
3359 
3360 /*
3361  * set_deparse_context_plan - Specify Plan node containing expression
3362  *
3363  * When deparsing an expression in a Plan tree, we might have to resolve
3364  * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
3365  * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
3366  * can be resolved by drilling down into the left and right child plans.
3367  * Similarly, INDEX_VAR references can be resolved by reference to the
3368  * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
3369  * ForeignScan and CustomScan nodes. (Note that we don't currently support
3370  * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
3371  * for those, we can only deparse the indexqualorig fields, which won't
3372  * contain INDEX_VAR Vars.)
3373  *
3374  * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
3375  * the most-closely-nested first. This is needed to resolve PARAM_EXEC
3376  * Params. Note we assume that all the Plan nodes share the same rtable.
3377  *
3378  * Once this function has been called, deparse_expression() can be called on
3379  * subsidiary expression(s) of the specified Plan node. To deparse
3380  * expressions of a different Plan node in the same Plan tree, re-call this
3381  * function to identify the new parent Plan node.
3382  *
3383  * The result is the same List passed in; this is a notational convenience.
3384  */
3385 List *
3386 set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
3387 {
3388  deparse_namespace *dpns;
3389 
3390  /* Should always have one-entry namespace list for Plan deparsing */
3391  Assert(list_length(dpcontext) == 1);
3392  dpns = (deparse_namespace *) linitial(dpcontext);
3393 
3394  /* Set our attention on the specific plan node passed in */
3395  set_deparse_plan(dpns, plan);
3396  dpns->ancestors = ancestors;
3397 
3398  return dpcontext;
3399 }
3400 
3401 /*
3402  * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
3403  *
3404  * Determine the relation aliases we'll use during an EXPLAIN operation.
3405  * This is just a frontend to set_rtable_names. We have to expose the aliases
3406  * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
3407  */
3408 List *
3410 {
3411  deparse_namespace dpns;
3412 
3413  memset(&dpns, 0, sizeof(dpns));
3414  dpns.rtable = rtable;
3415  dpns.subplans = NIL;
3416  dpns.ctes = NIL;
3417  dpns.appendrels = NULL;
3418  set_rtable_names(&dpns, NIL, rels_used);
3419  /* We needn't bother computing column aliases yet */
3420 
3421  return dpns.rtable_names;
3422 }
3423 
3424 /*
3425  * set_rtable_names: select RTE aliases to be used in printing a query
3426  *
3427  * We fill in dpns->rtable_names with a list of names that is one-for-one with
3428  * the already-filled dpns->rtable list. Each RTE name is unique among those
3429  * in the new namespace plus any ancestor namespaces listed in
3430  * parent_namespaces.
3431  *
3432  * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
3433  *
3434  * Note that this function is only concerned with relation names, not column
3435  * names.
3436  */
3437 static void
3438 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
3439  Bitmapset *rels_used)
3440 {
3441  HASHCTL hash_ctl;
3442  HTAB *names_hash;
3443  NameHashEntry *hentry;
3444  bool found;
3445  int rtindex;
3446  ListCell *lc;
3447 
3448  dpns->rtable_names = NIL;
3449  /* nothing more to do if empty rtable */
3450  if (dpns->rtable == NIL)
3451  return;
3452 
3453  /*
3454  * We use a hash table to hold known names, so that this process is O(N)
3455  * not O(N^2) for N names.
3456  */
3457  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
3458  hash_ctl.keysize = NAMEDATALEN;
3459  hash_ctl.entrysize = sizeof(NameHashEntry);
3460  hash_ctl.hcxt = CurrentMemoryContext;
3461  names_hash = hash_create("set_rtable_names names",
3462  list_length(dpns->rtable),
3463  &hash_ctl,
3465  /* Preload the hash table with names appearing in parent_namespaces */
3466  foreach(lc, parent_namespaces)
3467  {
3468  deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
3469  ListCell *lc2;
3470 
3471  foreach(lc2, olddpns->rtable_names)
3472  {
3473  char *oldname = (char *) lfirst(lc2);
3474 
3475  if (oldname == NULL)
3476  continue;
3477  hentry = (NameHashEntry *) hash_search(names_hash,
3478  oldname,
3479  HASH_ENTER,
3480  &found);
3481  /* we do not complain about duplicate names in parent namespaces */
3482  hentry->counter = 0;
3483  }
3484  }
3485 
3486  /* Now we can scan the rtable */
3487  rtindex = 1;
3488  foreach(lc, dpns->rtable)
3489  {
3490  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3491  char *refname;
3492 
3493  /* Just in case this takes an unreasonable amount of time ... */
3495 
3496  if (rels_used && !bms_is_member(rtindex, rels_used))
3497  {
3498  /* Ignore unreferenced RTE */
3499  refname = NULL;
3500  }
3501  else if (rte->alias)
3502  {
3503  /* If RTE has a user-defined alias, prefer that */
3504  refname = rte->alias->aliasname;
3505  }
3506  else if (rte->rtekind == RTE_RELATION)
3507  {
3508  /* Use the current actual name of the relation */
3509  refname = get_rel_name(rte->relid);
3510  }
3511  else if (rte->rtekind == RTE_JOIN)
3512  {
3513  /* Unnamed join has no refname */
3514  refname = NULL;
3515  }
3516  else
3517  {
3518  /* Otherwise use whatever the parser assigned */
3519  refname = rte->eref->aliasname;
3520  }
3521 
3522  /*
3523  * If the selected name isn't unique, append digits to make it so, and
3524  * make a new hash entry for it once we've got a unique name. For a
3525  * very long input name, we might have to truncate to stay within
3526  * NAMEDATALEN.
3527  */
3528  if (refname)
3529  {
3530  hentry = (NameHashEntry *) hash_search(names_hash,
3531  refname,
3532  HASH_ENTER,
3533  &found);
3534  if (found)
3535  {
3536  /* Name already in use, must choose a new one */
3537  int refnamelen = strlen(refname);
3538  char *modname = (char *) palloc(refnamelen + 16);
3539  NameHashEntry *hentry2;
3540 
3541  do
3542  {
3543  hentry->counter++;
3544  for (;;)
3545  {
3546  /*
3547  * We avoid using %.*s here because it can misbehave
3548  * if the data is not valid in what libc thinks is the
3549  * prevailing encoding.
3550  */
3551  memcpy(modname, refname, refnamelen);
3552  sprintf(modname + refnamelen, "_%d", hentry->counter);
3553  if (strlen(modname) < NAMEDATALEN)
3554  break;
3555  /* drop chars from refname to keep all the digits */
3556  refnamelen = pg_mbcliplen(refname, refnamelen,
3557  refnamelen - 1);
3558  }
3559  hentry2 = (NameHashEntry *) hash_search(names_hash,
3560  modname,
3561  HASH_ENTER,
3562  &found);
3563  } while (found);
3564  hentry2->counter = 0; /* init new hash entry */
3565  refname = modname;
3566  }
3567  else
3568  {
3569  /* Name not previously used, need only initialize hentry */
3570  hentry->counter = 0;
3571  }
3572  }
3573 
3574  dpns->rtable_names = lappend(dpns->rtable_names, refname);
3575  rtindex++;
3576  }
3577 
3578  hash_destroy(names_hash);
3579 }
3580 
3581 /*
3582  * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
3583  *
3584  * For convenience, this is defined to initialize the deparse_namespace struct
3585  * from scratch.
3586  */
3587 static void
3589  List *parent_namespaces)
3590 {
3591  ListCell *lc;
3592  ListCell *lc2;
3593 
3594  /* Initialize *dpns and fill rtable/ctes links */
3595  memset(dpns, 0, sizeof(deparse_namespace));
3596  dpns->rtable = query->rtable;
3597  dpns->subplans = NIL;
3598  dpns->ctes = query->cteList;
3599  dpns->appendrels = NULL;
3600 
3601  /* Assign a unique relation alias to each RTE */
3602  set_rtable_names(dpns, parent_namespaces, NULL);
3603 
3604  /* Initialize dpns->rtable_columns to contain zeroed structs */
3605  dpns->rtable_columns = NIL;
3606  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3607  dpns->rtable_columns = lappend(dpns->rtable_columns,
3608  palloc0(sizeof(deparse_columns)));
3609 
3610  /* If it's a utility query, it won't have a jointree */
3611  if (query->jointree)
3612  {
3613  /* Detect whether global uniqueness of USING names is needed */
3614  dpns->unique_using =
3615  has_dangerous_join_using(dpns, (Node *) query->jointree);
3616 
3617  /*
3618  * Select names for columns merged by USING, via a recursive pass over
3619  * the query jointree.
3620  */
3621  set_using_names(dpns, (Node *) query->jointree, NIL);
3622  }
3623 
3624  /*
3625  * Now assign remaining column aliases for each RTE. We do this in a
3626  * linear scan of the rtable, so as to process RTEs whether or not they
3627  * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
3628  * etc). JOIN RTEs must be processed after their children, but this is
3629  * okay because they appear later in the rtable list than their children
3630  * (cf Asserts in identify_join_columns()).
3631  */
3632  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
3633  {
3634  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3635  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
3636 
3637  if (rte->rtekind == RTE_JOIN)
3638  set_join_column_names(dpns, rte, colinfo);
3639  else
3640  set_relation_column_names(dpns, rte, colinfo);
3641  }
3642 }
3643 
3644 /*
3645  * set_simple_column_names: fill in column aliases for non-query situations
3646  *
3647  * This handles EXPLAIN and cases where we only have relation RTEs. Without
3648  * a join tree, we can't do anything smart about join RTEs, but we don't
3649  * need to (note that EXPLAIN should never see join alias Vars anyway).
3650  * If we do hit a join RTE we'll just process it like a non-table base RTE.
3651  */
3652 static void
3654 {
3655  ListCell *lc;
3656  ListCell *lc2;
3657 
3658  /* Initialize dpns->rtable_columns to contain zeroed structs */
3659  dpns->rtable_columns = NIL;
3660  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3661  dpns->rtable_columns = lappend(dpns->rtable_columns,
3662  palloc0(sizeof(deparse_columns)));
3663 
3664  /* Assign unique column aliases within each RTE */
3665  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
3666  {
3667  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3668  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
3669 
3670  set_relation_column_names(dpns, rte, colinfo);
3671  }
3672 }
3673 
3674 /*
3675  * has_dangerous_join_using: search jointree for unnamed JOIN USING
3676  *
3677  * Merged columns of a JOIN USING may act differently from either of the input
3678  * columns, either because they are merged with COALESCE (in a FULL JOIN) or
3679  * because an implicit coercion of the underlying input column is required.
3680  * In such a case the column must be referenced as a column of the JOIN not as
3681  * a column of either input. And this is problematic if the join is unnamed
3682  * (alias-less): we cannot qualify the column's name with an RTE name, since
3683  * there is none. (Forcibly assigning an alias to the join is not a solution,
3684  * since that will prevent legal references to tables below the join.)
3685  * To ensure that every column in the query is unambiguously referenceable,
3686  * we must assign such merged columns names that are globally unique across
3687  * the whole query, aliasing other columns out of the way as necessary.
3688  *
3689  * Because the ensuing re-aliasing is fairly damaging to the readability of
3690  * the query, we don't do this unless we have to. So, we must pre-scan
3691  * the join tree to see if we have to, before starting set_using_names().
3692  */
3693 static bool
3695 {
3696  if (IsA(jtnode, RangeTblRef))
3697  {
3698  /* nothing to do here */
3699  }
3700  else if (IsA(jtnode, FromExpr))
3701  {
3702  FromExpr *f = (FromExpr *) jtnode;
3703  ListCell *lc;
3704 
3705  foreach(lc, f->fromlist)
3706  {
3707  if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
3708  return true;
3709  }
3710  }
3711  else if (IsA(jtnode, JoinExpr))
3712  {
3713  JoinExpr *j = (JoinExpr *) jtnode;
3714 
3715  /* Is it an unnamed JOIN with USING? */
3716  if (j->alias == NULL && j->usingClause)
3717  {
3718  /*
3719  * Yes, so check each join alias var to see if any of them are not
3720  * simple references to underlying columns. If so, we have a
3721  * dangerous situation and must pick unique aliases.
3722  */
3723  RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
3724 
3725  /* We need only examine the merged columns */
3726  for (int i = 0; i < jrte->joinmergedcols; i++)
3727  {
3728  Node *aliasvar = list_nth(jrte->joinaliasvars, i);
3729 
3730  if (!IsA(aliasvar, Var))
3731  return true;
3732  }
3733  }
3734 
3735  /* Nope, but inspect children */
3736  if (has_dangerous_join_using(dpns, j->larg))
3737  return true;
3738  if (has_dangerous_join_using(dpns, j->rarg))
3739  return true;
3740  }
3741  else
3742  elog(ERROR, "unrecognized node type: %d",
3743  (int) nodeTag(jtnode));
3744  return false;
3745 }
3746 
3747 /*
3748  * set_using_names: select column aliases to be used for merged USING columns
3749  *
3750  * We do this during a recursive descent of the query jointree.
3751  * dpns->unique_using must already be set to determine the global strategy.
3752  *
3753  * Column alias info is saved in the dpns->rtable_columns list, which is
3754  * assumed to be filled with pre-zeroed deparse_columns structs.
3755  *
3756  * parentUsing is a list of all USING aliases assigned in parent joins of
3757  * the current jointree node. (The passed-in list must not be modified.)
3758  */
3759 static void
3760 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
3761 {
3762  if (IsA(jtnode, RangeTblRef))
3763  {
3764  /* nothing to do now */
3765  }
3766  else if (IsA(jtnode, FromExpr))
3767  {
3768  FromExpr *f = (FromExpr *) jtnode;
3769  ListCell *lc;
3770 
3771  foreach(lc, f->fromlist)
3772  set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
3773  }
3774  else if (IsA(jtnode, JoinExpr))
3775  {
3776  JoinExpr *j = (JoinExpr *) jtnode;
3777  RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
3778  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
3779  int *leftattnos;
3780  int *rightattnos;
3781  deparse_columns *leftcolinfo;
3782  deparse_columns *rightcolinfo;
3783  int i;
3784  ListCell *lc;
3785 
3786  /* Get info about the shape of the join */
3787  identify_join_columns(j, rte, colinfo);
3788  leftattnos = colinfo->leftattnos;
3789  rightattnos = colinfo->rightattnos;
3790 
3791  /* Look up the not-yet-filled-in child deparse_columns structs */
3792  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
3793  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
3794 
3795  /*
3796  * If this join is unnamed, then we cannot substitute new aliases at
3797  * this level, so any name requirements pushed down to here must be
3798  * pushed down again to the children.
3799  */
3800  if (rte->alias == NULL)
3801  {
3802  for (i = 0; i < colinfo->num_cols; i++)
3803  {
3804  char *colname = colinfo->colnames[i];
3805 
3806  if (colname == NULL)
3807  continue;
3808 
3809  /* Push down to left column, unless it's a system column */
3810  if (leftattnos[i] > 0)
3811  {
3812  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
3813  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
3814  }
3815 
3816  /* Same on the righthand side */
3817  if (rightattnos[i] > 0)
3818  {
3819  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
3820  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
3821  }
3822  }
3823  }
3824 
3825  /*
3826  * If there's a USING clause, select the USING column names and push
3827  * those names down to the children. We have two strategies:
3828  *
3829  * If dpns->unique_using is true, we force all USING names to be
3830  * unique across the whole query level. In principle we'd only need
3831  * the names of dangerous USING columns to be globally unique, but to
3832  * safely assign all USING names in a single pass, we have to enforce
3833  * the same uniqueness rule for all of them. However, if a USING
3834  * column's name has been pushed down from the parent, we should use
3835  * it as-is rather than making a uniqueness adjustment. This is
3836  * necessary when we're at an unnamed join, and it creates no risk of
3837  * ambiguity. Also, if there's a user-written output alias for a
3838  * merged column, we prefer to use that rather than the input name;
3839  * this simplifies the logic and seems likely to lead to less aliasing
3840  * overall.
3841  *
3842  * If dpns->unique_using is false, we only need USING names to be
3843  * unique within their own join RTE. We still need to honor
3844  * pushed-down names, though.
3845  *
3846  * Though significantly different in results, these two strategies are
3847  * implemented by the same code, with only the difference of whether
3848  * to put assigned names into dpns->using_names.
3849  */
3850  if (j->usingClause)
3851  {
3852  /* Copy the input parentUsing list so we don't modify it */
3853  parentUsing = list_copy(parentUsing);
3854 
3855  /* USING names must correspond to the first join output columns */
3857  i = 0;
3858  foreach(lc, j->usingClause)
3859  {
3860  char *colname = strVal(lfirst(lc));
3861 
3862  /* Assert it's a merged column */
3863  Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
3864 
3865  /* Adopt passed-down name if any, else select unique name */
3866  if (colinfo->colnames[i] != NULL)
3867  colname = colinfo->colnames[i];
3868  else
3869  {
3870  /* Prefer user-written output alias if any */
3871  if (rte->alias && i < list_length(rte->alias->colnames))
3872  colname = strVal(list_nth(rte->alias->colnames, i));
3873  /* Make it appropriately unique */
3874  colname = make_colname_unique(colname, dpns, colinfo);
3875  if (dpns->unique_using)
3876  dpns->using_names = lappend(dpns->using_names,
3877  colname);
3878  /* Save it as output column name, too */
3879  colinfo->colnames[i] = colname;
3880  }
3881 
3882  /* Remember selected names for use later */
3883  colinfo->usingNames = lappend(colinfo->usingNames, colname);
3884  parentUsing = lappend(parentUsing, colname);
3885 
3886  /* Push down to left column, unless it's a system column */
3887  if (leftattnos[i] > 0)
3888  {
3889  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
3890  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
3891  }
3892 
3893  /* Same on the righthand side */
3894  if (rightattnos[i] > 0)
3895  {
3896  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
3897  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
3898  }
3899 
3900  i++;
3901  }
3902  }
3903 
3904  /* Mark child deparse_columns structs with correct parentUsing info */
3905  leftcolinfo->parentUsing = parentUsing;
3906  rightcolinfo->parentUsing = parentUsing;
3907 
3908  /* Now recursively assign USING column names in children */
3909  set_using_names(dpns, j->larg, parentUsing);
3910  set_using_names(dpns, j->rarg, parentUsing);
3911  }
3912  else
3913  elog(ERROR, "unrecognized node type: %d",
3914  (int) nodeTag(jtnode));
3915 }
3916 
3917 /*
3918  * set_relation_column_names: select column aliases for a non-join RTE
3919  *
3920  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
3921  * If any colnames entries are already filled in, those override local
3922  * choices.
3923  */
3924 static void
3926  deparse_columns *colinfo)
3927 {
3928  int ncolumns;
3929  char **real_colnames;
3930  bool changed_any;
3931  int noldcolumns;
3932  int i;
3933  int j;
3934 
3935  /*
3936  * Extract the RTE's "real" column names. This is comparable to
3937  * get_rte_attribute_name, except that it's important to disregard dropped
3938  * columns. We put NULL into the array for a dropped column.
3939  */
3940  if (rte->rtekind == RTE_RELATION)
3941  {
3942  /* Relation --- look to the system catalogs for up-to-date info */
3943  Relation rel;
3944  TupleDesc tupdesc;
3945 
3946  rel = relation_open(rte->relid, AccessShareLock);
3947  tupdesc = RelationGetDescr(rel);
3948 
3949  ncolumns = tupdesc->natts;
3950  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
3951 
3952  for (i = 0; i < ncolumns; i++)
3953  {
3954  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
3955 
3956  if (attr->attisdropped)
3957  real_colnames[i] = NULL;
3958  else
3959  real_colnames[i] = pstrdup(NameStr(attr->attname));
3960  }
3962  }
3963  else
3964  {
3965  /* Otherwise use the column names from eref */
3966  ListCell *lc;
3967 
3968  ncolumns = list_length(rte->eref->colnames);
3969  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
3970 
3971  i = 0;
3972  foreach(lc, rte->eref->colnames)
3973  {
3974  /*
3975  * If the column name shown in eref is an empty string, then it's
3976  * a column that was dropped at the time of parsing the query, so
3977  * treat it as dropped.
3978  */
3979  char *cname = strVal(lfirst(lc));
3980 
3981  if (cname[0] == '\0')
3982  cname = NULL;
3983  real_colnames[i] = cname;
3984  i++;
3985  }
3986  }
3987 
3988  /*
3989  * Ensure colinfo->colnames has a slot for each column. (It could be long
3990  * enough already, if we pushed down a name for the last column.) Note:
3991  * it's possible that there are now more columns than there were when the
3992  * query was parsed, ie colnames could be longer than rte->eref->colnames.
3993  * We must assign unique aliases to the new columns too, else there could
3994  * be unresolved conflicts when the view/rule is reloaded.
3995  */
3996  expand_colnames_array_to(colinfo, ncolumns);
3997  Assert(colinfo->num_cols == ncolumns);
3998 
3999  /*
4000  * Make sufficiently large new_colnames and is_new_col arrays, too.
4001  *
4002  * Note: because we leave colinfo->num_new_cols zero until after the loop,
4003  * colname_is_unique will not consult that array, which is fine because it
4004  * would only be duplicate effort.
4005  */
4006  colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
4007  colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
4008 
4009  /*
4010  * Scan the columns, select a unique alias for each one, and store it in
4011  * colinfo->colnames and colinfo->new_colnames. The former array has NULL
4012  * entries for dropped columns, the latter omits them. Also mark
4013  * new_colnames entries as to whether they are new since parse time; this
4014  * is the case for entries beyond the length of rte->eref->colnames.
4015  */
4016  noldcolumns = list_length(rte->eref->colnames);
4017  changed_any = false;
4018  j = 0;
4019  for (i = 0; i < ncolumns; i++)
4020  {
4021  char *real_colname = real_colnames[i];
4022  char *colname = colinfo->colnames[i];
4023 
4024  /* Skip dropped columns */
4025  if (real_colname == NULL)
4026  {
4027  Assert(colname == NULL); /* colnames[i] is already NULL */
4028  continue;
4029  }
4030 
4031  /* If alias already assigned, that's what to use */
4032  if (colname == NULL)
4033  {
4034  /* If user wrote an alias, prefer that over real column name */
4035  if (rte->alias && i < list_length(rte->alias->colnames))
4036  colname = strVal(list_nth(rte->alias->colnames, i));
4037  else
4038  colname = real_colname;
4039 
4040  /* Unique-ify and insert into colinfo */
4041  colname = make_colname_unique(colname, dpns, colinfo);
4042 
4043  colinfo->colnames[i] = colname;
4044  }
4045 
4046  /* Put names of non-dropped columns in new_colnames[] too */
4047  colinfo->new_colnames[j] = colname;
4048  /* And mark them as new or not */
4049  colinfo->is_new_col[j] = (i >= noldcolumns);
4050  j++;
4051 
4052  /* Remember if any assigned aliases differ from "real" name */
4053  if (!changed_any && strcmp(colname, real_colname) != 0)
4054  changed_any = true;
4055  }
4056 
4057  /*
4058  * Set correct length for new_colnames[] array. (Note: if columns have
4059  * been added, colinfo->num_cols includes them, which is not really quite
4060  * right but is harmless, since any new columns must be at the end where
4061  * they won't affect varattnos of pre-existing columns.)
4062  */
4063  colinfo->num_new_cols = j;
4064 
4065  /*
4066  * For a relation RTE, we need only print the alias column names if any
4067  * are different from the underlying "real" names. For a function RTE,
4068  * always emit a complete column alias list; this is to protect against
4069  * possible instability of the default column names (eg, from altering
4070  * parameter names). For tablefunc RTEs, we never print aliases, because
4071  * the column names are part of the clause itself. For other RTE types,
4072  * print if we changed anything OR if there were user-written column
4073  * aliases (since the latter would be part of the underlying "reality").
4074  */
4075  if (rte->rtekind == RTE_RELATION)
4076  colinfo->printaliases = changed_any;
4077  else if (rte->rtekind == RTE_FUNCTION)
4078  colinfo->printaliases = true;
4079  else if (rte->rtekind == RTE_TABLEFUNC)
4080  colinfo->printaliases = false;
4081  else if (rte->alias && rte->alias->colnames != NIL)
4082  colinfo->printaliases = true;
4083  else
4084  colinfo->printaliases = changed_any;
4085 }
4086 
4087 /*
4088  * set_join_column_names: select column aliases for a join RTE
4089  *
4090  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4091  * If any colnames entries are already filled in, those override local
4092  * choices. Also, names for USING columns were already chosen by
4093  * set_using_names(). We further expect that column alias selection has been
4094  * completed for both input RTEs.
4095  */
4096 static void
4098  deparse_columns *colinfo)
4099 {
4100  deparse_columns *leftcolinfo;
4101  deparse_columns *rightcolinfo;
4102  bool changed_any;
4103  int noldcolumns;
4104  int nnewcolumns;
4105  Bitmapset *leftmerged = NULL;
4106  Bitmapset *rightmerged = NULL;
4107  int i;
4108  int j;
4109  int ic;
4110  int jc;
4111 
4112  /* Look up the previously-filled-in child deparse_columns structs */
4113  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4114  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4115 
4116  /*
4117  * Ensure colinfo->colnames has a slot for each column. (It could be long
4118  * enough already, if we pushed down a name for the last column.) Note:
4119  * it's possible that one or both inputs now have more columns than there
4120  * were when the query was parsed, but we'll deal with that below. We
4121  * only need entries in colnames for pre-existing columns.
4122  */
4123  noldcolumns = list_length(rte->eref->colnames);
4124  expand_colnames_array_to(colinfo, noldcolumns);
4125  Assert(colinfo->num_cols == noldcolumns);
4126 
4127  /*
4128  * Scan the join output columns, select an alias for each one, and store
4129  * it in colinfo->colnames. If there are USING columns, set_using_names()
4130  * already selected their names, so we can start the loop at the first
4131  * non-merged column.
4132  */
4133  changed_any = false;
4134  for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
4135  {
4136  char *colname = colinfo->colnames[i];
4137  char *real_colname;
4138 
4139  /* Join column must refer to at least one input column */
4140  Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
4141 
4142  /* Get the child column name */
4143  if (colinfo->leftattnos[i] > 0)
4144  real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
4145  else if (colinfo->rightattnos[i] > 0)
4146  real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
4147  else
4148  {
4149  /* We're joining system columns --- use eref name */
4150  real_colname = strVal(list_nth(rte->eref->colnames, i));
4151  }
4152 
4153  /* If child col has been dropped, no need to assign a join colname */
4154  if (real_colname == NULL)
4155  {
4156  colinfo->colnames[i] = NULL;
4157  continue;
4158  }
4159 
4160  /* In an unnamed join, just report child column names as-is */
4161  if (rte->alias == NULL)
4162  {
4163  colinfo->colnames[i] = real_colname;
4164  continue;
4165  }
4166 
4167  /* If alias already assigned, that's what to use */
4168  if (colname == NULL)
4169  {
4170  /* If user wrote an alias, prefer that over real column name */
4171  if (rte->alias && i < list_length(rte->alias->colnames))
4172  colname = strVal(list_nth(rte->alias->colnames, i));
4173  else
4174  colname = real_colname;
4175 
4176  /* Unique-ify and insert into colinfo */
4177  colname = make_colname_unique(colname, dpns, colinfo);
4178 
4179  colinfo->colnames[i] = colname;
4180  }
4181 
4182  /* Remember if any assigned aliases differ from "real" name */
4183  if (!changed_any && strcmp(colname, real_colname) != 0)
4184  changed_any = true;
4185  }
4186 
4187  /*
4188  * Calculate number of columns the join would have if it were re-parsed
4189  * now, and create storage for the new_colnames and is_new_col arrays.
4190  *
4191  * Note: colname_is_unique will be consulting new_colnames[] during the
4192  * loops below, so its not-yet-filled entries must be zeroes.
4193  */
4194  nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
4195  list_length(colinfo->usingNames);
4196  colinfo->num_new_cols = nnewcolumns;
4197  colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
4198  colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
4199 
4200  /*
4201  * Generating the new_colnames array is a bit tricky since any new columns
4202  * added since parse time must be inserted in the right places. This code
4203  * must match the parser, which will order a join's columns as merged
4204  * columns first (in USING-clause order), then non-merged columns from the
4205  * left input (in attnum order), then non-merged columns from the right
4206  * input (ditto). If one of the inputs is itself a join, its columns will
4207  * be ordered according to the same rule, which means newly-added columns
4208  * might not be at the end. We can figure out what's what by consulting
4209  * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
4210  *
4211  * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
4212  * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
4213  * meanings for the current child RTE.
4214  */
4215 
4216  /* Handle merged columns; they are first and can't be new */
4217  i = j = 0;
4218  while (i < noldcolumns &&
4219  colinfo->leftattnos[i] != 0 &&
4220  colinfo->rightattnos[i] != 0)
4221  {
4222  /* column name is already determined and known unique */
4223  colinfo->new_colnames[j] = colinfo->colnames[i];
4224  colinfo->is_new_col[j] = false;
4225 
4226  /* build bitmapsets of child attnums of merged columns */
4227  if (colinfo->leftattnos[i] > 0)
4228  leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
4229  if (colinfo->rightattnos[i] > 0)
4230  rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
4231 
4232  i++, j++;
4233  }
4234 
4235  /* Handle non-merged left-child columns */
4236  ic = 0;
4237  for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
4238  {
4239  char *child_colname = leftcolinfo->new_colnames[jc];
4240 
4241  if (!leftcolinfo->is_new_col[jc])
4242  {
4243  /* Advance ic to next non-dropped old column of left child */
4244  while (ic < leftcolinfo->num_cols &&
4245  leftcolinfo->colnames[ic] == NULL)
4246  ic++;
4247  Assert(ic < leftcolinfo->num_cols);
4248  ic++;
4249  /* If it is a merged column, we already processed it */
4250  if (bms_is_member(ic, leftmerged))
4251  continue;
4252  /* Else, advance i to the corresponding existing join column */
4253  while (i < colinfo->num_cols &&
4254  colinfo->colnames[i] == NULL)
4255  i++;
4256  Assert(i < colinfo->num_cols);
4257  Assert(ic == colinfo->leftattnos[i]);
4258  /* Use the already-assigned name of this column */
4259  colinfo->new_colnames[j] = colinfo->colnames[i];
4260  i++;
4261  }
4262  else
4263  {
4264  /*
4265  * Unique-ify the new child column name and assign, unless we're
4266  * in an unnamed join, in which case just copy
4267  */
4268  if (rte->alias != NULL)
4269  {
4270  colinfo->new_colnames[j] =
4271  make_colname_unique(child_colname, dpns, colinfo);
4272  if (!changed_any &&
4273  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4274  changed_any = true;
4275  }
4276  else
4277  colinfo->new_colnames[j] = child_colname;
4278  }
4279 
4280  colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
4281  j++;
4282  }
4283 
4284  /* Handle non-merged right-child columns in exactly the same way */
4285  ic = 0;
4286  for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
4287  {
4288  char *child_colname = rightcolinfo->new_colnames[jc];
4289 
4290  if (!rightcolinfo->is_new_col[jc])
4291  {
4292  /* Advance ic to next non-dropped old column of right child */
4293  while (ic < rightcolinfo->num_cols &&
4294  rightcolinfo->colnames[ic] == NULL)
4295  ic++;
4296  Assert(ic < rightcolinfo->num_cols);
4297  ic++;
4298  /* If it is a merged column, we already processed it */
4299  if (bms_is_member(ic, rightmerged))
4300  continue;
4301  /* Else, advance i to the corresponding existing join column */
4302  while (i < colinfo->num_cols &&
4303  colinfo->colnames[i] == NULL)
4304  i++;
4305  Assert(i < colinfo->num_cols);
4306  Assert(ic == colinfo->rightattnos[i]);
4307  /* Use the already-assigned name of this column */
4308  colinfo->new_colnames[j] = colinfo->colnames[i];
4309  i++;
4310  }
4311  else
4312  {
4313  /*
4314  * Unique-ify the new child column name and assign, unless we're
4315  * in an unnamed join, in which case just copy
4316  */
4317  if (rte->alias != NULL)
4318  {
4319  colinfo->new_colnames[j] =
4320  make_colname_unique(child_colname, dpns, colinfo);
4321  if (!changed_any &&
4322  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4323  changed_any = true;
4324  }
4325  else
4326  colinfo->new_colnames[j] = child_colname;
4327  }
4328 
4329  colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
4330  j++;
4331  }
4332 
4333  /* Assert we processed the right number of columns */
4334 #ifdef USE_ASSERT_CHECKING
4335  while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
4336  i++;
4337  Assert(i == colinfo->num_cols);
4338  Assert(j == nnewcolumns);
4339 #endif
4340 
4341  /*
4342  * For a named join, print column aliases if we changed any from the child
4343  * names. Unnamed joins cannot print aliases.
4344  */
4345  if (rte->alias != NULL)
4346  colinfo->printaliases = changed_any;
4347  else
4348  colinfo->printaliases = false;
4349 }
4350 
4351 /*
4352  * colname_is_unique: is colname distinct from already-chosen column names?
4353  *
4354  * dpns is query-wide info, colinfo is for the column's RTE
4355  */
4356 static bool
4357 colname_is_unique(const char *colname, deparse_namespace *dpns,
4358  deparse_columns *colinfo)
4359 {
4360  int i;
4361  ListCell *lc;
4362 
4363  /* Check against already-assigned column aliases within RTE */
4364  for (i = 0; i < colinfo->num_cols; i++)
4365  {
4366  char *oldname = colinfo->colnames[i];
4367 
4368  if (oldname && strcmp(oldname, colname) == 0)
4369  return false;
4370  }
4371 
4372  /*
4373  * If we're building a new_colnames array, check that too (this will be
4374  * partially but not completely redundant with the previous checks)
4375  */
4376  for (i = 0; i < colinfo->num_new_cols; i++)
4377  {
4378  char *oldname = colinfo->new_colnames[i];
4379 
4380  if (oldname && strcmp(oldname, colname) == 0)
4381  return false;
4382  }
4383 
4384  /* Also check against USING-column names that must be globally unique */
4385  foreach(lc, dpns->using_names)
4386  {
4387  char *oldname = (char *) lfirst(lc);
4388 
4389  if (strcmp(oldname, colname) == 0)
4390  return false;
4391  }
4392 
4393  /* Also check against names already assigned for parent-join USING cols */
4394  foreach(lc, colinfo->parentUsing)
4395  {
4396  char *oldname = (char *) lfirst(lc);
4397 
4398  if (strcmp(oldname, colname) == 0)
4399  return false;
4400  }
4401 
4402  return true;
4403 }
4404 
4405 /*
4406  * make_colname_unique: modify colname if necessary to make it unique
4407  *
4408  * dpns is query-wide info, colinfo is for the column's RTE
4409  */
4410 static char *
4412  deparse_columns *colinfo)
4413 {
4414  /*
4415  * If the selected name isn't unique, append digits to make it so. For a
4416  * very long input name, we might have to truncate to stay within
4417  * NAMEDATALEN.
4418  */
4419  if (!colname_is_unique(colname, dpns, colinfo))
4420  {
4421  int colnamelen = strlen(colname);
4422  char *modname = (char *) palloc(colnamelen + 16);
4423  int i = 0;
4424 
4425  do
4426  {
4427  i++;
4428  for (;;)
4429  {
4430  /*
4431  * We avoid using %.*s here because it can misbehave if the
4432  * data is not valid in what libc thinks is the prevailing
4433  * encoding.
4434  */
4435  memcpy(modname, colname, colnamelen);
4436  sprintf(modname + colnamelen, "_%d", i);
4437  if (strlen(modname) < NAMEDATALEN)
4438  break;
4439  /* drop chars from colname to keep all the digits */
4440  colnamelen = pg_mbcliplen(colname, colnamelen,
4441  colnamelen - 1);
4442  }
4443  } while (!colname_is_unique(modname, dpns, colinfo));
4444  colname = modname;
4445  }
4446  return colname;
4447 }
4448 
4449 /*
4450  * expand_colnames_array_to: make colinfo->colnames at least n items long
4451  *
4452  * Any added array entries are initialized to zero.
4453  */
4454 static void
4456 {
4457  if (n > colinfo->num_cols)
4458  {
4459  if (colinfo->colnames == NULL)
4460  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4461  else
4462  {
4463  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4464  n * sizeof(char *));
4465  memset(colinfo->colnames + colinfo->num_cols, 0,
4466  (n - colinfo->num_cols) * sizeof(char *));
4467  }
4468  colinfo->num_cols = n;
4469  }
4470 }
4471 
4472 /*
4473  * identify_join_columns: figure out where columns of a join come from
4474  *
4475  * Fills the join-specific fields of the colinfo struct, except for
4476  * usingNames which is filled later.
4477  */
4478 static void
4480  deparse_columns *colinfo)
4481 {
4482  int numjoincols;
4483  int jcolno;
4484  int rcolno;
4485  ListCell *lc;
4486 
4487  /* Extract left/right child RT indexes */
4488  if (IsA(j->larg, RangeTblRef))
4489  colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
4490  else if (IsA(j->larg, JoinExpr))
4491  colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
4492  else
4493  elog(ERROR, "unrecognized node type in jointree: %d",
4494  (int) nodeTag(j->larg));
4495  if (IsA(j->rarg, RangeTblRef))
4496  colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
4497  else if (IsA(j->rarg, JoinExpr))
4498  colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
4499  else
4500  elog(ERROR, "unrecognized node type in jointree: %d",
4501  (int) nodeTag(j->rarg));
4502 
4503  /* Assert children will be processed earlier than join in second pass */
4504  Assert(colinfo->leftrti < j->rtindex);
4505  Assert(colinfo->rightrti < j->rtindex);
4506 
4507  /* Initialize result arrays with zeroes */
4508  numjoincols = list_length(jrte->joinaliasvars);
4509  Assert(numjoincols == list_length(jrte->eref->colnames));
4510  colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
4511  colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
4512 
4513  /*
4514  * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
4515  * Recall that the column(s) merged due to USING are the first column(s)
4516  * of the join output. We need not do anything special while scanning
4517  * joinleftcols, but while scanning joinrightcols we must distinguish
4518  * merged from unmerged columns.
4519  */
4520  jcolno = 0;
4521  foreach(lc, jrte->joinleftcols)
4522  {
4523  int leftattno = lfirst_int(lc);
4524 
4525  colinfo->leftattnos[jcolno++] = leftattno;
4526  }
4527  rcolno = 0;
4528  foreach(lc, jrte->joinrightcols)
4529  {
4530  int rightattno = lfirst_int(lc);
4531 
4532  if (rcolno < jrte->joinmergedcols) /* merged column? */
4533  colinfo->rightattnos[rcolno] = rightattno;
4534  else
4535  colinfo->rightattnos[jcolno++] = rightattno;
4536  rcolno++;
4537  }
4538  Assert(jcolno == numjoincols);
4539 }
4540 
4541 /*
4542  * get_rtable_name: convenience function to get a previously assigned RTE alias
4543  *
4544  * The RTE must belong to the topmost namespace level in "context".
4545  */
4546 static char *
4547 get_rtable_name(int rtindex, deparse_context *context)
4548 {
4550 
4551  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4552  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4553 }
4554 
4555 /*
4556  * set_deparse_plan: set up deparse_namespace to parse subexpressions
4557  * of a given Plan node
4558  *
4559  * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
4560  * and index_tlist fields. Caller is responsible for adjusting the ancestors
4561  * list if necessary. Note that the rtable, subplans, and ctes fields do
4562  * not need to change when shifting attention to different plan nodes in a
4563  * single plan tree.
4564  */
4565 static void
4567 {
4568  dpns->plan = plan;
4569 
4570  /*
4571  * We special-case Append and MergeAppend to pretend that the first child
4572  * plan is the OUTER referent; we have to interpret OUTER Vars in their
4573  * tlists according to one of the children, and the first one is the most
4574  * natural choice. Likewise special-case ModifyTable to pretend that the
4575  * first child plan is the OUTER referent; this is to support RETURNING
4576  * lists containing references to non-target relations.
4577  */
4578  if (IsA(plan, Append))
4579  dpns->outer_plan = linitial(((Append *) plan)->appendplans);
4580  else if (IsA(plan, MergeAppend))
4581  dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
4582  else if (IsA(plan, ModifyTable))
4583  dpns->outer_plan = linitial(((ModifyTable *) plan)->plans);
4584  else
4585  dpns->outer_plan = outerPlan(plan);
4586 
4587  if (dpns->outer_plan)
4588  dpns->outer_tlist = dpns->outer_plan->targetlist;
4589  else
4590  dpns->outer_tlist = NIL;
4591 
4592  /*
4593  * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
4594  * use OUTER because that could someday conflict with the normal meaning.)
4595  * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
4596  * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
4597  * excluded expression's tlist. (Similar to the SubqueryScan we don't want
4598  * to reuse OUTER, it's used for RETURNING in some modify table cases,
4599  * although not INSERT .. CONFLICT).
4600  */
4601  if (IsA(plan, SubqueryScan))
4602  dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
4603  else if (IsA(plan, CteScan))
4604  dpns->inner_plan = list_nth(dpns->subplans,
4605  ((CteScan *) plan)->ctePlanId - 1);
4606  else if (IsA(plan, ModifyTable))
4607  dpns->inner_plan = plan;
4608  else
4609  dpns->inner_plan = innerPlan(plan);
4610 
4611  if (IsA(plan, ModifyTable))
4612  dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
4613  else if (dpns->inner_plan)
4614  dpns->inner_tlist = dpns->inner_plan->targetlist;
4615  else
4616  dpns->inner_tlist = NIL;
4617 
4618  /* Set up referent for INDEX_VAR Vars, if needed */
4619  if (IsA(plan, IndexOnlyScan))
4620  dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
4621  else if (IsA(plan, ForeignScan))
4622  dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
4623  else if (IsA(plan, CustomScan))
4624  dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
4625  else
4626  dpns->index_tlist = NIL;
4627 }
4628 
4629 /*
4630  * push_child_plan: temporarily transfer deparsing attention to a child plan
4631  *
4632  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
4633  * deparse context in case the referenced expression itself uses
4634  * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
4635  * affecting levelsup issues (although in a Plan tree there really shouldn't
4636  * be any).
4637  *
4638  * Caller must provide a local deparse_namespace variable to save the
4639  * previous state for pop_child_plan.
4640  */
4641 static void
4643  deparse_namespace *save_dpns)
4644 {
4645  /* Save state for restoration later */
4646  *save_dpns = *dpns;
4647 
4648  /* Link current plan node into ancestors list */
4649  dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
4650 
4651  /* Set attention on selected child */
4652  set_deparse_plan(dpns, plan);
4653 }
4654 
4655 /*
4656  * pop_child_plan: undo the effects of push_child_plan
4657  */
4658 static void
4660 {
4661  List *ancestors;
4662 
4663  /* Get rid of ancestors list cell added by push_child_plan */
4664  ancestors = list_delete_first(dpns->ancestors);
4665 
4666  /* Restore fields changed by push_child_plan */
4667  *dpns = *save_dpns;
4668 
4669  /* Make sure dpns->ancestors is right (may be unnecessary) */
4670  dpns->ancestors = ancestors;
4671 }
4672 
4673 /*
4674  * push_ancestor_plan: temporarily transfer deparsing attention to an
4675  * ancestor plan
4676  *
4677  * When expanding a Param reference, we must adjust the deparse context
4678  * to match the plan node that contains the expression being printed;
4679  * otherwise we'd fail if that expression itself contains a Param or
4680  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
4681  *
4682  * The target ancestor is conveniently identified by the ListCell holding it
4683  * in dpns->ancestors.
4684  *
4685  * Caller must provide a local deparse_namespace variable to save the
4686  * previous state for pop_ancestor_plan.
4687  */
4688 static void
4690  deparse_namespace *save_dpns)
4691 {
4692  Plan *plan = (Plan *) lfirst(ancestor_cell);
4693 
4694  /* Save state for restoration later */
4695  *save_dpns = *dpns;
4696 
4697  /* Build a new ancestor list with just this node's ancestors */
4698  dpns->ancestors =
4699  list_copy_tail(dpns->ancestors,
4700  list_cell_number(dpns->ancestors, ancestor_cell) + 1);
4701 
4702  /* Set attention on selected ancestor */
4703  set_deparse_plan(dpns, plan);
4704 }
4705 
4706 /*
4707  * pop_ancestor_plan: undo the effects of push_ancestor_plan
4708  */
4709 static void
4711 {
4712  /* Free the ancestor list made in push_ancestor_plan */
4713  list_free(dpns->ancestors);
4714 
4715  /* Restore fields changed by push_ancestor_plan */
4716  *dpns = *save_dpns;
4717 }
4718 
4719 
4720 /* ----------
4721  * make_ruledef - reconstruct the CREATE RULE command
4722  * for a given pg_rewrite tuple
4723  * ----------
4724  */
4725 static void
4727  int prettyFlags)
4728 {
4729  char *rulename;
4730  char ev_type;
4731  Oid ev_class;
4732  bool is_instead;
4733  char *ev_qual;
4734  char *ev_action;
4735  List *actions = NIL;
4736  Relation ev_relation;
4737  TupleDesc viewResultDesc = NULL;
4738  int fno;
4739  Datum dat;
4740  bool isnull;
4741 
4742  /*
4743  * Get the attribute values from the rules tuple
4744  */
4745  fno = SPI_fnumber(rulettc, "rulename");
4746  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4747  Assert(!isnull);
4748  rulename = NameStr(*(DatumGetName(dat)));
4749 
4750  fno = SPI_fnumber(rulettc, "ev_type");
4751  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4752  Assert(!isnull);
4753  ev_type = DatumGetChar(dat);
4754 
4755  fno = SPI_fnumber(rulettc, "ev_class");
4756  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4757  Assert(!isnull);
4758  ev_class = DatumGetObjectId(dat);
4759 
4760  fno = SPI_fnumber(rulettc, "is_instead");
4761  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4762  Assert(!isnull);
4763  is_instead = DatumGetBool(dat);
4764 
4765  /* these could be nulls */
4766  fno = SPI_fnumber(rulettc, "ev_qual");
4767  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
4768 
4769  fno = SPI_fnumber(rulettc, "ev_action");
4770  ev_action = SPI_getvalue(ruletup, rulettc, fno);
4771  if (ev_action != NULL)
4772  actions = (List *) stringToNode(ev_action);
4773 
4774  ev_relation = table_open(ev_class, AccessShareLock);
4775 
4776  /*
4777  * Build the rules definition text
4778  */
4779  appendStringInfo(buf, "CREATE RULE %s AS",
4780  quote_identifier(rulename));
4781 
4782  if (prettyFlags & PRETTYFLAG_INDENT)
4783  appendStringInfoString(buf, "\n ON ");
4784  else
4785  appendStringInfoString(buf, " ON ");
4786 
4787  /* The event the rule is fired for */
4788  switch (ev_type)
4789  {
4790  case '1':
4791  appendStringInfoString(buf, "SELECT");
4792  viewResultDesc = RelationGetDescr(ev_relation);
4793  break;
4794 
4795  case '2':
4796  appendStringInfoString(buf, "UPDATE");
4797  break;
4798 
4799  case '3':
4800  appendStringInfoString(buf, "INSERT");
4801  break;
4802 
4803  case '4':
4804  appendStringInfoString(buf, "DELETE");
4805  break;
4806 
4807  default:
4808  ereport(ERROR,
4809  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4810  errmsg("rule \"%s\" has unsupported event type %d",
4811  rulename, ev_type)));
4812  break;
4813  }
4814 
4815  /* The relation the rule is fired on */
4816  appendStringInfo(buf, " TO %s",
4817  (prettyFlags & PRETTYFLAG_SCHEMA) ?
4818  generate_relation_name(ev_class, NIL) :
4820 
4821  /* If the rule has an event qualification, add it */
4822  if (ev_qual == NULL)
4823  ev_qual = "";
4824  if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
4825  {
4826  Node *qual;
4827  Query *query;
4828  deparse_context context;
4829  deparse_namespace dpns;
4830 
4831  if (prettyFlags & PRETTYFLAG_INDENT)
4832  appendStringInfoString(buf, "\n ");
4833  appendStringInfoString(buf, " WHERE ");
4834 
4835  qual = stringToNode(ev_qual);
4836 
4837  /*
4838  * We need to make a context for recognizing any Vars in the qual
4839  * (which can only be references to OLD and NEW). Use the rtable of
4840  * the first query in the action list for this purpose.
4841  */
4842  query = (Query *) linitial(actions);
4843 
4844  /*
4845  * If the action is INSERT...SELECT, OLD/NEW have been pushed down
4846  * into the SELECT, and that's what we need to look at. (Ugly kluge
4847  * ... try to fix this when we redesign querytrees.)
4848  */
4849  query = getInsertSelectQuery(query, NULL);
4850 
4851  /* Must acquire locks right away; see notes in get_query_def() */
4852  AcquireRewriteLocks(query, false, false);
4853 
4854  context.buf = buf;
4855  context.namespaces = list_make1(&dpns);
4856  context.windowClause = NIL;
4857  context.windowTList = NIL;
4858  context.varprefix = (list_length(query->rtable) != 1);
4859  context.prettyFlags = prettyFlags;
4860  context.wrapColumn = WRAP_COLUMN_DEFAULT;
4861  context.indentLevel = PRETTYINDENT_STD;
4862  context.special_exprkind = EXPR_KIND_NONE;
4863  context.appendparents = NULL;
4864 
4865  set_deparse_for_query(&dpns, query, NIL);
4866 
4867  get_rule_expr(qual, &context, false);
4868  }
4869 
4870  appendStringInfoString(buf, " DO ");
4871 
4872  /* The INSTEAD keyword (if so) */
4873  if (is_instead)
4874  appendStringInfoString(buf, "INSTEAD ");
4875 
4876  /* Finally the rules actions */
4877  if (list_length(actions) > 1)
4878  {
4879  ListCell *action;
4880  Query *query;
4881 
4882  appendStringInfoChar(buf, '(');
4883  foreach(action, actions)
4884  {
4885  query = (Query *) lfirst(action);
4886  get_query_def(query, buf, NIL, viewResultDesc,
4887  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
4888  if (prettyFlags)
4889  appendStringInfoString(buf, ";\n");
4890  else
4891  appendStringInfoString(buf, "; ");
4892  }
4893  appendStringInfoString(buf, ");");
4894  }
4895  else if (list_length(actions) == 0)
4896  {
4897  appendStringInfoString(buf, "NOTHING;");
4898  }
4899  else
4900  {
4901  Query *query;
4902 
4903  query = (Query *) linitial(actions);
4904  get_query_def(query, buf, NIL, viewResultDesc,
4905  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
4906  appendStringInfoChar(buf, ';');
4907  }
4908 
4909  table_close(ev_relation, AccessShareLock);
4910 }
4911 
4912 
4913 /* ----------
4914  * make_viewdef - reconstruct the SELECT part of a
4915  * view rewrite rule
4916  * ----------
4917  */
4918 static void
4920  int prettyFlags, int wrapColumn)
4921 {
4922  Query *query;
4923  char ev_type;
4924  Oid ev_class;
4925  bool is_instead;
4926  char *ev_qual;
4927  char *ev_action;
4928  List *actions = NIL;
4929  Relation ev_relation;
4930  int fno;
4931  Datum dat;
4932  bool isnull;
4933 
4934  /*
4935  * Get the attribute values from the rules tuple
4936  */
4937  fno = SPI_fnumber(rulettc, "ev_type");
4938  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4939  Assert(!isnull);
4940  ev_type = DatumGetChar(dat);
4941 
4942  fno = SPI_fnumber(rulettc, "ev_class");
4943  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4944  Assert(!isnull);
4945  ev_class = DatumGetObjectId(dat);
4946 
4947  fno = SPI_fnumber(rulettc, "is_instead");
4948  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4949  Assert(!isnull);
4950  is_instead = DatumGetBool(dat);
4951 
4952  /* these could be nulls */
4953  fno = SPI_fnumber(rulettc, "ev_qual");
4954  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
4955 
4956  fno = SPI_fnumber(rulettc, "ev_action");
4957  ev_action = SPI_getvalue(ruletup, rulettc, fno);
4958  if (ev_action != NULL)
4959  actions = (List *) stringToNode(ev_action);
4960 
4961  if (list_length(actions) != 1)
4962  {
4963  /* keep output buffer empty and leave */
4964  return;
4965  }
4966 
4967  query = (Query *) linitial(actions);
4968 
4969  if (ev_type != '1' || !is_instead ||
4970  strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
4971  {
4972  /* keep output buffer empty and leave */
4973  return;
4974  }
4975 
4976  ev_relation = table_open(ev_class, AccessShareLock);
4977 
4978  get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
4979  prettyFlags, wrapColumn, 0);
4980  appendStringInfoChar(buf, ';');
4981 
4982  table_close(ev_relation, AccessShareLock);
4983 }
4984 
4985 
4986 /* ----------
4987  * get_query_def - Parse back one query parsetree
4988  *
4989  * If resultDesc is not NULL, then it is the output tuple descriptor for
4990  * the view represented by a SELECT query.
4991  * ----------
4992  */
4993 static void
4994 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
4995  TupleDesc resultDesc,
4996  int prettyFlags, int wrapColumn, int startIndent)
4997 {
4998  deparse_context context;
4999  deparse_namespace dpns;
5000 
5001  /* Guard against excessively long or deeply-nested queries */
5004 
5005  /*
5006  * Before we begin to examine the query, acquire locks on referenced
5007  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5008  * consistent results. Note we assume it's OK to scribble on the passed
5009  * querytree!
5010  *
5011  * We are only deparsing the query (we are not about to execute it), so we
5012  * only need AccessShareLock on the relations it mentions.
5013  */
5014  AcquireRewriteLocks(query, false, false);
5015 
5016  context.buf = buf;
5017  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5018  context.windowClause = NIL;
5019  context.windowTList = NIL;
5020  context.varprefix = (parentnamespace != NIL ||
5021  list_length(query->rtable) != 1);
5022  context.prettyFlags = prettyFlags;
5023  context.wrapColumn = wrapColumn;
5024  context.indentLevel = startIndent;
5025  context.special_exprkind = EXPR_KIND_NONE;
5026  context.appendparents = NULL;
5027 
5028  set_deparse_for_query(&dpns, query, parentnamespace);
5029 
5030  switch (query->commandType)
5031  {
5032  case CMD_SELECT:
5033  get_select_query_def(query, &context, resultDesc);
5034  break;
5035 
5036  case CMD_UPDATE:
5037  get_update_query_def(query, &context);
5038  break;
5039 
5040  case CMD_INSERT:
5041  get_insert_query_def(query, &context);
5042  break;
5043 
5044  case CMD_DELETE:
5045  get_delete_query_def(query, &context);
5046  break;
5047 
5048  case CMD_NOTHING:
5049  appendStringInfoString(buf, "NOTHING");
5050  break;
5051 
5052  case CMD_UTILITY:
5053  get_utility_query_def(query, &context);
5054  break;
5055 
5056  default:
5057  elog(ERROR, "unrecognized query command type: %d",
5058  query->commandType);
5059  break;
5060  }
5061 }
5062 
5063 /* ----------
5064  * get_values_def - Parse back a VALUES list
5065  * ----------
5066  */
5067 static void
5068 get_values_def(List *values_lists, deparse_context *context)
5069 {
5070  StringInfo buf = context->buf;
5071  bool first_list = true;
5072  ListCell *vtl;
5073 
5074  appendStringInfoString(buf, "VALUES ");
5075 
5076  foreach(vtl, values_lists)
5077  {
5078  List *sublist = (List *) lfirst(vtl);
5079  bool first_col = true;
5080  ListCell *lc;
5081 
5082  if (first_list)
5083  first_list = false;
5084  else
5085  appendStringInfoString(buf, ", ");
5086 
5087  appendStringInfoChar(buf, '(');
5088  foreach(lc, sublist)
5089  {
5090  Node *col = (Node *) lfirst(lc);
5091 
5092  if (first_col)
5093  first_col = false;
5094  else
5095  appendStringInfoChar(buf, ',');
5096 
5097  /*
5098  * Print the value. Whole-row Vars need special treatment.
5099  */
5100  get_rule_expr_toplevel(col, context, false);
5101  }
5102  appendStringInfoChar(buf, ')');
5103  }
5104 }
5105 
5106 /* ----------
5107  * get_with_clause - Parse back a WITH clause
5108  * ----------
5109  */
5110 static void
5112 {
5113  StringInfo buf = context->buf;
5114  const char *sep;
5115  ListCell *l;
5116 
5117  if (query->cteList == NIL)
5118  return;
5119 
5120  if (PRETTY_INDENT(context))
5121  {
5122  context->indentLevel += PRETTYINDENT_STD;
5123  appendStringInfoChar(buf, ' ');
5124  }
5125 
5126  if (query->hasRecursive)
5127  sep = "WITH RECURSIVE ";
5128  else
5129  sep = "WITH ";
5130  foreach(l, query->cteList)
5131  {
5132  CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
5133 
5134  appendStringInfoString(buf, sep);
5136  if (cte->aliascolnames)
5137  {
5138  bool first = true;
5139  ListCell *col;
5140 
5141  appendStringInfoChar(buf, '(');
5142  foreach(col, cte->aliascolnames)
5143  {
5144  if (first)
5145  first = false;
5146  else
5147  appendStringInfoString(buf, ", ");
5149  quote_identifier(strVal(lfirst(col))));
5150  }
5151  appendStringInfoChar(buf, ')');
5152  }
5153  appendStringInfoString(buf, " AS ");
5154  switch (cte->ctematerialized)
5155  {
5156  case CTEMaterializeDefault:
5157  break;
5158  case CTEMaterializeAlways:
5159  appendStringInfoString(buf, "MATERIALIZED ");
5160  break;
5161  case CTEMaterializeNever:
5162  appendStringInfoString(buf, "NOT MATERIALIZED ");
5163  break;
5164  }
5165  appendStringInfoChar(buf, '(');
5166  if (PRETTY_INDENT(context))
5167  appendContextKeyword(context, "", 0, 0, 0);
5168  get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5169  context->prettyFlags, context->wrapColumn,
5170  context->indentLevel);
5171  if (PRETTY_INDENT(context))
5172  appendContextKeyword(context, "", 0, 0, 0);
5173  appendStringInfoChar(buf, ')');
5174  sep = ", ";
5175  }
5176 
5177  if (PRETTY_INDENT(context))
5178  {
5179  context->indentLevel -= PRETTYINDENT_STD;
5180  appendContextKeyword(context, "", 0, 0, 0);
5181  }
5182  else
5183  appendStringInfoChar(buf, ' ');
5184 }
5185 
5186 /* ----------
5187  * get_select_query_def - Parse back a SELECT parsetree
5188  * ----------
5189  */
5190 static void
5192  TupleDesc resultDesc)
5193 {
5194  StringInfo buf = context->buf;
5195  List *save_windowclause;
5196  List *save_windowtlist;
5197  bool force_colno;
5198  ListCell *l;
5199 
5200  /* Insert the WITH clause if given */
5201  get_with_clause(query, context);
5202 
5203  /* Set up context for possible window functions */
5204  save_windowclause = context->windowClause;
5205  context->windowClause = query->windowClause;
5206  save_windowtlist = context->windowTList;
5207  context->windowTList = query->targetList;
5208 
5209  /*
5210  * If the Query node has a setOperations tree, then it's the top level of
5211  * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
5212  * fields are interesting in the top query itself.
5213  */
5214  if (query->setOperations)
5215  {
5216  get_setop_query(query->setOperations, query, context, resultDesc);
5217  /* ORDER BY clauses must be simple in this case */
5218  force_colno = true;
5219  }
5220  else
5221  {
5222  get_basic_select_query(query, context, resultDesc);
5223  force_colno = false;
5224  }
5225 
5226  /* Add the ORDER BY clause if given */
5227  if (query->sortClause != NIL)
5228  {
5229  appendContextKeyword(context, " ORDER BY ",
5231  get_rule_orderby(query->sortClause, query->targetList,
5232  force_colno, context);
5233  }
5234 
5235  /* Add the LIMIT clause if given */
5236  if (query->limitOffset != NULL)
5237  {
5238  appendContextKeyword(context, " OFFSET ",
5240  get_rule_expr(query->limitOffset, context, false);
5241  }
5242  if (query->limitCount != NULL)
5243  {
5244  appendContextKeyword(context, " LIMIT ",
5246  if (IsA(query->limitCount, Const) &&
5247  ((Const *) query->limitCount)->constisnull)
5248  appendStringInfoString(buf, "ALL");
5249  else
5250  get_rule_expr(query->limitCount, context, false);
5251  }
5252 
5253  /* Add FOR [KEY] UPDATE/SHARE clauses if present */
5254  if (query->hasForUpdate)
5255  {
5256  foreach(l, query->rowMarks)
5257  {
5258  RowMarkClause *rc = (RowMarkClause *) lfirst(l);
5259 
5260  /* don't print implicit clauses */
5261  if (rc->pushedDown)
5262  continue;
5263 
5264  switch (rc->strength)
5265  {
5266  case LCS_NONE:
5267  /* we intentionally throw an error for LCS_NONE */
5268  elog(ERROR, "unrecognized LockClauseStrength %d",
5269  (int) rc->strength);
5270  break;
5271  case LCS_FORKEYSHARE:
5272  appendContextKeyword(context, " FOR KEY SHARE",
5274  break;
5275  case LCS_FORSHARE:
5276  appendContextKeyword(context, " FOR SHARE",
5278  break;
5279  case LCS_FORNOKEYUPDATE:
5280  appendContextKeyword(context, " FOR NO KEY UPDATE",
5282  break;
5283  case LCS_FORUPDATE:
5284  appendContextKeyword(context, " FOR UPDATE",
5286  break;
5287  }
5288 
5289  appendStringInfo(buf, " OF %s",
5291  context)));
5292  if (rc->waitPolicy == LockWaitError)
5293  appendStringInfoString(buf, " NOWAIT");
5294  else if (rc->waitPolicy == LockWaitSkip)
5295  appendStringInfoString(buf, " SKIP LOCKED");
5296  }
5297  }
5298 
5299  context->windowClause = save_windowclause;
5300  context->windowTList = save_windowtlist;
5301 }
5302 
5303 /*
5304  * Detect whether query looks like SELECT ... FROM VALUES(),
5305  * with no need to rename the output columns of the VALUES RTE.
5306  * If so, return the VALUES RTE. Otherwise return NULL.
5307  */
5308 static RangeTblEntry *
5310 {
5311  RangeTblEntry *result = NULL;
5312  ListCell *lc;
5313 
5314  /*
5315  * We want to detect a match even if the Query also contains OLD or NEW
5316  * rule RTEs. So the idea is to scan the rtable and see if there is only
5317  * one inFromCl RTE that is a VALUES RTE.
5318  */
5319  foreach(lc, query->rtable)
5320  {
5321  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
5322 
5323  if (rte->rtekind == RTE_VALUES && rte->inFromCl)
5324  {
5325  if (result)
5326  return NULL; /* multiple VALUES (probably not possible) */
5327  result = rte;
5328  }
5329  else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
5330  continue; /* ignore rule entries */
5331  else
5332  return NULL; /* something else -> not simple VALUES */
5333  }
5334 
5335  /*
5336  * We don't need to check the targetlist in any great detail, because
5337  * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
5338  * appear inside auto-generated sub-queries with very restricted
5339  * structure. However, DefineView might have modified the tlist by
5340  * injecting new column aliases, or we might have some other column
5341  * aliases forced by a resultDesc. We can only simplify if the RTE's
5342  * column names match the names that get_target_list() would select.
5343  */
5344  if (result)
5345  {
5346  ListCell *lcn;
5347  int colno;
5348 
5349  if (list_length(query->targetList) != list_length(result->eref->colnames))
5350  return NULL; /* this probably cannot happen */
5351  colno = 0;
5352  forboth(lc, query->targetList, lcn, result->eref->colnames)
5353  {
5354  TargetEntry *tle = (TargetEntry *) lfirst(lc);
5355  char *cname = strVal(lfirst(lcn));
5356  char *colname;
5357 
5358  if (tle->resjunk)
5359  return NULL; /* this probably cannot happen */
5360 
5361  /* compute name that get_target_list would use for column */
5362  colno++;
5363  if (resultDesc && colno <= resultDesc->natts)
5364  colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5365  else
5366  colname = tle->resname;
5367 
5368  /* does it match the VALUES RTE? */
5369  if (colname == NULL || strcmp(colname, cname) != 0)
5370  return NULL; /* column name has been changed */
5371  }
5372  }
5373 
5374  return result;
5375 }
5376 
5377 static void
5379  TupleDesc resultDesc)
5380 {
5381  StringInfo buf = context->buf;
5382  RangeTblEntry *values_rte;
5383  char *sep;
5384  ListCell *l;
5385 
5386  if (PRETTY_INDENT(context))
5387  {
5388  context->indentLevel += PRETTYINDENT_STD;
5389  appendStringInfoChar(buf, ' ');
5390  }
5391 
5392  /*
5393  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5394  * VALUES part. This reverses what transformValuesClause() did at parse
5395  * time.
5396  */
5397  values_rte = get_simple_values_rte(query, resultDesc);
5398  if (values_rte)
5399  {
5400  get_values_def(values_rte->values_lists, context);
5401  return;
5402  }
5403 
5404  /*
5405  * Build up the query string - first we say SELECT
5406  */
5407  appendStringInfoString(buf, "SELECT");
5408 
5409  /* Add the DISTINCT clause if given */
5410  if (query->distinctClause != NIL)
5411  {
5412  if (query->hasDistinctOn)
5413  {
5414  appendStringInfoString(buf, " DISTINCT ON (");
5415  sep = "";
5416  foreach(l, query->distinctClause)
5417  {
5418  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5419 
5420  appendStringInfoString(buf, sep);
5422  false, context);
5423  sep = ", ";
5424  }
5425  appendStringInfoChar(buf, ')');
5426  }
5427  else
5428  appendStringInfoString(buf, " DISTINCT");
5429  }
5430 
5431  /* Then we tell what to select (the targetlist) */
5432  get_target_list(query->targetList, context, resultDesc);
5433 
5434  /* Add the FROM clause if needed */
5435  get_from_clause(query, " FROM ", context);
5436 
5437  /* Add the WHERE clause if given */
5438  if (query->jointree->quals != NULL)
5439  {
5440  appendContextKeyword(context, " WHERE ",
5442  get_rule_expr(query->jointree->quals, context, false);
5443  }
5444 
5445  /* Add the GROUP BY clause if given */
5446  if (query->groupClause != NULL || query->groupingSets != NULL)
5447  {
5448  ParseExprKind save_exprkind;
5449 
5450  appendContextKeyword(context, " GROUP BY ",
5452 
5453  save_exprkind = context->special_exprkind;
5455 
5456  if (query->groupingSets == NIL)
5457  {
5458  sep = "";
5459  foreach(l, query->groupClause)
5460  {
5461  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5462 
5463  appendStringInfoString(buf, sep);
5465  false, context);
5466  sep = ", ";
5467  }
5468  }
5469  else
5470  {
5471  sep = "";
5472  foreach(l, query->groupingSets)
5473  {
5474  GroupingSet *grp = lfirst(l);
5475 
5476  appendStringInfoString(buf, sep);
5477  get_rule_groupingset(grp, query->targetList, true, context);
5478  sep = ", ";
5479  }
5480  }
5481 
5482  context->special_exprkind = save_exprkind;
5483  }
5484 
5485  /* Add the HAVING clause if given */
5486  if (query->havingQual != NULL)
5487  {
5488  appendContextKeyword(context, " HAVING ",
5490  get_rule_expr(query->havingQual, context, false);
5491  }
5492 
5493  /* Add the WINDOW clause if needed */
5494  if (query->windowClause != NIL)
5495  get_rule_windowclause(query, context);
5496 }
5497 
5498 /* ----------
5499  * get_target_list - Parse back a SELECT target list
5500  *
5501  * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
5502  * ----------
5503  */
5504 static void
5505 get_target_list(List *targetList, deparse_context *context,
5506  TupleDesc resultDesc)
5507 {
5508  StringInfo buf = context->buf;
5509  StringInfoData targetbuf;
5510  bool last_was_multiline = false;
5511  char *sep;
5512  int colno;
5513  ListCell *l;
5514 
5515  /* we use targetbuf to hold each TLE's text temporarily */
5516  initStringInfo(&targetbuf);
5517 
5518  sep = " ";
5519  colno = 0;
5520  foreach(l, targetList)
5521  {
5522  TargetEntry *tle = (TargetEntry *) lfirst(l);
5523  char *colname;
5524  char *attname;
5525 
5526  if (tle->resjunk)
5527  continue; /* ignore junk entries */
5528 
5529  appendStringInfoString(buf, sep);
5530  sep = ", ";
5531  colno++;
5532 
5533  /*
5534  * Put the new field text into targetbuf so we can decide after we've
5535  * got it whether or not it needs to go on a new line.
5536  */
5537  resetStringInfo(&targetbuf);
5538  context->buf = &targetbuf;
5539 
5540  /*
5541  * We special-case Var nodes rather than using get_rule_expr. This is
5542  * needed because get_rule_expr will display a whole-row Var as
5543  * "foo.*", which is the preferred notation in most contexts, but at
5544  * the top level of a SELECT list it's not right (the parser will
5545  * expand that notation into multiple columns, yielding behavior
5546  * different from a whole-row Var). We need to call get_variable
5547  * directly so that we can tell it to do the right thing, and so that
5548  * we can get the attribute name which is the default AS label.
5549  */
5550  if (tle->expr && (IsA(tle->expr, Var)))
5551  {
5552  attname = get_variable((Var *) tle->expr, 0, true, context);
5553  }
5554  else
5555  {
5556  get_rule_expr((Node *) tle->expr, context, true);
5557  /* We'll show the AS name unless it's this: */
5558  attname = "?column?";
5559  }
5560 
5561  /*
5562  * Figure out what the result column should be called. In the context
5563  * of a view, use the view's tuple descriptor (so as to pick up the
5564  * effects of any column RENAME that's been done on the view).
5565  * Otherwise, just use what we can find in the TLE.
5566  */
5567  if (resultDesc && colno <= resultDesc->natts)
5568  colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5569  else
5570  colname = tle->resname;
5571 
5572  /* Show AS unless the column's name is correct as-is */
5573  if (colname) /* resname could be NULL */
5574  {
5575  if (attname == NULL || strcmp(attname, colname) != 0)
5576  appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
5577  }
5578 
5579  /* Restore context's output buffer */
5580  context->buf = buf;
5581 
5582  /* Consider line-wrapping if enabled */
5583  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
5584  {
5585  int leading_nl_pos;
5586 
5587  /* Does the new field start with a new line? */
5588  if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
5589  leading_nl_pos = 0;
5590  else
5591  leading_nl_pos = -1;
5592 
5593  /* If so, we shouldn't add anything */
5594  if (leading_nl_pos >= 0)
5595  {
5596  /* instead, remove any trailing spaces currently in buf */
5598  }
5599  else
5600  {
5601  char *trailing_nl;
5602 
5603  /* Locate the start of the current line in the output buffer */
5604  trailing_nl = strrchr(buf->data, '\n');
5605  if (trailing_nl == NULL)
5606  trailing_nl = buf->data;
5607  else
5608  trailing_nl++;
5609 
5610  /*
5611  * Add a newline, plus some indentation, if the new field is
5612  * not the first and either the new field would cause an
5613  * overflow or the last field used more than one line.
5614  */
5615  if (colno > 1 &&
5616  ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
5617  last_was_multiline))
5618  appendContextKeyword(context, "", -PRETTYINDENT_STD,
5620  }
5621 
5622  /* Remember this field's multiline status for next iteration */
5623  last_was_multiline =
5624  (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
5625  }
5626 
5627  /* Add the new field */
5628  appendBinaryStringInfo(buf, targetbuf.data, targetbuf.len);
5629  }
5630 
5631  /* clean up */
5632  pfree(targetbuf.data);
5633 }
5634 
5635 static void
5636 get_setop_query(Node *setOp, Query *query, deparse_context *context,
5637  TupleDesc resultDesc)
5638 {
5639  StringInfo buf = context->buf;
5640  bool need_paren;
5641 
5642  /* Guard against excessively long or deeply-nested queries */
5645 
5646  if (IsA(setOp, RangeTblRef))
5647  {
5648  RangeTblRef *rtr = (RangeTblRef *) setOp;
5649  RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
5650  Query *subquery = rte->subquery;
5651 
5652  Assert(subquery != NULL);
5653  Assert(subquery->setOperations == NULL);
5654  /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
5655  need_paren = (subquery->cteList ||
5656  subquery->sortClause ||
5657  subquery->rowMarks ||
5658  subquery->limitOffset ||
5659  subquery->limitCount);
5660  if (need_paren)
5661  appendStringInfoChar(buf, '(');
5662  get_query_def(subquery, buf, context->namespaces, resultDesc,
5663  context->prettyFlags, context->wrapColumn,
5664  context->indentLevel);
5665  if (need_paren)
5666  appendStringInfoChar(buf, ')');
5667  }
5668  else if (IsA(setOp, SetOperationStmt))
5669  {
5670  SetOperationStmt *op = (SetOperationStmt *) setOp;
5671  int subindent;
5672 
5673  /*
5674  * We force parens when nesting two SetOperationStmts, except when the
5675  * lefthand input is another setop of the same kind. Syntactically,
5676  * we could omit parens in rather more cases, but it seems best to use
5677  * parens to flag cases where the setop operator changes. If we use
5678  * parens, we also increase the indentation level for the child query.
5679  *
5680  * There are some cases in which parens are needed around a leaf query
5681  * too, but those are more easily handled at the next level down (see
5682  * code above).
5683  */
5684  if (IsA(op->larg, SetOperationStmt))
5685  {
5686  SetOperationStmt *lop = (SetOperationStmt *) op->larg;
5687 
5688  if (op->op == lop->op && op->all == lop->all)
5689  need_paren = false;
5690  else
5691  need_paren = true;
5692  }
5693  else
5694  need_paren = false;
5695 
5696  if (need_paren)
5697  {
5698  appendStringInfoChar(buf, '(');
5699  subindent = PRETTYINDENT_STD;
5700  appendContextKeyword(context, "", subindent, 0, 0);
5701  }
5702  else
5703  subindent = 0;
5704 
5705  get_setop_query(op->larg, query, context, resultDesc);
5706 
5707  if (need_paren)
5708  appendContextKeyword(context, ") ", -subindent, 0, 0);
5709  else if (PRETTY_INDENT(context))
5710  appendContextKeyword(context, "", -subindent, 0, 0);
5711  else
5712  appendStringInfoChar(buf, ' ');
5713 
5714  switch (op->op)
5715  {
5716  case SETOP_UNION:
5717  appendStringInfoString(buf, "UNION ");
5718  break;
5719  case SETOP_INTERSECT:
5720  appendStringInfoString(buf, "INTERSECT ");
5721  break;
5722  case SETOP_EXCEPT:
5723  appendStringInfoString(buf, "EXCEPT ");
5724  break;
5725  default:
5726  elog(ERROR, "unrecognized set op: %d",
5727  (int) op->op);
5728  }
5729  if (op->all)
5730  appendStringInfoString(buf, "ALL ");
5731 
5732  /* Always parenthesize if RHS is another setop */
5733  need_paren = IsA(op->rarg, SetOperationStmt);
5734 
5735  /*
5736  * The indentation code here is deliberately a bit different from that
5737  * for the lefthand input, because we want the line breaks in
5738  * different places.
5739  */
5740  if (need_paren)
5741  {
5742  appendStringInfoChar(buf, '(');
5743  subindent = PRETTYINDENT_STD;
5744  }
5745  else
5746  subindent = 0;