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