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