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