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