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-2023, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/utils/adt/ruleutils.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 
22 #include "access/amapi.h"
23 #include "access/htup_details.h"
24 #include "access/relation.h"
25 #include "access/sysattr.h"
26 #include "access/table.h"
27 #include "catalog/pg_aggregate.h"
28 #include "catalog/pg_am.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_collation.h"
31 #include "catalog/pg_constraint.h"
32 #include "catalog/pg_depend.h"
33 #include "catalog/pg_language.h"
34 #include "catalog/pg_opclass.h"
35 #include "catalog/pg_operator.h"
37 #include "catalog/pg_proc.h"
39 #include "catalog/pg_trigger.h"
40 #include "catalog/pg_type.h"
41 #include "commands/defrem.h"
42 #include "commands/tablespace.h"
43 #include "common/keywords.h"
44 #include "executor/spi.h"
45 #include "funcapi.h"
46 #include "mb/pg_wchar.h"
47 #include "miscadmin.h"
48 #include "nodes/makefuncs.h"
49 #include "nodes/nodeFuncs.h"
50 #include "nodes/pathnodes.h"
51 #include "optimizer/optimizer.h"
52 #include "parser/parse_agg.h"
53 #include "parser/parse_func.h"
54 #include "parser/parse_node.h"
55 #include "parser/parse_oper.h"
56 #include "parser/parse_relation.h"
57 #include "parser/parser.h"
58 #include "parser/parsetree.h"
59 #include "rewrite/rewriteHandler.h"
60 #include "rewrite/rewriteManip.h"
61 #include "rewrite/rewriteSupport.h"
62 #include "utils/array.h"
63 #include "utils/builtins.h"
64 #include "utils/fmgroids.h"
65 #include "utils/guc.h"
66 #include "utils/hsearch.h"
67 #include "utils/lsyscache.h"
68 #include "utils/partcache.h"
69 #include "utils/rel.h"
70 #include "utils/ruleutils.h"
71 #include "utils/snapmgr.h"
72 #include "utils/syscache.h"
73 #include "utils/typcache.h"
74 #include "utils/varlena.h"
75 #include "utils/xml.h"
76 
77 /* ----------
78  * Pretty formatting constants
79  * ----------
80  */
81 
82 /* Indent counts */
83 #define PRETTYINDENT_STD 8
84 #define PRETTYINDENT_JOIN 4
85 #define PRETTYINDENT_VAR 4
86 
87 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
88 
89 /* Pretty flags */
90 #define PRETTYFLAG_PAREN 0x0001
91 #define PRETTYFLAG_INDENT 0x0002
92 #define PRETTYFLAG_SCHEMA 0x0004
93 
94 /* Standard conversion of a "bool pretty" option to detailed flags */
95 #define GET_PRETTY_FLAGS(pretty) \
96  ((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
97  : PRETTYFLAG_INDENT)
98 
99 /* Default line length for pretty-print wrapping: 0 means wrap always */
100 #define WRAP_COLUMN_DEFAULT 0
101 
102 /* macros to test if pretty action needed */
103 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
104 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
105 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
106 
107 
108 /* ----------
109  * Local data types
110  * ----------
111  */
112 
113 /* Context info needed for invoking a recursive querytree display routine */
114 typedef struct
115 {
116  StringInfo buf; /* output buffer to append to */
117  List *namespaces; /* List of deparse_namespace nodes */
118  List *windowClause; /* Current query level's WINDOW clause */
119  List *windowTList; /* targetlist for resolving WINDOW clause */
120  int prettyFlags; /* enabling of pretty-print functions */
121  int wrapColumn; /* max line length, or -1 for no limit */
122  int indentLevel; /* current indent level for pretty-print */
123  bool varprefix; /* true to print prefixes on Vars */
124  ParseExprKind special_exprkind; /* set only for exprkinds needing special
125  * handling */
126  Bitmapset *appendparents; /* if not null, map child Vars of these relids
127  * back to the parent rel */
129 
130 /*
131  * Each level of query context around a subtree needs a level of Var namespace.
132  * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
133  * the current context's namespaces list.
134  *
135  * rtable is the list of actual RTEs from the Query or PlannedStmt.
136  * rtable_names holds the alias name to be used for each RTE (either a C
137  * string, or NULL for nameless RTEs such as unnamed joins).
138  * rtable_columns holds the column alias names to be used for each RTE.
139  *
140  * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
141  * in the PlannedStmt case).
142  * ctes is a list of CommonTableExpr nodes (only used in the Query case).
143  * appendrels, if not null (it's only used in the PlannedStmt case), is an
144  * array of AppendRelInfo nodes, indexed by child relid. We use that to map
145  * child-table Vars to their inheritance parents.
146  *
147  * In some cases we need to make names of merged JOIN USING columns unique
148  * across the whole query, not only per-RTE. If so, unique_using is true
149  * and using_names is a list of C strings representing names already assigned
150  * to USING columns.
151  *
152  * When deparsing plan trees, there is always just a single item in the
153  * deparse_namespace list (since a plan tree never contains Vars with
154  * varlevelsup > 0). We store the Plan node that is the immediate
155  * parent of the expression to be deparsed, as well as a list of that
156  * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
157  * as well as their targetlists, and the index tlist if the current plan node
158  * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
159  * from the current Plan node, but it seems notationally clearer to set them
160  * up as separate fields.)
161  */
162 typedef struct
163 {
164  List *rtable; /* List of RangeTblEntry nodes */
165  List *rtable_names; /* Parallel list of names for RTEs */
166  List *rtable_columns; /* Parallel list of deparse_columns structs */
167  List *subplans; /* List of Plan trees for SubPlans */
168  List *ctes; /* List of CommonTableExpr nodes */
169  AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
170  /* Workspace for column alias assignment: */
171  bool unique_using; /* Are we making USING names globally unique */
172  List *using_names; /* List of assigned names for USING columns */
173  /* Remaining fields are used only when deparsing a Plan tree: */
174  Plan *plan; /* immediate parent of current expression */
175  List *ancestors; /* ancestors of plan */
176  Plan *outer_plan; /* outer subnode, or NULL if none */
177  Plan *inner_plan; /* inner subnode, or NULL if none */
178  List *outer_tlist; /* referent for OUTER_VAR Vars */
179  List *inner_tlist; /* referent for INNER_VAR Vars */
180  List *index_tlist; /* referent for INDEX_VAR Vars */
181  /* Special namespace representing a function signature: */
182  char *funcname;
183  int numargs;
184  char **argnames;
186 
187 /*
188  * Per-relation data about column alias names.
189  *
190  * Selecting aliases is unreasonably complicated because of the need to dump
191  * rules/views whose underlying tables may have had columns added, deleted, or
192  * renamed since the query was parsed. We must nonetheless print the rule/view
193  * in a form that can be reloaded and will produce the same results as before.
194  *
195  * For each RTE used in the query, we must assign column aliases that are
196  * unique within that RTE. SQL does not require this of the original query,
197  * but due to factors such as *-expansion we need to be able to uniquely
198  * reference every column in a decompiled query. As long as we qualify all
199  * column references, per-RTE uniqueness is sufficient for that.
200  *
201  * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
202  * since they just inherit column names from their input RTEs, and we can't
203  * rename the columns at the join level. Most of the time this isn't an issue
204  * because we don't need to reference the join's output columns as such; we
205  * can reference the input columns instead. That approach can fail for merged
206  * JOIN USING columns, however, so when we have one of those in an unnamed
207  * join, we have to make that column's alias globally unique across the whole
208  * query to ensure it can be referenced unambiguously.
209  *
210  * Another problem is that a JOIN USING clause requires the columns to be
211  * merged to have the same aliases in both input RTEs, and that no other
212  * columns in those RTEs or their children conflict with the USING names.
213  * To handle that, we do USING-column alias assignment in a recursive
214  * traversal of the query's jointree. When descending through a JOIN with
215  * USING, we preassign the USING column names to the child columns, overriding
216  * other rules for column alias assignment. We also mark each RTE with a list
217  * of all USING column names selected for joins containing that RTE, so that
218  * when we assign other columns' aliases later, we can avoid conflicts.
219  *
220  * Another problem is that if a JOIN's input tables have had columns added or
221  * deleted since the query was parsed, we must generate a column alias list
222  * for the join that matches the current set of input columns --- otherwise, a
223  * change in the number of columns in the left input would throw off matching
224  * of aliases to columns of the right input. Thus, positions in the printable
225  * column alias list are not necessarily one-for-one with varattnos of the
226  * JOIN, so we need a separate new_colnames[] array for printing purposes.
227  */
228 typedef struct
229 {
230  /*
231  * colnames is an array containing column aliases to use for columns that
232  * existed when the query was parsed. Dropped columns have NULL entries.
233  * This array can be directly indexed by varattno to get a Var's name.
234  *
235  * Non-NULL entries are guaranteed unique within the RTE, *except* when
236  * this is for an unnamed JOIN RTE. In that case we merely copy up names
237  * from the two input RTEs.
238  *
239  * During the recursive descent in set_using_names(), forcible assignment
240  * of a child RTE's column name is represented by pre-setting that element
241  * of the child's colnames array. So at that stage, NULL entries in this
242  * array just mean that no name has been preassigned, not necessarily that
243  * the column is dropped.
244  */
245  int num_cols; /* length of colnames[] array */
246  char **colnames; /* array of C strings and NULLs */
247 
248  /*
249  * new_colnames is an array containing column aliases to use for columns
250  * that would exist if the query was re-parsed against the current
251  * definitions of its base tables. This is what to print as the column
252  * alias list for the RTE. This array does not include dropped columns,
253  * but it will include columns added since original parsing. Indexes in
254  * it therefore have little to do with current varattno values. As above,
255  * entries are unique unless this is for an unnamed JOIN RTE. (In such an
256  * RTE, we never actually print this array, but we must compute it anyway
257  * for possible use in computing column names of upper joins.) The
258  * parallel array is_new_col marks which of these columns are new since
259  * original parsing. Entries with is_new_col false must match the
260  * non-NULL colnames entries one-for-one.
261  */
262  int num_new_cols; /* length of new_colnames[] array */
263  char **new_colnames; /* array of C strings */
264  bool *is_new_col; /* array of bool flags */
265 
266  /* This flag tells whether we should actually print a column alias list */
268 
269  /* This list has all names used as USING names in joins above this RTE */
270  List *parentUsing; /* names assigned to parent merged columns */
271 
272  /*
273  * If this struct is for a JOIN RTE, we fill these fields during the
274  * set_using_names() pass to describe its relationship to its child RTEs.
275  *
276  * leftattnos and rightattnos are arrays with one entry per existing
277  * output column of the join (hence, indexable by join varattno). For a
278  * simple reference to a column of the left child, leftattnos[i] is the
279  * child RTE's attno and rightattnos[i] is zero; and conversely for a
280  * column of the right child. But for merged columns produced by JOIN
281  * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
282  * Note that a simple reference might be to a child RTE column that's been
283  * dropped; but that's OK since the column could not be used in the query.
284  *
285  * If it's a JOIN USING, usingNames holds the alias names selected for the
286  * merged columns (these might be different from the original USING list,
287  * if we had to modify names to achieve uniqueness).
288  */
289  int leftrti; /* rangetable index of left child */
290  int rightrti; /* rangetable index of right child */
291  int *leftattnos; /* left-child varattnos of join cols, or 0 */
292  int *rightattnos; /* right-child varattnos of join cols, or 0 */
293  List *usingNames; /* names assigned to merged columns */
295 
296 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
297 #define deparse_columns_fetch(rangetable_index, dpns) \
298  ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
299 
300 /*
301  * Entry in set_rtable_names' hash table
302  */
303 typedef struct
304 {
305  char name[NAMEDATALEN]; /* Hash key --- must be first */
306  int counter; /* Largest addition used so far for name */
307 } NameHashEntry;
308 
309 /* Callback signature for resolve_special_varno() */
310 typedef void (*rsv_callback) (Node *node, deparse_context *context,
311  void *callback_arg);
312 
313 
314 /* ----------
315  * Global data
316  * ----------
317  */
319 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
321 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
322 
323 /* GUC parameters */
325 
326 
327 /* ----------
328  * Local functions
329  *
330  * Most of these functions used to use fixed-size buffers to build their
331  * results. Now, they take an (already initialized) StringInfo object
332  * as a parameter, and append their text output to its contents.
333  * ----------
334  */
335 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
336  bool forceprefix, bool showimplicit,
337  int prettyFlags, int startIndent);
338 static char *pg_get_viewdef_worker(Oid viewoid,
339  int prettyFlags, int wrapColumn);
340 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
341 static int decompile_column_index_array(Datum column_index_array, Oid relId,
342  StringInfo buf);
343 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
344 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
345  const Oid *excludeOps,
346  bool attrsOnly, bool keysOnly,
347  bool showTblSpc, bool inherits,
348  int prettyFlags, bool missing_ok);
349 static char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
350  bool missing_ok);
351 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
352  bool attrsOnly, bool missing_ok);
353 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
354  int prettyFlags, bool missing_ok);
355 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
356  int prettyFlags);
358  bool print_table_args, bool print_defaults);
359 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
360 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
361 static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
362 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
363  Bitmapset *rels_used);
364 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
365  List *parent_namespaces);
366 static void set_simple_column_names(deparse_namespace *dpns);
367 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
368 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
369  List *parentUsing);
371  RangeTblEntry *rte,
372  deparse_columns *colinfo);
374  deparse_columns *colinfo);
375 static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
376  deparse_columns *colinfo);
377 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
378  deparse_columns *colinfo);
379 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
380 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
381  deparse_columns *colinfo);
382 static char *get_rtable_name(int rtindex, deparse_context *context);
383 static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
385  WorkTableScan *wtscan);
386 static void push_child_plan(deparse_namespace *dpns, Plan *plan,
387  deparse_namespace *save_dpns);
388 static void pop_child_plan(deparse_namespace *dpns,
389  deparse_namespace *save_dpns);
390 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
391  deparse_namespace *save_dpns);
392 static void pop_ancestor_plan(deparse_namespace *dpns,
393  deparse_namespace *save_dpns);
394 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
395  int prettyFlags);
396 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
397  int prettyFlags, int wrapColumn);
398 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
399  TupleDesc resultDesc, bool colNamesVisible,
400  int prettyFlags, int wrapColumn, int startIndent);
401 static void get_values_def(List *values_lists, deparse_context *context);
402 static void get_with_clause(Query *query, deparse_context *context);
403 static void get_select_query_def(Query *query, deparse_context *context,
404  TupleDesc resultDesc, bool colNamesVisible);
405 static void get_insert_query_def(Query *query, deparse_context *context,
406  bool colNamesVisible);
407 static void get_update_query_def(Query *query, deparse_context *context,
408  bool colNamesVisible);
409 static void get_update_query_targetlist_def(Query *query, List *targetList,
410  deparse_context *context,
411  RangeTblEntry *rte);
412 static void get_delete_query_def(Query *query, deparse_context *context,
413  bool colNamesVisible);
414 static void get_utility_query_def(Query *query, deparse_context *context);
415 static void get_basic_select_query(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,
420  deparse_context *context,
421  TupleDesc resultDesc, bool colNamesVisible);
422 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
423  bool force_colno,
424  deparse_context *context);
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,
431  deparse_context *context);
432 static char *get_variable(Var *var, int levelsup, bool istoplevel,
433  deparse_context *context);
434 static void get_special_variable(Node *node, deparse_context *context,
435  void *callback_arg);
436 static void resolve_special_varno(Node *node, deparse_context *context,
437  rsv_callback callback, void *callback_arg);
438 static Node *find_param_referent(Param *param, deparse_context *context,
439  deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
440 static void get_parameter(Param *param, deparse_context *context);
441 static const char *get_simple_binary_op_name(OpExpr *expr);
442 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
443 static void appendContextKeyword(deparse_context *context, const char *str,
444  int indentBefore, int indentAfter, int indentPlus);
446 static void get_rule_expr(Node *node, deparse_context *context,
447  bool showimplicit);
448 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
449  bool showimplicit);
450 static void get_rule_list_toplevel(List *lst, deparse_context *context,
451  bool showimplicit);
452 static void get_rule_expr_funccall(Node *node, deparse_context *context,
453  bool showimplicit);
454 static bool looks_like_function(Node *node);
455 static void get_oper_expr(OpExpr *expr, deparse_context *context);
456 static void get_func_expr(FuncExpr *expr, deparse_context *context,
457  bool showimplicit);
458 static void get_agg_expr(Aggref *aggref, deparse_context *context,
459  Aggref *original_aggref);
460 static void get_agg_combine_expr(Node *node, deparse_context *context,
461  void *callback_arg);
462 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
463 static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
464 static void get_coercion_expr(Node *arg, deparse_context *context,
465  Oid resulttype, int32 resulttypmod,
466  Node *parentNode);
467 static void get_const_expr(Const *constval, deparse_context *context,
468  int showtype);
469 static void get_const_collation(Const *constval, deparse_context *context);
470 static void simple_quote_literal(StringInfo buf, const char *val);
471 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
472 static void get_tablefunc(TableFunc *tf, deparse_context *context,
473  bool showimplicit);
474 static void get_from_clause(Query *query, const char *prefix,
475  deparse_context *context);
476 static void get_from_clause_item(Node *jtnode, Query *query,
477  deparse_context *context);
478 static void get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
479  deparse_context *context);
480 static void get_column_alias_list(deparse_columns *colinfo,
481  deparse_context *context);
482 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
483  deparse_columns *colinfo,
484  deparse_context *context);
485 static void get_tablesample_def(TableSampleClause *tablesample,
486  deparse_context *context);
487 static void get_opclass_name(Oid opclass, Oid actual_datatype,
488  StringInfo buf);
489 static Node *processIndirection(Node *node, deparse_context *context);
490 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
491 static char *get_relation_name(Oid relid);
492 static char *generate_relation_name(Oid relid, List *namespaces);
493 static char *generate_qualified_relation_name(Oid relid);
494 static char *generate_function_name(Oid funcid, int nargs,
495  List *argnames, Oid *argtypes,
496  bool has_variadic, bool *use_variadic_p,
497  ParseExprKind special_exprkind);
498 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
499 static void add_cast_to(StringInfo buf, Oid typid);
500 static char *generate_qualified_type_name(Oid typid);
501 static text *string_to_text(char *str);
502 static char *flatten_reloptions(Oid relid);
503 static void get_reloptions(StringInfo buf, Datum reloptions);
504 
505 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
506 
507 
508 /* ----------
509  * pg_get_ruledef - Do it all and return a text
510  * that could be used as a statement
511  * to recreate the rule
512  * ----------
513  */
514 Datum
516 {
517  Oid ruleoid = PG_GETARG_OID(0);
518  int prettyFlags;
519  char *res;
520 
521  prettyFlags = PRETTYFLAG_INDENT;
522 
523  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
524 
525  if (res == NULL)
526  PG_RETURN_NULL();
527 
529 }
530 
531 
532 Datum
534 {
535  Oid ruleoid = PG_GETARG_OID(0);
536  bool pretty = PG_GETARG_BOOL(1);
537  int prettyFlags;
538  char *res;
539 
540  prettyFlags = GET_PRETTY_FLAGS(pretty);
541 
542  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
543 
544  if (res == NULL)
545  PG_RETURN_NULL();
546 
548 }
549 
550 
551 static char *
552 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
553 {
554  Datum args[1];
555  char nulls[1];
556  int spirc;
557  HeapTuple ruletup;
558  TupleDesc rulettc;
560 
561  /*
562  * Do this first so that string is alloc'd in outer context not SPI's.
563  */
565 
566  /*
567  * Connect to SPI manager
568  */
569  if (SPI_connect() != SPI_OK_CONNECT)
570  elog(ERROR, "SPI_connect failed");
571 
572  /*
573  * On the first call prepare the plan to lookup pg_rewrite. We read
574  * pg_rewrite over the SPI manager instead of using the syscache to be
575  * checked for read access on pg_rewrite.
576  */
577  if (plan_getrulebyoid == NULL)
578  {
579  Oid argtypes[1];
580  SPIPlanPtr plan;
581 
582  argtypes[0] = OIDOID;
583  plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
584  if (plan == NULL)
585  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
586  SPI_keepplan(plan);
587  plan_getrulebyoid = plan;
588  }
589 
590  /*
591  * Get the pg_rewrite tuple for this rule
592  */
593  args[0] = ObjectIdGetDatum(ruleoid);
594  nulls[0] = ' ';
595  spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
596  if (spirc != SPI_OK_SELECT)
597  elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
598  if (SPI_processed != 1)
599  {
600  /*
601  * There is no tuple data available here, just keep the output buffer
602  * empty.
603  */
604  }
605  else
606  {
607  /*
608  * Get the rule's definition and put it into executor's memory
609  */
610  ruletup = SPI_tuptable->vals[0];
611  rulettc = SPI_tuptable->tupdesc;
612  make_ruledef(&buf, ruletup, rulettc, prettyFlags);
613  }
614 
615  /*
616  * Disconnect from SPI manager
617  */
618  if (SPI_finish() != SPI_OK_FINISH)
619  elog(ERROR, "SPI_finish failed");
620 
621  if (buf.len == 0)
622  return NULL;
623 
624  return buf.data;
625 }
626 
627 
628 /* ----------
629  * pg_get_viewdef - Mainly the same thing, but we
630  * only return the SELECT part of a view
631  * ----------
632  */
633 Datum
635 {
636  /* By OID */
637  Oid viewoid = PG_GETARG_OID(0);
638  int prettyFlags;
639  char *res;
640 
641  prettyFlags = PRETTYFLAG_INDENT;
642 
643  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
644 
645  if (res == NULL)
646  PG_RETURN_NULL();
647 
649 }
650 
651 
652 Datum
654 {
655  /* By OID */
656  Oid viewoid = PG_GETARG_OID(0);
657  bool pretty = PG_GETARG_BOOL(1);
658  int prettyFlags;
659  char *res;
660 
661  prettyFlags = GET_PRETTY_FLAGS(pretty);
662 
663  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
664 
665  if (res == NULL)
666  PG_RETURN_NULL();
667 
669 }
670 
671 Datum
673 {
674  /* By OID */
675  Oid viewoid = PG_GETARG_OID(0);
676  int wrap = PG_GETARG_INT32(1);
677  int prettyFlags;
678  char *res;
679 
680  /* calling this implies we want pretty printing */
681  prettyFlags = GET_PRETTY_FLAGS(true);
682 
683  res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
684 
685  if (res == NULL)
686  PG_RETURN_NULL();
687 
689 }
690 
691 Datum
693 {
694  /* By qualified name */
695  text *viewname = PG_GETARG_TEXT_PP(0);
696  int prettyFlags;
697  RangeVar *viewrel;
698  Oid viewoid;
699  char *res;
700 
701  prettyFlags = PRETTYFLAG_INDENT;
702 
703  /* Look up view name. Can't lock it - we might not have privileges. */
705  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
706 
707  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
708 
709  if (res == NULL)
710  PG_RETURN_NULL();
711 
713 }
714 
715 
716 Datum
718 {
719  /* By qualified name */
720  text *viewname = PG_GETARG_TEXT_PP(0);
721  bool pretty = PG_GETARG_BOOL(1);
722  int prettyFlags;
723  RangeVar *viewrel;
724  Oid viewoid;
725  char *res;
726 
727  prettyFlags = GET_PRETTY_FLAGS(pretty);
728 
729  /* Look up view name. Can't lock it - we might not have privileges. */
731  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
732 
733  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
734 
735  if (res == NULL)
736  PG_RETURN_NULL();
737 
739 }
740 
741 /*
742  * Common code for by-OID and by-name variants of pg_get_viewdef
743  */
744 static char *
745 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
746 {
747  Datum args[2];
748  char nulls[2];
749  int spirc;
750  HeapTuple ruletup;
751  TupleDesc rulettc;
753 
754  /*
755  * Do this first so that string is alloc'd in outer context not SPI's.
756  */
758 
759  /*
760  * Connect to SPI manager
761  */
762  if (SPI_connect() != SPI_OK_CONNECT)
763  elog(ERROR, "SPI_connect failed");
764 
765  /*
766  * On the first call prepare the plan to lookup pg_rewrite. We read
767  * pg_rewrite over the SPI manager instead of using the syscache to be
768  * checked for read access on pg_rewrite.
769  */
770  if (plan_getviewrule == NULL)
771  {
772  Oid argtypes[2];
773  SPIPlanPtr plan;
774 
775  argtypes[0] = OIDOID;
776  argtypes[1] = NAMEOID;
777  plan = SPI_prepare(query_getviewrule, 2, argtypes);
778  if (plan == NULL)
779  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
780  SPI_keepplan(plan);
781  plan_getviewrule = plan;
782  }
783 
784  /*
785  * Get the pg_rewrite tuple for the view's SELECT rule
786  */
787  args[0] = ObjectIdGetDatum(viewoid);
789  nulls[0] = ' ';
790  nulls[1] = ' ';
791  spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
792  if (spirc != SPI_OK_SELECT)
793  elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
794  if (SPI_processed != 1)
795  {
796  /*
797  * There is no tuple data available here, just keep the output buffer
798  * empty.
799  */
800  }
801  else
802  {
803  /*
804  * Get the rule's definition and put it into executor's memory
805  */
806  ruletup = SPI_tuptable->vals[0];
807  rulettc = SPI_tuptable->tupdesc;
808  make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
809  }
810 
811  /*
812  * Disconnect from SPI manager
813  */
814  if (SPI_finish() != SPI_OK_FINISH)
815  elog(ERROR, "SPI_finish failed");
816 
817  if (buf.len == 0)
818  return NULL;
819 
820  return buf.data;
821 }
822 
823 /* ----------
824  * pg_get_triggerdef - Get the definition of a trigger
825  * ----------
826  */
827 Datum
829 {
830  Oid trigid = PG_GETARG_OID(0);
831  char *res;
832 
833  res = pg_get_triggerdef_worker(trigid, false);
834 
835  if (res == NULL)
836  PG_RETURN_NULL();
837 
839 }
840 
841 Datum
843 {
844  Oid trigid = PG_GETARG_OID(0);
845  bool pretty = PG_GETARG_BOOL(1);
846  char *res;
847 
848  res = pg_get_triggerdef_worker(trigid, pretty);
849 
850  if (res == NULL)
851  PG_RETURN_NULL();
852 
854 }
855 
856 static char *
857 pg_get_triggerdef_worker(Oid trigid, bool pretty)
858 {
859  HeapTuple ht_trig;
860  Form_pg_trigger trigrec;
862  Relation tgrel;
863  ScanKeyData skey[1];
864  SysScanDesc tgscan;
865  int findx = 0;
866  char *tgname;
867  char *tgoldtable;
868  char *tgnewtable;
869  Datum value;
870  bool isnull;
871 
872  /*
873  * Fetch the pg_trigger tuple by the Oid of the trigger
874  */
875  tgrel = table_open(TriggerRelationId, AccessShareLock);
876 
877  ScanKeyInit(&skey[0],
878  Anum_pg_trigger_oid,
879  BTEqualStrategyNumber, F_OIDEQ,
880  ObjectIdGetDatum(trigid));
881 
882  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
883  NULL, 1, skey);
884 
885  ht_trig = systable_getnext(tgscan);
886 
887  if (!HeapTupleIsValid(ht_trig))
888  {
889  systable_endscan(tgscan);
891  return NULL;
892  }
893 
894  trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
895 
896  /*
897  * Start the trigger definition. Note that the trigger's name should never
898  * be schema-qualified, but the trigger rel's name may be.
899  */
901 
902  tgname = NameStr(trigrec->tgname);
903  appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
904  OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
905  quote_identifier(tgname));
906 
907  if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
908  appendStringInfoString(&buf, "BEFORE");
909  else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
910  appendStringInfoString(&buf, "AFTER");
911  else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
912  appendStringInfoString(&buf, "INSTEAD OF");
913  else
914  elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
915 
916  if (TRIGGER_FOR_INSERT(trigrec->tgtype))
917  {
918  appendStringInfoString(&buf, " INSERT");
919  findx++;
920  }
921  if (TRIGGER_FOR_DELETE(trigrec->tgtype))
922  {
923  if (findx > 0)
924  appendStringInfoString(&buf, " OR DELETE");
925  else
926  appendStringInfoString(&buf, " DELETE");
927  findx++;
928  }
929  if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
930  {
931  if (findx > 0)
932  appendStringInfoString(&buf, " OR UPDATE");
933  else
934  appendStringInfoString(&buf, " UPDATE");
935  findx++;
936  /* tgattr is first var-width field, so OK to access directly */
937  if (trigrec->tgattr.dim1 > 0)
938  {
939  int i;
940 
941  appendStringInfoString(&buf, " OF ");
942  for (i = 0; i < trigrec->tgattr.dim1; i++)
943  {
944  char *attname;
945 
946  if (i > 0)
947  appendStringInfoString(&buf, ", ");
948  attname = get_attname(trigrec->tgrelid,
949  trigrec->tgattr.values[i], false);
951  }
952  }
953  }
954  if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
955  {
956  if (findx > 0)
957  appendStringInfoString(&buf, " OR TRUNCATE");
958  else
959  appendStringInfoString(&buf, " TRUNCATE");
960  findx++;
961  }
962 
963  /*
964  * In non-pretty mode, always schema-qualify the target table name for
965  * safety. In pretty mode, schema-qualify only if not visible.
966  */
967  appendStringInfo(&buf, " ON %s ",
968  pretty ?
969  generate_relation_name(trigrec->tgrelid, NIL) :
970  generate_qualified_relation_name(trigrec->tgrelid));
971 
972  if (OidIsValid(trigrec->tgconstraint))
973  {
974  if (OidIsValid(trigrec->tgconstrrelid))
975  appendStringInfo(&buf, "FROM %s ",
976  generate_relation_name(trigrec->tgconstrrelid, NIL));
977  if (!trigrec->tgdeferrable)
978  appendStringInfoString(&buf, "NOT ");
979  appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
980  if (trigrec->tginitdeferred)
981  appendStringInfoString(&buf, "DEFERRED ");
982  else
983  appendStringInfoString(&buf, "IMMEDIATE ");
984  }
985 
986  value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
987  tgrel->rd_att, &isnull);
988  if (!isnull)
989  tgoldtable = NameStr(*DatumGetName(value));
990  else
991  tgoldtable = NULL;
992  value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
993  tgrel->rd_att, &isnull);
994  if (!isnull)
995  tgnewtable = NameStr(*DatumGetName(value));
996  else
997  tgnewtable = NULL;
998  if (tgoldtable != NULL || tgnewtable != NULL)
999  {
1000  appendStringInfoString(&buf, "REFERENCING ");
1001  if (tgoldtable != NULL)
1002  appendStringInfo(&buf, "OLD TABLE AS %s ",
1003  quote_identifier(tgoldtable));
1004  if (tgnewtable != NULL)
1005  appendStringInfo(&buf, "NEW TABLE AS %s ",
1006  quote_identifier(tgnewtable));
1007  }
1008 
1009  if (TRIGGER_FOR_ROW(trigrec->tgtype))
1010  appendStringInfoString(&buf, "FOR EACH ROW ");
1011  else
1012  appendStringInfoString(&buf, "FOR EACH STATEMENT ");
1013 
1014  /* If the trigger has a WHEN qualification, add that */
1015  value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
1016  tgrel->rd_att, &isnull);
1017  if (!isnull)
1018  {
1019  Node *qual;
1020  char relkind;
1021  deparse_context context;
1022  deparse_namespace dpns;
1023  RangeTblEntry *oldrte;
1024  RangeTblEntry *newrte;
1025 
1026  appendStringInfoString(&buf, "WHEN (");
1027 
1029 
1030  relkind = get_rel_relkind(trigrec->tgrelid);
1031 
1032  /* Build minimal OLD and NEW RTEs for the rel */
1033  oldrte = makeNode(RangeTblEntry);
1034  oldrte->rtekind = RTE_RELATION;
1035  oldrte->relid = trigrec->tgrelid;
1036  oldrte->relkind = relkind;
1037  oldrte->rellockmode = AccessShareLock;
1038  oldrte->alias = makeAlias("old", NIL);
1039  oldrte->eref = oldrte->alias;
1040  oldrte->lateral = false;
1041  oldrte->inh = false;
1042  oldrte->inFromCl = true;
1043 
1044  newrte = makeNode(RangeTblEntry);
1045  newrte->rtekind = RTE_RELATION;
1046  newrte->relid = trigrec->tgrelid;
1047  newrte->relkind = relkind;
1048  newrte->rellockmode = AccessShareLock;
1049  newrte->alias = makeAlias("new", NIL);
1050  newrte->eref = newrte->alias;
1051  newrte->lateral = false;
1052  newrte->inh = false;
1053  newrte->inFromCl = true;
1054 
1055  /* Build two-element rtable */
1056  memset(&dpns, 0, sizeof(dpns));
1057  dpns.rtable = list_make2(oldrte, newrte);
1058  dpns.subplans = NIL;
1059  dpns.ctes = NIL;
1060  dpns.appendrels = NULL;
1061  set_rtable_names(&dpns, NIL, NULL);
1062  set_simple_column_names(&dpns);
1063 
1064  /* Set up context with one-deep namespace stack */
1065  context.buf = &buf;
1066  context.namespaces = list_make1(&dpns);
1067  context.windowClause = NIL;
1068  context.windowTList = NIL;
1069  context.varprefix = true;
1070  context.prettyFlags = GET_PRETTY_FLAGS(pretty);
1071  context.wrapColumn = WRAP_COLUMN_DEFAULT;
1072  context.indentLevel = PRETTYINDENT_STD;
1073  context.special_exprkind = EXPR_KIND_NONE;
1074  context.appendparents = NULL;
1075 
1076  get_rule_expr(qual, &context, false);
1077 
1078  appendStringInfoString(&buf, ") ");
1079  }
1080 
1081  appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
1082  generate_function_name(trigrec->tgfoid, 0,
1083  NIL, NULL,
1084  false, NULL, EXPR_KIND_NONE));
1085 
1086  if (trigrec->tgnargs > 0)
1087  {
1088  char *p;
1089  int i;
1090 
1091  value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
1092  tgrel->rd_att, &isnull);
1093  if (isnull)
1094  elog(ERROR, "tgargs is null for trigger %u", trigid);
1095  p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
1096  for (i = 0; i < trigrec->tgnargs; i++)
1097  {
1098  if (i > 0)
1099  appendStringInfoString(&buf, ", ");
1101  /* advance p to next string embedded in tgargs */
1102  while (*p)
1103  p++;
1104  p++;
1105  }
1106  }
1107 
1108  /* We deliberately do not put semi-colon at end */
1109  appendStringInfoChar(&buf, ')');
1110 
1111  /* Clean up */
1112  systable_endscan(tgscan);
1113 
1114  table_close(tgrel, AccessShareLock);
1115 
1116  return buf.data;
1117 }
1118 
1119 /* ----------
1120  * pg_get_indexdef - Get the definition of an index
1121  *
1122  * In the extended version, there is a colno argument as well as pretty bool.
1123  * if colno == 0, we want a complete index definition.
1124  * if colno > 0, we only want the Nth index key's variable or expression.
1125  *
1126  * Note that the SQL-function versions of this omit any info about the
1127  * index tablespace; this is intentional because pg_dump wants it that way.
1128  * However pg_get_indexdef_string() includes the index tablespace.
1129  * ----------
1130  */
1131 Datum
1133 {
1134  Oid indexrelid = PG_GETARG_OID(0);
1135  int prettyFlags;
1136  char *res;
1137 
1138  prettyFlags = PRETTYFLAG_INDENT;
1139 
1140  res = pg_get_indexdef_worker(indexrelid, 0, NULL,
1141  false, false,
1142  false, false,
1143  prettyFlags, true);
1144 
1145  if (res == NULL)
1146  PG_RETURN_NULL();
1147 
1149 }
1150 
1151 Datum
1153 {
1154  Oid indexrelid = PG_GETARG_OID(0);
1155  int32 colno = PG_GETARG_INT32(1);
1156  bool pretty = PG_GETARG_BOOL(2);
1157  int prettyFlags;
1158  char *res;
1159 
1160  prettyFlags = GET_PRETTY_FLAGS(pretty);
1161 
1162  res = pg_get_indexdef_worker(indexrelid, colno, NULL,
1163  colno != 0, false,
1164  false, false,
1165  prettyFlags, true);
1166 
1167  if (res == NULL)
1168  PG_RETURN_NULL();
1169 
1171 }
1172 
1173 /*
1174  * Internal version for use by ALTER TABLE.
1175  * Includes a tablespace clause in the result.
1176  * Returns a palloc'd C string; no pretty-printing.
1177  */
1178 char *
1180 {
1181  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1182  false, false,
1183  true, true,
1184  0, false);
1185 }
1186 
1187 /* Internal version that just reports the key-column definitions */
1188 char *
1189 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1190 {
1191  int prettyFlags;
1192 
1193  prettyFlags = GET_PRETTY_FLAGS(pretty);
1194 
1195  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1196  true, true,
1197  false, false,
1198  prettyFlags, false);
1199 }
1200 
1201 /*
1202  * Internal workhorse to decompile an index definition.
1203  *
1204  * This is now used for exclusion constraints as well: if excludeOps is not
1205  * NULL then it points to an array of exclusion operator OIDs.
1206  */
1207 static char *
1208 pg_get_indexdef_worker(Oid indexrelid, int colno,
1209  const Oid *excludeOps,
1210  bool attrsOnly, bool keysOnly,
1211  bool showTblSpc, bool inherits,
1212  int prettyFlags, bool missing_ok)
1213 {
1214  /* might want a separate isConstraint parameter later */
1215  bool isConstraint = (excludeOps != NULL);
1216  HeapTuple ht_idx;
1217  HeapTuple ht_idxrel;
1218  HeapTuple ht_am;
1219  Form_pg_index idxrec;
1220  Form_pg_class idxrelrec;
1221  Form_pg_am amrec;
1222  IndexAmRoutine *amroutine;
1223  List *indexprs;
1224  ListCell *indexpr_item;
1225  List *context;
1226  Oid indrelid;
1227  int keyno;
1228  Datum indcollDatum;
1229  Datum indclassDatum;
1230  Datum indoptionDatum;
1231  bool isnull;
1232  oidvector *indcollation;
1233  oidvector *indclass;
1234  int2vector *indoption;
1236  char *str;
1237  char *sep;
1238 
1239  /*
1240  * Fetch the pg_index tuple by the Oid of the index
1241  */
1242  ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1243  if (!HeapTupleIsValid(ht_idx))
1244  {
1245  if (missing_ok)
1246  return NULL;
1247  elog(ERROR, "cache lookup failed for index %u", indexrelid);
1248  }
1249  idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1250 
1251  indrelid = idxrec->indrelid;
1252  Assert(indexrelid == idxrec->indexrelid);
1253 
1254  /* Must get indcollation, indclass, and indoption the hard way */
1255  indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1256  Anum_pg_index_indcollation, &isnull);
1257  Assert(!isnull);
1258  indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1259 
1260  indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1261  Anum_pg_index_indclass, &isnull);
1262  Assert(!isnull);
1263  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1264 
1265  indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1266  Anum_pg_index_indoption, &isnull);
1267  Assert(!isnull);
1268  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1269 
1270  /*
1271  * Fetch the pg_class tuple of the index relation
1272  */
1273  ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1274  if (!HeapTupleIsValid(ht_idxrel))
1275  elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1276  idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1277 
1278  /*
1279  * Fetch the pg_am tuple of the index' access method
1280  */
1281  ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1282  if (!HeapTupleIsValid(ht_am))
1283  elog(ERROR, "cache lookup failed for access method %u",
1284  idxrelrec->relam);
1285  amrec = (Form_pg_am) GETSTRUCT(ht_am);
1286 
1287  /* Fetch the index AM's API struct */
1288  amroutine = GetIndexAmRoutine(amrec->amhandler);
1289 
1290  /*
1291  * Get the index expressions, if any. (NOTE: we do not use the relcache
1292  * versions of the expressions and predicate, because we want to display
1293  * non-const-folded expressions.)
1294  */
1295  if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
1296  {
1297  Datum exprsDatum;
1298  char *exprsString;
1299 
1300  exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1301  Anum_pg_index_indexprs, &isnull);
1302  Assert(!isnull);
1303  exprsString = TextDatumGetCString(exprsDatum);
1304  indexprs = (List *) stringToNode(exprsString);
1305  pfree(exprsString);
1306  }
1307  else
1308  indexprs = NIL;
1309 
1310  indexpr_item = list_head(indexprs);
1311 
1312  context = deparse_context_for(get_relation_name(indrelid), indrelid);
1313 
1314  /*
1315  * Start the index definition. Note that the index's name should never be
1316  * schema-qualified, but the indexed rel's name may be.
1317  */
1318  initStringInfo(&buf);
1319 
1320  if (!attrsOnly)
1321  {
1322  if (!isConstraint)
1323  appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
1324  idxrec->indisunique ? "UNIQUE " : "",
1325  quote_identifier(NameStr(idxrelrec->relname)),
1326  idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
1327  && !inherits ? "ONLY " : "",
1328  (prettyFlags & PRETTYFLAG_SCHEMA) ?
1329  generate_relation_name(indrelid, NIL) :
1331  quote_identifier(NameStr(amrec->amname)));
1332  else /* currently, must be EXCLUDE constraint */
1333  appendStringInfo(&buf, "EXCLUDE USING %s (",
1334  quote_identifier(NameStr(amrec->amname)));
1335  }
1336 
1337  /*
1338  * Report the indexed attributes
1339  */
1340  sep = "";
1341  for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1342  {
1343  AttrNumber attnum = idxrec->indkey.values[keyno];
1344  Oid keycoltype;
1345  Oid keycolcollation;
1346 
1347  /*
1348  * Ignore non-key attributes if told to.
1349  */
1350  if (keysOnly && keyno >= idxrec->indnkeyatts)
1351  break;
1352 
1353  /* Otherwise, print INCLUDE to divide key and non-key attrs. */
1354  if (!colno && keyno == idxrec->indnkeyatts)
1355  {
1356  appendStringInfoString(&buf, ") INCLUDE (");
1357  sep = "";
1358  }
1359 
1360  if (!colno)
1361  appendStringInfoString(&buf, sep);
1362  sep = ", ";
1363 
1364  if (attnum != 0)
1365  {
1366  /* Simple index column */
1367  char *attname;
1368  int32 keycoltypmod;
1369 
1370  attname = get_attname(indrelid, attnum, false);
1371  if (!colno || colno == keyno + 1)
1373  get_atttypetypmodcoll(indrelid, attnum,
1374  &keycoltype, &keycoltypmod,
1375  &keycolcollation);
1376  }
1377  else
1378  {
1379  /* expressional index */
1380  Node *indexkey;
1381 
1382  if (indexpr_item == NULL)
1383  elog(ERROR, "too few entries in indexprs list");
1384  indexkey = (Node *) lfirst(indexpr_item);
1385  indexpr_item = lnext(indexprs, indexpr_item);
1386  /* Deparse */
1387  str = deparse_expression_pretty(indexkey, context, false, false,
1388  prettyFlags, 0);
1389  if (!colno || colno == keyno + 1)
1390  {
1391  /* Need parens if it's not a bare function call */
1392  if (looks_like_function(indexkey))
1394  else
1395  appendStringInfo(&buf, "(%s)", str);
1396  }
1397  keycoltype = exprType(indexkey);
1398  keycolcollation = exprCollation(indexkey);
1399  }
1400 
1401  /* Print additional decoration for (selected) key columns */
1402  if (!attrsOnly && keyno < idxrec->indnkeyatts &&
1403  (!colno || colno == keyno + 1))
1404  {
1405  int16 opt = indoption->values[keyno];
1406  Oid indcoll = indcollation->values[keyno];
1407  Datum attoptions = get_attoptions(indexrelid, keyno + 1);
1408  bool has_options = attoptions != (Datum) 0;
1409 
1410  /* Add collation, if not default for column */
1411  if (OidIsValid(indcoll) && indcoll != keycolcollation)
1412  appendStringInfo(&buf, " COLLATE %s",
1413  generate_collation_name((indcoll)));
1414 
1415  /* Add the operator class name, if not default */
1416  get_opclass_name(indclass->values[keyno],
1417  has_options ? InvalidOid : keycoltype, &buf);
1418 
1419  if (has_options)
1420  {
1421  appendStringInfoString(&buf, " (");
1422  get_reloptions(&buf, attoptions);
1423  appendStringInfoChar(&buf, ')');
1424  }
1425 
1426  /* Add options if relevant */
1427  if (amroutine->amcanorder)
1428  {
1429  /* if it supports sort ordering, report DESC and NULLS opts */
1430  if (opt & INDOPTION_DESC)
1431  {
1432  appendStringInfoString(&buf, " DESC");
1433  /* NULLS FIRST is the default in this case */
1434  if (!(opt & INDOPTION_NULLS_FIRST))
1435  appendStringInfoString(&buf, " NULLS LAST");
1436  }
1437  else
1438  {
1439  if (opt & INDOPTION_NULLS_FIRST)
1440  appendStringInfoString(&buf, " NULLS FIRST");
1441  }
1442  }
1443 
1444  /* Add the exclusion operator if relevant */
1445  if (excludeOps != NULL)
1446  appendStringInfo(&buf, " WITH %s",
1447  generate_operator_name(excludeOps[keyno],
1448  keycoltype,
1449  keycoltype));
1450  }
1451  }
1452 
1453  if (!attrsOnly)
1454  {
1455  appendStringInfoChar(&buf, ')');
1456 
1457  if (idxrec->indnullsnotdistinct)
1458  appendStringInfoString(&buf, " NULLS NOT DISTINCT");
1459 
1460  /*
1461  * If it has options, append "WITH (options)"
1462  */
1463  str = flatten_reloptions(indexrelid);
1464  if (str)
1465  {
1466  appendStringInfo(&buf, " WITH (%s)", str);
1467  pfree(str);
1468  }
1469 
1470  /*
1471  * Print tablespace, but only if requested
1472  */
1473  if (showTblSpc)
1474  {
1475  Oid tblspc;
1476 
1477  tblspc = get_rel_tablespace(indexrelid);
1478  if (OidIsValid(tblspc))
1479  {
1480  if (isConstraint)
1481  appendStringInfoString(&buf, " USING INDEX");
1482  appendStringInfo(&buf, " TABLESPACE %s",
1484  }
1485  }
1486 
1487  /*
1488  * If it's a partial index, decompile and append the predicate
1489  */
1490  if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
1491  {
1492  Node *node;
1493  Datum predDatum;
1494  char *predString;
1495 
1496  /* Convert text string to node tree */
1497  predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1498  Anum_pg_index_indpred, &isnull);
1499  Assert(!isnull);
1500  predString = TextDatumGetCString(predDatum);
1501  node = (Node *) stringToNode(predString);
1502  pfree(predString);
1503 
1504  /* Deparse */
1505  str = deparse_expression_pretty(node, context, false, false,
1506  prettyFlags, 0);
1507  if (isConstraint)
1508  appendStringInfo(&buf, " WHERE (%s)", str);
1509  else
1510  appendStringInfo(&buf, " WHERE %s", str);
1511  }
1512  }
1513 
1514  /* Clean up */
1515  ReleaseSysCache(ht_idx);
1516  ReleaseSysCache(ht_idxrel);
1517  ReleaseSysCache(ht_am);
1518 
1519  return buf.data;
1520 }
1521 
1522 /* ----------
1523  * pg_get_querydef
1524  *
1525  * Public entry point to deparse one query parsetree.
1526  * The pretty flags are determined by GET_PRETTY_FLAGS(pretty).
1527  *
1528  * The result is a palloc'd C string.
1529  * ----------
1530  */
1531 char *
1532 pg_get_querydef(Query *query, bool pretty)
1533 {
1535  int prettyFlags;
1536 
1537  prettyFlags = GET_PRETTY_FLAGS(pretty);
1538 
1539  initStringInfo(&buf);
1540 
1541  get_query_def(query, &buf, NIL, NULL, true,
1542  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
1543 
1544  return buf.data;
1545 }
1546 
1547 /*
1548  * pg_get_statisticsobjdef
1549  * Get the definition of an extended statistics object
1550  */
1551 Datum
1553 {
1554  Oid statextid = PG_GETARG_OID(0);
1555  char *res;
1556 
1557  res = pg_get_statisticsobj_worker(statextid, false, true);
1558 
1559  if (res == NULL)
1560  PG_RETURN_NULL();
1561 
1563 }
1564 
1565 /*
1566  * Internal version for use by ALTER TABLE.
1567  * Includes a tablespace clause in the result.
1568  * Returns a palloc'd C string; no pretty-printing.
1569  */
1570 char *
1572 {
1573  return pg_get_statisticsobj_worker(statextid, false, false);
1574 }
1575 
1576 /*
1577  * pg_get_statisticsobjdef_columns
1578  * Get columns and expressions for an extended statistics object
1579  */
1580 Datum
1582 {
1583  Oid statextid = PG_GETARG_OID(0);
1584  char *res;
1585 
1586  res = pg_get_statisticsobj_worker(statextid, true, true);
1587 
1588  if (res == NULL)
1589  PG_RETURN_NULL();
1590 
1592 }
1593 
1594 /*
1595  * Internal workhorse to decompile an extended statistics object.
1596  */
1597 static char *
1598 pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
1599 {
1600  Form_pg_statistic_ext statextrec;
1601  HeapTuple statexttup;
1603  int colno;
1604  char *nsp;
1605  ArrayType *arr;
1606  char *enabled;
1607  Datum datum;
1608  bool ndistinct_enabled;
1609  bool dependencies_enabled;
1610  bool mcv_enabled;
1611  int i;
1612  List *context;
1613  ListCell *lc;
1614  List *exprs = NIL;
1615  bool has_exprs;
1616  int ncolumns;
1617 
1618  statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1619 
1620  if (!HeapTupleIsValid(statexttup))
1621  {
1622  if (missing_ok)
1623  return NULL;
1624  elog(ERROR, "cache lookup failed for statistics object %u", statextid);
1625  }
1626 
1627  /* has the statistics expressions? */
1628  has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1629 
1630  statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1631 
1632  /*
1633  * Get the statistics expressions, if any. (NOTE: we do not use the
1634  * relcache versions of the expressions, because we want to display
1635  * non-const-folded expressions.)
1636  */
1637  if (has_exprs)
1638  {
1639  Datum exprsDatum;
1640  bool isnull;
1641  char *exprsString;
1642 
1643  exprsDatum = SysCacheGetAttr(STATEXTOID, statexttup,
1644  Anum_pg_statistic_ext_stxexprs, &isnull);
1645  Assert(!isnull);
1646  exprsString = TextDatumGetCString(exprsDatum);
1647  exprs = (List *) stringToNode(exprsString);
1648  pfree(exprsString);
1649  }
1650  else
1651  exprs = NIL;
1652 
1653  /* count the number of columns (attributes and expressions) */
1654  ncolumns = statextrec->stxkeys.dim1 + list_length(exprs);
1655 
1656  initStringInfo(&buf);
1657 
1658  if (!columns_only)
1659  {
1660  bool isnull;
1661 
1662  nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
1663  appendStringInfo(&buf, "CREATE STATISTICS %s",
1665  NameStr(statextrec->stxname)));
1666 
1667  /*
1668  * Decode the stxkind column so that we know which stats types to
1669  * print.
1670  */
1671  datum = SysCacheGetAttr(STATEXTOID, statexttup,
1672  Anum_pg_statistic_ext_stxkind, &isnull);
1673  Assert(!isnull);
1674  arr = DatumGetArrayTypeP(datum);
1675  if (ARR_NDIM(arr) != 1 ||
1676  ARR_HASNULL(arr) ||
1677  ARR_ELEMTYPE(arr) != CHAROID)
1678  elog(ERROR, "stxkind is not a 1-D char array");
1679  enabled = (char *) ARR_DATA_PTR(arr);
1680 
1681  ndistinct_enabled = false;
1682  dependencies_enabled = false;
1683  mcv_enabled = false;
1684 
1685  for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1686  {
1687  if (enabled[i] == STATS_EXT_NDISTINCT)
1688  ndistinct_enabled = true;
1689  else if (enabled[i] == STATS_EXT_DEPENDENCIES)
1690  dependencies_enabled = true;
1691  else if (enabled[i] == STATS_EXT_MCV)
1692  mcv_enabled = true;
1693 
1694  /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */
1695  }
1696 
1697  /*
1698  * If any option is disabled, then we'll need to append the types
1699  * clause to show which options are enabled. We omit the types clause
1700  * on purpose when all options are enabled, so a pg_dump/pg_restore
1701  * will create all statistics types on a newer postgres version, if
1702  * the statistics had all options enabled on the original version.
1703  *
1704  * But if the statistics is defined on just a single column, it has to
1705  * be an expression statistics. In that case we don't need to specify
1706  * kinds.
1707  */
1708  if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) &&
1709  (ncolumns > 1))
1710  {
1711  bool gotone = false;
1712 
1713  appendStringInfoString(&buf, " (");
1714 
1715  if (ndistinct_enabled)
1716  {
1717  appendStringInfoString(&buf, "ndistinct");
1718  gotone = true;
1719  }
1720 
1721  if (dependencies_enabled)
1722  {
1723  appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
1724  gotone = true;
1725  }
1726 
1727  if (mcv_enabled)
1728  appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
1729 
1730  appendStringInfoChar(&buf, ')');
1731  }
1732 
1733  appendStringInfoString(&buf, " ON ");
1734  }
1735 
1736  /* decode simple column references */
1737  for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
1738  {
1739  AttrNumber attnum = statextrec->stxkeys.values[colno];
1740  char *attname;
1741 
1742  if (colno > 0)
1743  appendStringInfoString(&buf, ", ");
1744 
1745  attname = get_attname(statextrec->stxrelid, attnum, false);
1746 
1748  }
1749 
1750  context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1751  statextrec->stxrelid);
1752 
1753  foreach(lc, exprs)
1754  {
1755  Node *expr = (Node *) lfirst(lc);
1756  char *str;
1757  int prettyFlags = PRETTYFLAG_PAREN;
1758 
1759  str = deparse_expression_pretty(expr, context, false, false,
1760  prettyFlags, 0);
1761 
1762  if (colno > 0)
1763  appendStringInfoString(&buf, ", ");
1764 
1765  /* Need parens if it's not a bare function call */
1766  if (looks_like_function(expr))
1768  else
1769  appendStringInfo(&buf, "(%s)", str);
1770 
1771  colno++;
1772  }
1773 
1774  if (!columns_only)
1775  appendStringInfo(&buf, " FROM %s",
1776  generate_relation_name(statextrec->stxrelid, NIL));
1777 
1778  ReleaseSysCache(statexttup);
1779 
1780  return buf.data;
1781 }
1782 
1783 /*
1784  * Generate text array of expressions for statistics object.
1785  */
1786 Datum
1788 {
1789  Oid statextid = PG_GETARG_OID(0);
1790  Form_pg_statistic_ext statextrec;
1791  HeapTuple statexttup;
1792  Datum datum;
1793  bool isnull;
1794  List *context;
1795  ListCell *lc;
1796  List *exprs = NIL;
1797  bool has_exprs;
1798  char *tmp;
1799  ArrayBuildState *astate = NULL;
1800 
1801  statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1802 
1803  if (!HeapTupleIsValid(statexttup))
1804  PG_RETURN_NULL();
1805 
1806  /* Does the stats object have expressions? */
1807  has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1808 
1809  /* no expressions? we're done */
1810  if (!has_exprs)
1811  {
1812  ReleaseSysCache(statexttup);
1813  PG_RETURN_NULL();
1814  }
1815 
1816  statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1817 
1818  /*
1819  * Get the statistics expressions, and deparse them into text values.
1820  */
1821  datum = SysCacheGetAttr(STATEXTOID, statexttup,
1822  Anum_pg_statistic_ext_stxexprs, &isnull);
1823 
1824  Assert(!isnull);
1825  tmp = TextDatumGetCString(datum);
1826  exprs = (List *) stringToNode(tmp);
1827  pfree(tmp);
1828 
1829  context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1830  statextrec->stxrelid);
1831 
1832  foreach(lc, exprs)
1833  {
1834  Node *expr = (Node *) lfirst(lc);
1835  char *str;
1836  int prettyFlags = PRETTYFLAG_INDENT;
1837 
1838  str = deparse_expression_pretty(expr, context, false, false,
1839  prettyFlags, 0);
1840 
1841  astate = accumArrayResult(astate,
1843  false,
1844  TEXTOID,
1846  }
1847 
1848  ReleaseSysCache(statexttup);
1849 
1851 }
1852 
1853 /*
1854  * pg_get_partkeydef
1855  *
1856  * Returns the partition key specification, ie, the following:
1857  *
1858  * { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
1859  */
1860 Datum
1862 {
1863  Oid relid = PG_GETARG_OID(0);
1864  char *res;
1865 
1866  res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
1867 
1868  if (res == NULL)
1869  PG_RETURN_NULL();
1870 
1872 }
1873 
1874 /* Internal version that just reports the column definitions */
1875 char *
1876 pg_get_partkeydef_columns(Oid relid, bool pretty)
1877 {
1878  int prettyFlags;
1879 
1880  prettyFlags = GET_PRETTY_FLAGS(pretty);
1881 
1882  return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
1883 }
1884 
1885 /*
1886  * Internal workhorse to decompile a partition key definition.
1887  */
1888 static char *
1889 pg_get_partkeydef_worker(Oid relid, int prettyFlags,
1890  bool attrsOnly, bool missing_ok)
1891 {
1893  HeapTuple tuple;
1894  oidvector *partclass;
1895  oidvector *partcollation;
1896  List *partexprs;
1897  ListCell *partexpr_item;
1898  List *context;
1899  Datum datum;
1900  bool isnull;
1902  int keyno;
1903  char *str;
1904  char *sep;
1905 
1906  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
1907  if (!HeapTupleIsValid(tuple))
1908  {
1909  if (missing_ok)
1910  return NULL;
1911  elog(ERROR, "cache lookup failed for partition key of %u", relid);
1912  }
1913 
1914  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
1915 
1916  Assert(form->partrelid == relid);
1917 
1918  /* Must get partclass and partcollation the hard way */
1919  datum = SysCacheGetAttr(PARTRELID, tuple,
1920  Anum_pg_partitioned_table_partclass, &isnull);
1921  Assert(!isnull);
1922  partclass = (oidvector *) DatumGetPointer(datum);
1923 
1924  datum = SysCacheGetAttr(PARTRELID, tuple,
1925  Anum_pg_partitioned_table_partcollation, &isnull);
1926  Assert(!isnull);
1927  partcollation = (oidvector *) DatumGetPointer(datum);
1928 
1929 
1930  /*
1931  * Get the expressions, if any. (NOTE: we do not use the relcache
1932  * versions of the expressions, because we want to display
1933  * non-const-folded expressions.)
1934  */
1935  if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
1936  {
1937  Datum exprsDatum;
1938  char *exprsString;
1939 
1940  exprsDatum = SysCacheGetAttr(PARTRELID, tuple,
1941  Anum_pg_partitioned_table_partexprs, &isnull);
1942  Assert(!isnull);
1943  exprsString = TextDatumGetCString(exprsDatum);
1944  partexprs = (List *) stringToNode(exprsString);
1945 
1946  if (!IsA(partexprs, List))
1947  elog(ERROR, "unexpected node type found in partexprs: %d",
1948  (int) nodeTag(partexprs));
1949 
1950  pfree(exprsString);
1951  }
1952  else
1953  partexprs = NIL;
1954 
1955  partexpr_item = list_head(partexprs);
1956  context = deparse_context_for(get_relation_name(relid), relid);
1957 
1958  initStringInfo(&buf);
1959 
1960  switch (form->partstrat)
1961  {
1963  if (!attrsOnly)
1964  appendStringInfoString(&buf, "HASH");
1965  break;
1967  if (!attrsOnly)
1968  appendStringInfoString(&buf, "LIST");
1969  break;
1971  if (!attrsOnly)
1972  appendStringInfoString(&buf, "RANGE");
1973  break;
1974  default:
1975  elog(ERROR, "unexpected partition strategy: %d",
1976  (int) form->partstrat);
1977  }
1978 
1979  if (!attrsOnly)
1980  appendStringInfoString(&buf, " (");
1981  sep = "";
1982  for (keyno = 0; keyno < form->partnatts; keyno++)
1983  {
1984  AttrNumber attnum = form->partattrs.values[keyno];
1985  Oid keycoltype;
1986  Oid keycolcollation;
1987  Oid partcoll;
1988 
1989  appendStringInfoString(&buf, sep);
1990  sep = ", ";
1991  if (attnum != 0)
1992  {
1993  /* Simple attribute reference */
1994  char *attname;
1995  int32 keycoltypmod;
1996 
1997  attname = get_attname(relid, attnum, false);
2000  &keycoltype, &keycoltypmod,
2001  &keycolcollation);
2002  }
2003  else
2004  {
2005  /* Expression */
2006  Node *partkey;
2007 
2008  if (partexpr_item == NULL)
2009  elog(ERROR, "too few entries in partexprs list");
2010  partkey = (Node *) lfirst(partexpr_item);
2011  partexpr_item = lnext(partexprs, partexpr_item);
2012 
2013  /* Deparse */
2014  str = deparse_expression_pretty(partkey, context, false, false,
2015  prettyFlags, 0);
2016  /* Need parens if it's not a bare function call */
2017  if (looks_like_function(partkey))
2019  else
2020  appendStringInfo(&buf, "(%s)", str);
2021 
2022  keycoltype = exprType(partkey);
2023  keycolcollation = exprCollation(partkey);
2024  }
2025 
2026  /* Add collation, if not default for column */
2027  partcoll = partcollation->values[keyno];
2028  if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
2029  appendStringInfo(&buf, " COLLATE %s",
2030  generate_collation_name((partcoll)));
2031 
2032  /* Add the operator class name, if not default */
2033  if (!attrsOnly)
2034  get_opclass_name(partclass->values[keyno], keycoltype, &buf);
2035  }
2036 
2037  if (!attrsOnly)
2038  appendStringInfoChar(&buf, ')');
2039 
2040  /* Clean up */
2041  ReleaseSysCache(tuple);
2042 
2043  return buf.data;
2044 }
2045 
2046 /*
2047  * pg_get_partition_constraintdef
2048  *
2049  * Returns partition constraint expression as a string for the input relation
2050  */
2051 Datum
2053 {
2054  Oid relationId = PG_GETARG_OID(0);
2055  Expr *constr_expr;
2056  int prettyFlags;
2057  List *context;
2058  char *consrc;
2059 
2060  constr_expr = get_partition_qual_relid(relationId);
2061 
2062  /* Quick exit if no partition constraint */
2063  if (constr_expr == NULL)
2064  PG_RETURN_NULL();
2065 
2066  /*
2067  * Deparse and return the constraint expression.
2068  */
2069  prettyFlags = PRETTYFLAG_INDENT;
2070  context = deparse_context_for(get_relation_name(relationId), relationId);
2071  consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
2072  false, prettyFlags, 0);
2073 
2075 }
2076 
2077 /*
2078  * pg_get_partconstrdef_string
2079  *
2080  * Returns the partition constraint as a C-string for the input relation, with
2081  * the given alias. No pretty-printing.
2082  */
2083 char *
2084 pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
2085 {
2086  Expr *constr_expr;
2087  List *context;
2088 
2089  constr_expr = get_partition_qual_relid(partitionId);
2090  context = deparse_context_for(aliasname, partitionId);
2091 
2092  return deparse_expression((Node *) constr_expr, context, true, false);
2093 }
2094 
2095 /*
2096  * pg_get_constraintdef
2097  *
2098  * Returns the definition for the constraint, ie, everything that needs to
2099  * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
2100  */
2101 Datum
2103 {
2104  Oid constraintId = PG_GETARG_OID(0);
2105  int prettyFlags;
2106  char *res;
2107 
2108  prettyFlags = PRETTYFLAG_INDENT;
2109 
2110  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2111 
2112  if (res == NULL)
2113  PG_RETURN_NULL();
2114 
2116 }
2117 
2118 Datum
2120 {
2121  Oid constraintId = PG_GETARG_OID(0);
2122  bool pretty = PG_GETARG_BOOL(1);
2123  int prettyFlags;
2124  char *res;
2125 
2126  prettyFlags = GET_PRETTY_FLAGS(pretty);
2127 
2128  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2129 
2130  if (res == NULL)
2131  PG_RETURN_NULL();
2132 
2134 }
2135 
2136 /*
2137  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
2138  */
2139 char *
2141 {
2142  return pg_get_constraintdef_worker(constraintId, true, 0, false);
2143 }
2144 
2145 /*
2146  * As of 9.4, we now use an MVCC snapshot for this.
2147  */
2148 static char *
2149 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
2150  int prettyFlags, bool missing_ok)
2151 {
2152  HeapTuple tup;
2153  Form_pg_constraint conForm;
2155  SysScanDesc scandesc;
2156  ScanKeyData scankey[1];
2158  Relation relation = table_open(ConstraintRelationId, AccessShareLock);
2159 
2160  ScanKeyInit(&scankey[0],
2161  Anum_pg_constraint_oid,
2162  BTEqualStrategyNumber, F_OIDEQ,
2163  ObjectIdGetDatum(constraintId));
2164 
2165  scandesc = systable_beginscan(relation,
2166  ConstraintOidIndexId,
2167  true,
2168  snapshot,
2169  1,
2170  scankey);
2171 
2172  /*
2173  * We later use the tuple with SysCacheGetAttr() as if we had obtained it
2174  * via SearchSysCache, which works fine.
2175  */
2176  tup = systable_getnext(scandesc);
2177 
2178  UnregisterSnapshot(snapshot);
2179 
2180  if (!HeapTupleIsValid(tup))
2181  {
2182  if (missing_ok)
2183  {
2184  systable_endscan(scandesc);
2185  table_close(relation, AccessShareLock);
2186  return NULL;
2187  }
2188  elog(ERROR, "could not find tuple for constraint %u", constraintId);
2189  }
2190 
2191  conForm = (Form_pg_constraint) GETSTRUCT(tup);
2192 
2193  initStringInfo(&buf);
2194 
2195  if (fullCommand)
2196  {
2197  if (OidIsValid(conForm->conrelid))
2198  {
2199  /*
2200  * Currently, callers want ALTER TABLE (without ONLY) for CHECK
2201  * constraints, and other types of constraints don't inherit
2202  * anyway so it doesn't matter whether we say ONLY or not. Someday
2203  * we might need to let callers specify whether to put ONLY in the
2204  * command.
2205  */
2206  appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
2207  generate_qualified_relation_name(conForm->conrelid),
2208  quote_identifier(NameStr(conForm->conname)));
2209  }
2210  else
2211  {
2212  /* Must be a domain constraint */
2213  Assert(OidIsValid(conForm->contypid));
2214  appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
2215  generate_qualified_type_name(conForm->contypid),
2216  quote_identifier(NameStr(conForm->conname)));
2217  }
2218  }
2219 
2220  switch (conForm->contype)
2221  {
2222  case CONSTRAINT_FOREIGN:
2223  {
2224  Datum val;
2225  bool isnull;
2226  const char *string;
2227 
2228  /* Start off the constraint definition */
2229  appendStringInfoString(&buf, "FOREIGN KEY (");
2230 
2231  /* Fetch and build referencing-column list */
2232  val = SysCacheGetAttr(CONSTROID, tup,
2233  Anum_pg_constraint_conkey, &isnull);
2234  if (isnull)
2235  elog(ERROR, "null conkey for constraint %u",
2236  constraintId);
2237 
2238  decompile_column_index_array(val, conForm->conrelid, &buf);
2239 
2240  /* add foreign relation name */
2241  appendStringInfo(&buf, ") REFERENCES %s(",
2242  generate_relation_name(conForm->confrelid,
2243  NIL));
2244 
2245  /* Fetch and build referenced-column list */
2246  val = SysCacheGetAttr(CONSTROID, tup,
2247  Anum_pg_constraint_confkey, &isnull);
2248  if (isnull)
2249  elog(ERROR, "null confkey for constraint %u",
2250  constraintId);
2251 
2252  decompile_column_index_array(val, conForm->confrelid, &buf);
2253 
2254  appendStringInfoChar(&buf, ')');
2255 
2256  /* Add match type */
2257  switch (conForm->confmatchtype)
2258  {
2259  case FKCONSTR_MATCH_FULL:
2260  string = " MATCH FULL";
2261  break;
2263  string = " MATCH PARTIAL";
2264  break;
2265  case FKCONSTR_MATCH_SIMPLE:
2266  string = "";
2267  break;
2268  default:
2269  elog(ERROR, "unrecognized confmatchtype: %d",
2270  conForm->confmatchtype);
2271  string = ""; /* keep compiler quiet */
2272  break;
2273  }
2274  appendStringInfoString(&buf, string);
2275 
2276  /* Add ON UPDATE and ON DELETE clauses, if needed */
2277  switch (conForm->confupdtype)
2278  {
2280  string = NULL; /* suppress default */
2281  break;
2283  string = "RESTRICT";
2284  break;
2286  string = "CASCADE";
2287  break;
2289  string = "SET NULL";
2290  break;
2292  string = "SET DEFAULT";
2293  break;
2294  default:
2295  elog(ERROR, "unrecognized confupdtype: %d",
2296  conForm->confupdtype);
2297  string = NULL; /* keep compiler quiet */
2298  break;
2299  }
2300  if (string)
2301  appendStringInfo(&buf, " ON UPDATE %s", string);
2302 
2303  switch (conForm->confdeltype)
2304  {
2306  string = NULL; /* suppress default */
2307  break;
2309  string = "RESTRICT";
2310  break;
2312  string = "CASCADE";
2313  break;
2315  string = "SET NULL";
2316  break;
2318  string = "SET DEFAULT";
2319  break;
2320  default:
2321  elog(ERROR, "unrecognized confdeltype: %d",
2322  conForm->confdeltype);
2323  string = NULL; /* keep compiler quiet */
2324  break;
2325  }
2326  if (string)
2327  appendStringInfo(&buf, " ON DELETE %s", string);
2328 
2329  /*
2330  * Add columns specified to SET NULL or SET DEFAULT if
2331  * provided.
2332  */
2333  val = SysCacheGetAttr(CONSTROID, tup,
2334  Anum_pg_constraint_confdelsetcols, &isnull);
2335  if (!isnull)
2336  {
2337  appendStringInfoString(&buf, " (");
2338  decompile_column_index_array(val, conForm->conrelid, &buf);
2339  appendStringInfoChar(&buf, ')');
2340  }
2341 
2342  break;
2343  }
2344  case CONSTRAINT_PRIMARY:
2345  case CONSTRAINT_UNIQUE:
2346  {
2347  Datum val;
2348  bool isnull;
2349  Oid indexId;
2350  int keyatts;
2351  HeapTuple indtup;
2352 
2353  /* Start off the constraint definition */
2354  if (conForm->contype == CONSTRAINT_PRIMARY)
2355  appendStringInfoString(&buf, "PRIMARY KEY ");
2356  else
2357  appendStringInfoString(&buf, "UNIQUE ");
2358 
2359  indexId = conForm->conindid;
2360 
2361  indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2362  if (!HeapTupleIsValid(indtup))
2363  elog(ERROR, "cache lookup failed for index %u", indexId);
2364  if (conForm->contype == CONSTRAINT_UNIQUE &&
2365  ((Form_pg_index) GETSTRUCT(indtup))->indnullsnotdistinct)
2366  appendStringInfoString(&buf, "NULLS NOT DISTINCT ");
2367 
2368  appendStringInfoChar(&buf, '(');
2369 
2370  /* Fetch and build target column list */
2371  val = SysCacheGetAttr(CONSTROID, tup,
2372  Anum_pg_constraint_conkey, &isnull);
2373  if (isnull)
2374  elog(ERROR, "null conkey for constraint %u",
2375  constraintId);
2376 
2377  keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2378 
2379  appendStringInfoChar(&buf, ')');
2380 
2381  /* Build including column list (from pg_index.indkeys) */
2382  val = SysCacheGetAttr(INDEXRELID, indtup,
2383  Anum_pg_index_indnatts, &isnull);
2384  if (isnull)
2385  elog(ERROR, "null indnatts for index %u", indexId);
2386  if (DatumGetInt32(val) > keyatts)
2387  {
2388  Datum cols;
2389  Datum *keys;
2390  int nKeys;
2391  int j;
2392 
2393  appendStringInfoString(&buf, " INCLUDE (");
2394 
2395  cols = SysCacheGetAttr(INDEXRELID, indtup,
2396  Anum_pg_index_indkey, &isnull);
2397  if (isnull)
2398  elog(ERROR, "null indkey for index %u", indexId);
2399 
2401  &keys, NULL, &nKeys);
2402 
2403  for (j = keyatts; j < nKeys; j++)
2404  {
2405  char *colName;
2406 
2407  colName = get_attname(conForm->conrelid,
2408  DatumGetInt16(keys[j]), false);
2409  if (j > keyatts)
2410  appendStringInfoString(&buf, ", ");
2412  }
2413 
2414  appendStringInfoChar(&buf, ')');
2415  }
2416  ReleaseSysCache(indtup);
2417 
2418  /* XXX why do we only print these bits if fullCommand? */
2419  if (fullCommand && OidIsValid(indexId))
2420  {
2421  char *options = flatten_reloptions(indexId);
2422  Oid tblspc;
2423 
2424  if (options)
2425  {
2426  appendStringInfo(&buf, " WITH (%s)", options);
2427  pfree(options);
2428  }
2429 
2430  /*
2431  * Print the tablespace, unless it's the database default.
2432  * This is to help ALTER TABLE usage of this facility,
2433  * which needs this behavior to recreate exact catalog
2434  * state.
2435  */
2436  tblspc = get_rel_tablespace(indexId);
2437  if (OidIsValid(tblspc))
2438  appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2440  }
2441 
2442  break;
2443  }
2444  case CONSTRAINT_CHECK:
2445  {
2446  Datum val;
2447  bool isnull;
2448  char *conbin;
2449  char *consrc;
2450  Node *expr;
2451  List *context;
2452 
2453  /* Fetch constraint expression in parsetree form */
2454  val = SysCacheGetAttr(CONSTROID, tup,
2455  Anum_pg_constraint_conbin, &isnull);
2456  if (isnull)
2457  elog(ERROR, "null conbin for constraint %u",
2458  constraintId);
2459 
2460  conbin = TextDatumGetCString(val);
2461  expr = stringToNode(conbin);
2462 
2463  /* Set up deparsing context for Var nodes in constraint */
2464  if (conForm->conrelid != InvalidOid)
2465  {
2466  /* relation constraint */
2467  context = deparse_context_for(get_relation_name(conForm->conrelid),
2468  conForm->conrelid);
2469  }
2470  else
2471  {
2472  /* domain constraint --- can't have Vars */
2473  context = NIL;
2474  }
2475 
2476  consrc = deparse_expression_pretty(expr, context, false, false,
2477  prettyFlags, 0);
2478 
2479  /*
2480  * Now emit the constraint definition, adding NO INHERIT if
2481  * necessary.
2482  *
2483  * There are cases where the constraint expression will be
2484  * fully parenthesized and we don't need the outer parens ...
2485  * but there are other cases where we do need 'em. Be
2486  * conservative for now.
2487  *
2488  * Note that simply checking for leading '(' and trailing ')'
2489  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2490  */
2491  appendStringInfo(&buf, "CHECK (%s)%s",
2492  consrc,
2493  conForm->connoinherit ? " NO INHERIT" : "");
2494  break;
2495  }
2496  case CONSTRAINT_TRIGGER:
2497 
2498  /*
2499  * There isn't an ALTER TABLE syntax for creating a user-defined
2500  * constraint trigger, but it seems better to print something than
2501  * throw an error; if we throw error then this function couldn't
2502  * safely be applied to all rows of pg_constraint.
2503  */
2504  appendStringInfoString(&buf, "TRIGGER");
2505  break;
2506  case CONSTRAINT_EXCLUSION:
2507  {
2508  Oid indexOid = conForm->conindid;
2509  Datum val;
2510  bool isnull;
2511  Datum *elems;
2512  int nElems;
2513  int i;
2514  Oid *operators;
2515 
2516  /* Extract operator OIDs from the pg_constraint tuple */
2517  val = SysCacheGetAttr(CONSTROID, tup,
2518  Anum_pg_constraint_conexclop,
2519  &isnull);
2520  if (isnull)
2521  elog(ERROR, "null conexclop for constraint %u",
2522  constraintId);
2523 
2525  &elems, NULL, &nElems);
2526 
2527  operators = (Oid *) palloc(nElems * sizeof(Oid));
2528  for (i = 0; i < nElems; i++)
2529  operators[i] = DatumGetObjectId(elems[i]);
2530 
2531  /* pg_get_indexdef_worker does the rest */
2532  /* suppress tablespace because pg_dump wants it that way */
2534  pg_get_indexdef_worker(indexOid,
2535  0,
2536  operators,
2537  false,
2538  false,
2539  false,
2540  false,
2541  prettyFlags,
2542  false));
2543  break;
2544  }
2545  default:
2546  elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2547  break;
2548  }
2549 
2550  if (conForm->condeferrable)
2551  appendStringInfoString(&buf, " DEFERRABLE");
2552  if (conForm->condeferred)
2553  appendStringInfoString(&buf, " INITIALLY DEFERRED");
2554  if (!conForm->convalidated)
2555  appendStringInfoString(&buf, " NOT VALID");
2556 
2557  /* Cleanup */
2558  systable_endscan(scandesc);
2559  table_close(relation, AccessShareLock);
2560 
2561  return buf.data;
2562 }
2563 
2564 
2565 /*
2566  * Convert an int16[] Datum into a comma-separated list of column names
2567  * for the indicated relation; append the list to buf. Returns the number
2568  * of keys.
2569  */
2570 static int
2571 decompile_column_index_array(Datum column_index_array, Oid relId,
2572  StringInfo buf)
2573 {
2574  Datum *keys;
2575  int nKeys;
2576  int j;
2577 
2578  /* Extract data from array of int16 */
2579  deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID,
2580  &keys, NULL, &nKeys);
2581 
2582  for (j = 0; j < nKeys; j++)
2583  {
2584  char *colName;
2585 
2586  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2587 
2588  if (j == 0)
2590  else
2591  appendStringInfo(buf, ", %s", quote_identifier(colName));
2592  }
2593 
2594  return nKeys;
2595 }
2596 
2597 
2598 /* ----------
2599  * pg_get_expr - Decompile an expression tree
2600  *
2601  * Input: an expression tree in nodeToString form, and a relation OID
2602  *
2603  * Output: reverse-listed expression
2604  *
2605  * Currently, the expression can only refer to a single relation, namely
2606  * the one specified by the second parameter. This is sufficient for
2607  * partial indexes, column default expressions, etc. We also support
2608  * Var-free expressions, for which the OID can be InvalidOid.
2609  *
2610  * We expect this function to work, or throw a reasonably clean error,
2611  * for any node tree that can appear in a catalog pg_node_tree column.
2612  * Query trees, such as those appearing in pg_rewrite.ev_action, are
2613  * not supported. Nor are expressions in more than one relation, which
2614  * can appear in places like pg_rewrite.ev_qual.
2615  * ----------
2616  */
2617 Datum
2619 {
2620  text *expr = PG_GETARG_TEXT_PP(0);
2621  Oid relid = PG_GETARG_OID(1);
2622  int prettyFlags;
2623  char *relname;
2624 
2625  prettyFlags = PRETTYFLAG_INDENT;
2626 
2627  if (OidIsValid(relid))
2628  {
2629  /* Get the name for the relation */
2630  relname = get_rel_name(relid);
2631 
2632  /*
2633  * If the OID isn't actually valid, don't throw an error, just return
2634  * NULL. This is a bit questionable, but it's what we've done
2635  * historically, and it can help avoid unwanted failures when
2636  * examining catalog entries for just-deleted relations.
2637  */
2638  if (relname == NULL)
2639  PG_RETURN_NULL();
2640  }
2641  else
2642  relname = NULL;
2643 
2644  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2645 }
2646 
2647 Datum
2649 {
2650  text *expr = PG_GETARG_TEXT_PP(0);
2651  Oid relid = PG_GETARG_OID(1);
2652  bool pretty = PG_GETARG_BOOL(2);
2653  int prettyFlags;
2654  char *relname;
2655 
2656  prettyFlags = GET_PRETTY_FLAGS(pretty);
2657 
2658  if (OidIsValid(relid))
2659  {
2660  /* Get the name for the relation */
2661  relname = get_rel_name(relid);
2662  /* See notes above */
2663  if (relname == NULL)
2664  PG_RETURN_NULL();
2665  }
2666  else
2667  relname = NULL;
2668 
2669  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2670 }
2671 
2672 static text *
2673 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
2674 {
2675  Node *node;
2676  Node *tst;
2677  Relids relids;
2678  List *context;
2679  char *exprstr;
2680  char *str;
2681 
2682  /* Convert input pg_node_tree (really TEXT) object to C string */
2683  exprstr = text_to_cstring(expr);
2684 
2685  /* Convert expression to node tree */
2686  node = (Node *) stringToNode(exprstr);
2687 
2688  pfree(exprstr);
2689 
2690  /*
2691  * Throw error if the input is a querytree rather than an expression tree.
2692  * While we could support queries here, there seems no very good reason
2693  * to. In most such catalog columns, we'll see a List of Query nodes, or
2694  * even nested Lists, so drill down to a non-List node before checking.
2695  */
2696  tst = node;
2697  while (tst && IsA(tst, List))
2698  tst = linitial((List *) tst);
2699  if (tst && IsA(tst, Query))
2700  ereport(ERROR,
2701  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2702  errmsg("input is a query, not an expression")));
2703 
2704  /*
2705  * Throw error if the expression contains Vars we won't be able to
2706  * deparse.
2707  */
2708  relids = pull_varnos(NULL, node);
2709  if (OidIsValid(relid))
2710  {
2711  if (!bms_is_subset(relids, bms_make_singleton(1)))
2712  ereport(ERROR,
2713  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2714  errmsg("expression contains variables of more than one relation")));
2715  }
2716  else
2717  {
2718  if (!bms_is_empty(relids))
2719  ereport(ERROR,
2720  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2721  errmsg("expression contains variables")));
2722  }
2723 
2724  /* Prepare deparse context if needed */
2725  if (OidIsValid(relid))
2726  context = deparse_context_for(relname, relid);
2727  else
2728  context = NIL;
2729 
2730  /* Deparse */
2731  str = deparse_expression_pretty(node, context, false, false,
2732  prettyFlags, 0);
2733 
2734  return string_to_text(str);
2735 }
2736 
2737 
2738 /* ----------
2739  * pg_get_userbyid - Get a user name by roleid and
2740  * fallback to 'unknown (OID=n)'
2741  * ----------
2742  */
2743 Datum
2745 {
2746  Oid roleid = PG_GETARG_OID(0);
2747  Name result;
2748  HeapTuple roletup;
2749  Form_pg_authid role_rec;
2750 
2751  /*
2752  * Allocate space for the result
2753  */
2754  result = (Name) palloc(NAMEDATALEN);
2755  memset(NameStr(*result), 0, NAMEDATALEN);
2756 
2757  /*
2758  * Get the pg_authid entry and print the result
2759  */
2760  roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2761  if (HeapTupleIsValid(roletup))
2762  {
2763  role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2764  *result = role_rec->rolname;
2765  ReleaseSysCache(roletup);
2766  }
2767  else
2768  sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2769 
2770  PG_RETURN_NAME(result);
2771 }
2772 
2773 
2774 /*
2775  * pg_get_serial_sequence
2776  * Get the name of the sequence used by an identity or serial column,
2777  * formatted suitably for passing to setval, nextval or currval.
2778  * First parameter is not treated as double-quoted, second parameter
2779  * is --- see documentation for reason.
2780  */
2781 Datum
2783 {
2784  text *tablename = PG_GETARG_TEXT_PP(0);
2785  text *columnname = PG_GETARG_TEXT_PP(1);
2786  RangeVar *tablerv;
2787  Oid tableOid;
2788  char *column;
2790  Oid sequenceId = InvalidOid;
2791  Relation depRel;
2792  ScanKeyData key[3];
2793  SysScanDesc scan;
2794  HeapTuple tup;
2795 
2796  /* Look up table name. Can't lock it - we might not have privileges. */
2797  tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2798  tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2799 
2800  /* Get the number of the column */
2801  column = text_to_cstring(columnname);
2802 
2803  attnum = get_attnum(tableOid, column);
2804  if (attnum == InvalidAttrNumber)
2805  ereport(ERROR,
2806  (errcode(ERRCODE_UNDEFINED_COLUMN),
2807  errmsg("column \"%s\" of relation \"%s\" does not exist",
2808  column, tablerv->relname)));
2809 
2810  /* Search the dependency table for the dependent sequence */
2811  depRel = table_open(DependRelationId, AccessShareLock);
2812 
2813  ScanKeyInit(&key[0],
2814  Anum_pg_depend_refclassid,
2815  BTEqualStrategyNumber, F_OIDEQ,
2816  ObjectIdGetDatum(RelationRelationId));
2817  ScanKeyInit(&key[1],
2818  Anum_pg_depend_refobjid,
2819  BTEqualStrategyNumber, F_OIDEQ,
2820  ObjectIdGetDatum(tableOid));
2821  ScanKeyInit(&key[2],
2822  Anum_pg_depend_refobjsubid,
2823  BTEqualStrategyNumber, F_INT4EQ,
2825 
2826  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2827  NULL, 3, key);
2828 
2829  while (HeapTupleIsValid(tup = systable_getnext(scan)))
2830  {
2831  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2832 
2833  /*
2834  * Look for an auto dependency (serial column) or internal dependency
2835  * (identity column) of a sequence on a column. (We need the relkind
2836  * test because indexes can also have auto dependencies on columns.)
2837  */
2838  if (deprec->classid == RelationRelationId &&
2839  deprec->objsubid == 0 &&
2840  (deprec->deptype == DEPENDENCY_AUTO ||
2841  deprec->deptype == DEPENDENCY_INTERNAL) &&
2842  get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2843  {
2844  sequenceId = deprec->objid;
2845  break;
2846  }
2847  }
2848 
2849  systable_endscan(scan);
2850  table_close(depRel, AccessShareLock);
2851 
2852  if (OidIsValid(sequenceId))
2853  {
2854  char *result;
2855 
2856  result = generate_qualified_relation_name(sequenceId);
2857 
2859  }
2860 
2861  PG_RETURN_NULL();
2862 }
2863 
2864 
2865 /*
2866  * pg_get_functiondef
2867  * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2868  * the specified function.
2869  *
2870  * Note: if you change the output format of this function, be careful not
2871  * to break psql's rules (in \ef and \sf) for identifying the start of the
2872  * function body. To wit: the function body starts on a line that begins with
2873  * "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
2874  */
2875 Datum
2877 {
2878  Oid funcid = PG_GETARG_OID(0);
2880  StringInfoData dq;
2881  HeapTuple proctup;
2882  Form_pg_proc proc;
2883  bool isfunction;
2884  Datum tmp;
2885  bool isnull;
2886  const char *prosrc;
2887  const char *name;
2888  const char *nsp;
2889  float4 procost;
2890  int oldlen;
2891 
2892  initStringInfo(&buf);
2893 
2894  /* Look up the function */
2895  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2896  if (!HeapTupleIsValid(proctup))
2897  PG_RETURN_NULL();
2898 
2899  proc = (Form_pg_proc) GETSTRUCT(proctup);
2900  name = NameStr(proc->proname);
2901 
2902  if (proc->prokind == PROKIND_AGGREGATE)
2903  ereport(ERROR,
2904  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2905  errmsg("\"%s\" is an aggregate function", name)));
2906 
2907  isfunction = (proc->prokind != PROKIND_PROCEDURE);
2908 
2909  /*
2910  * We always qualify the function name, to ensure the right function gets
2911  * replaced.
2912  */
2913  nsp = get_namespace_name_or_temp(proc->pronamespace);
2914  appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2915  isfunction ? "FUNCTION" : "PROCEDURE",
2917  (void) print_function_arguments(&buf, proctup, false, true);
2918  appendStringInfoString(&buf, ")\n");
2919  if (isfunction)
2920  {
2921  appendStringInfoString(&buf, " RETURNS ");
2922  print_function_rettype(&buf, proctup);
2923  appendStringInfoChar(&buf, '\n');
2924  }
2925 
2926  print_function_trftypes(&buf, proctup);
2927 
2928  appendStringInfo(&buf, " LANGUAGE %s\n",
2929  quote_identifier(get_language_name(proc->prolang, false)));
2930 
2931  /* Emit some miscellaneous options on one line */
2932  oldlen = buf.len;
2933 
2934  if (proc->prokind == PROKIND_WINDOW)
2935  appendStringInfoString(&buf, " WINDOW");
2936  switch (proc->provolatile)
2937  {
2938  case PROVOLATILE_IMMUTABLE:
2939  appendStringInfoString(&buf, " IMMUTABLE");
2940  break;
2941  case PROVOLATILE_STABLE:
2942  appendStringInfoString(&buf, " STABLE");
2943  break;
2944  case PROVOLATILE_VOLATILE:
2945  break;
2946  }
2947 
2948  switch (proc->proparallel)
2949  {
2950  case PROPARALLEL_SAFE:
2951  appendStringInfoString(&buf, " PARALLEL SAFE");
2952  break;
2953  case PROPARALLEL_RESTRICTED:
2954  appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2955  break;
2956  case PROPARALLEL_UNSAFE:
2957  break;
2958  }
2959 
2960  if (proc->proisstrict)
2961  appendStringInfoString(&buf, " STRICT");
2962  if (proc->prosecdef)
2963  appendStringInfoString(&buf, " SECURITY DEFINER");
2964  if (proc->proleakproof)
2965  appendStringInfoString(&buf, " LEAKPROOF");
2966 
2967  /* This code for the default cost and rows should match functioncmds.c */
2968  if (proc->prolang == INTERNALlanguageId ||
2969  proc->prolang == ClanguageId)
2970  procost = 1;
2971  else
2972  procost = 100;
2973  if (proc->procost != procost)
2974  appendStringInfo(&buf, " COST %g", proc->procost);
2975 
2976  if (proc->prorows > 0 && proc->prorows != 1000)
2977  appendStringInfo(&buf, " ROWS %g", proc->prorows);
2978 
2979  if (proc->prosupport)
2980  {
2981  Oid argtypes[1];
2982 
2983  /*
2984  * We should qualify the support function's name if it wouldn't be
2985  * resolved by lookup in the current search path.
2986  */
2987  argtypes[0] = INTERNALOID;
2988  appendStringInfo(&buf, " SUPPORT %s",
2989  generate_function_name(proc->prosupport, 1,
2990  NIL, argtypes,
2991  false, NULL, EXPR_KIND_NONE));
2992  }
2993 
2994  if (oldlen != buf.len)
2995  appendStringInfoChar(&buf, '\n');
2996 
2997  /* Emit any proconfig options, one per line */
2998  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
2999  if (!isnull)
3000  {
3001  ArrayType *a = DatumGetArrayTypeP(tmp);
3002  int i;
3003 
3004  Assert(ARR_ELEMTYPE(a) == TEXTOID);
3005  Assert(ARR_NDIM(a) == 1);
3006  Assert(ARR_LBOUND(a)[0] == 1);
3007 
3008  for (i = 1; i <= ARR_DIMS(a)[0]; i++)
3009  {
3010  Datum d;
3011 
3012  d = array_ref(a, 1, &i,
3013  -1 /* varlenarray */ ,
3014  -1 /* TEXT's typlen */ ,
3015  false /* TEXT's typbyval */ ,
3016  TYPALIGN_INT /* TEXT's typalign */ ,
3017  &isnull);
3018  if (!isnull)
3019  {
3020  char *configitem = TextDatumGetCString(d);
3021  char *pos;
3022 
3023  pos = strchr(configitem, '=');
3024  if (pos == NULL)
3025  continue;
3026  *pos++ = '\0';
3027 
3028  appendStringInfo(&buf, " SET %s TO ",
3029  quote_identifier(configitem));
3030 
3031  /*
3032  * Variables that are marked GUC_LIST_QUOTE were already fully
3033  * quoted by flatten_set_variable_args() before they were put
3034  * into the proconfig array. However, because the quoting
3035  * rules used there aren't exactly like SQL's, we have to
3036  * break the list value apart and then quote the elements as
3037  * string literals. (The elements may be double-quoted as-is,
3038  * but we can't just feed them to the SQL parser; it would do
3039  * the wrong thing with elements that are zero-length or
3040  * longer than NAMEDATALEN.)
3041  *
3042  * Variables that are not so marked should just be emitted as
3043  * simple string literals. If the variable is not known to
3044  * guc.c, we'll do that; this makes it unsafe to use
3045  * GUC_LIST_QUOTE for extension variables.
3046  */
3047  if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
3048  {
3049  List *namelist;
3050  ListCell *lc;
3051 
3052  /* Parse string into list of identifiers */
3053  if (!SplitGUCList(pos, ',', &namelist))
3054  {
3055  /* this shouldn't fail really */
3056  elog(ERROR, "invalid list syntax in proconfig item");
3057  }
3058  foreach(lc, namelist)
3059  {
3060  char *curname = (char *) lfirst(lc);
3061 
3062  simple_quote_literal(&buf, curname);
3063  if (lnext(namelist, lc))
3064  appendStringInfoString(&buf, ", ");
3065  }
3066  }
3067  else
3068  simple_quote_literal(&buf, pos);
3069  appendStringInfoChar(&buf, '\n');
3070  }
3071  }
3072  }
3073 
3074  /* And finally the function definition ... */
3075  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3076  if (proc->prolang == SQLlanguageId && !isnull)
3077  {
3078  print_function_sqlbody(&buf, proctup);
3079  }
3080  else
3081  {
3082  appendStringInfoString(&buf, "AS ");
3083 
3084  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
3085  if (!isnull)
3086  {
3088  appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
3089  }
3090 
3091  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
3092  if (isnull)
3093  elog(ERROR, "null prosrc");
3094  prosrc = TextDatumGetCString(tmp);
3095 
3096  /*
3097  * We always use dollar quoting. Figure out a suitable delimiter.
3098  *
3099  * Since the user is likely to be editing the function body string, we
3100  * shouldn't use a short delimiter that he might easily create a
3101  * conflict with. Hence prefer "$function$"/"$procedure$", but extend
3102  * if needed.
3103  */
3104  initStringInfo(&dq);
3105  appendStringInfoChar(&dq, '$');
3106  appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
3107  while (strstr(prosrc, dq.data) != NULL)
3108  appendStringInfoChar(&dq, 'x');
3109  appendStringInfoChar(&dq, '$');
3110 
3111  appendBinaryStringInfo(&buf, dq.data, dq.len);
3112  appendStringInfoString(&buf, prosrc);
3113  appendBinaryStringInfo(&buf, dq.data, dq.len);
3114  }
3115 
3116  appendStringInfoChar(&buf, '\n');
3117 
3118  ReleaseSysCache(proctup);
3119 
3121 }
3122 
3123 /*
3124  * pg_get_function_arguments
3125  * Get a nicely-formatted list of arguments for a function.
3126  * This is everything that would go between the parentheses in
3127  * CREATE FUNCTION.
3128  */
3129 Datum
3131 {
3132  Oid funcid = PG_GETARG_OID(0);
3134  HeapTuple proctup;
3135 
3136  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3137  if (!HeapTupleIsValid(proctup))
3138  PG_RETURN_NULL();
3139 
3140  initStringInfo(&buf);
3141 
3142  (void) print_function_arguments(&buf, proctup, false, true);
3143 
3144  ReleaseSysCache(proctup);
3145 
3147 }
3148 
3149 /*
3150  * pg_get_function_identity_arguments
3151  * Get a formatted list of arguments for a function.
3152  * This is everything that would go between the parentheses in
3153  * ALTER FUNCTION, etc. In particular, don't print defaults.
3154  */
3155 Datum
3157 {
3158  Oid funcid = PG_GETARG_OID(0);
3160  HeapTuple proctup;
3161 
3162  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3163  if (!HeapTupleIsValid(proctup))
3164  PG_RETURN_NULL();
3165 
3166  initStringInfo(&buf);
3167 
3168  (void) print_function_arguments(&buf, proctup, false, false);
3169 
3170  ReleaseSysCache(proctup);
3171 
3173 }
3174 
3175 /*
3176  * pg_get_function_result
3177  * Get a nicely-formatted version of the result type of a function.
3178  * This is what would appear after RETURNS in CREATE FUNCTION.
3179  */
3180 Datum
3182 {
3183  Oid funcid = PG_GETARG_OID(0);
3185  HeapTuple proctup;
3186 
3187  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3188  if (!HeapTupleIsValid(proctup))
3189  PG_RETURN_NULL();
3190 
3191  if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
3192  {
3193  ReleaseSysCache(proctup);
3194  PG_RETURN_NULL();
3195  }
3196 
3197  initStringInfo(&buf);
3198 
3199  print_function_rettype(&buf, proctup);
3200 
3201  ReleaseSysCache(proctup);
3202 
3204 }
3205 
3206 /*
3207  * Guts of pg_get_function_result: append the function's return type
3208  * to the specified buffer.
3209  */
3210 static void
3212 {
3213  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3214  int ntabargs = 0;
3215  StringInfoData rbuf;
3216 
3217  initStringInfo(&rbuf);
3218 
3219  if (proc->proretset)
3220  {
3221  /* It might be a table function; try to print the arguments */
3222  appendStringInfoString(&rbuf, "TABLE(");
3223  ntabargs = print_function_arguments(&rbuf, proctup, true, false);
3224  if (ntabargs > 0)
3225  appendStringInfoChar(&rbuf, ')');
3226  else
3227  resetStringInfo(&rbuf);
3228  }
3229 
3230  if (ntabargs == 0)
3231  {
3232  /* Not a table function, so do the normal thing */
3233  if (proc->proretset)
3234  appendStringInfoString(&rbuf, "SETOF ");
3235  appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
3236  }
3237 
3238  appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
3239 }
3240 
3241 /*
3242  * Common code for pg_get_function_arguments and pg_get_function_result:
3243  * append the desired subset of arguments to buf. We print only TABLE
3244  * arguments when print_table_args is true, and all the others when it's false.
3245  * We print argument defaults only if print_defaults is true.
3246  * Function return value is the number of arguments printed.
3247  */
3248 static int
3250  bool print_table_args, bool print_defaults)
3251 {
3252  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3253  int numargs;
3254  Oid *argtypes;
3255  char **argnames;
3256  char *argmodes;
3257  int insertorderbyat = -1;
3258  int argsprinted;
3259  int inputargno;
3260  int nlackdefaults;
3261  List *argdefaults = NIL;
3262  ListCell *nextargdefault = NULL;
3263  int i;
3264 
3265  numargs = get_func_arg_info(proctup,
3266  &argtypes, &argnames, &argmodes);
3267 
3268  nlackdefaults = numargs;
3269  if (print_defaults && proc->pronargdefaults > 0)
3270  {
3271  Datum proargdefaults;
3272  bool isnull;
3273 
3274  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3275  Anum_pg_proc_proargdefaults,
3276  &isnull);
3277  if (!isnull)
3278  {
3279  char *str;
3280 
3281  str = TextDatumGetCString(proargdefaults);
3282  argdefaults = castNode(List, stringToNode(str));
3283  pfree(str);
3284  nextargdefault = list_head(argdefaults);
3285  /* nlackdefaults counts only *input* arguments lacking defaults */
3286  nlackdefaults = proc->pronargs - list_length(argdefaults);
3287  }
3288  }
3289 
3290  /* Check for special treatment of ordered-set aggregates */
3291  if (proc->prokind == PROKIND_AGGREGATE)
3292  {
3293  HeapTuple aggtup;
3294  Form_pg_aggregate agg;
3295 
3296  aggtup = SearchSysCache1(AGGFNOID, proc->oid);
3297  if (!HeapTupleIsValid(aggtup))
3298  elog(ERROR, "cache lookup failed for aggregate %u",
3299  proc->oid);
3300  agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3301  if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3302  insertorderbyat = agg->aggnumdirectargs;
3303  ReleaseSysCache(aggtup);
3304  }
3305 
3306  argsprinted = 0;
3307  inputargno = 0;
3308  for (i = 0; i < numargs; i++)
3309  {
3310  Oid argtype = argtypes[i];
3311  char *argname = argnames ? argnames[i] : NULL;
3312  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3313  const char *modename;
3314  bool isinput;
3315 
3316  switch (argmode)
3317  {
3318  case PROARGMODE_IN:
3319 
3320  /*
3321  * For procedures, explicitly mark all argument modes, so as
3322  * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
3323  */
3324  if (proc->prokind == PROKIND_PROCEDURE)
3325  modename = "IN ";
3326  else
3327  modename = "";
3328  isinput = true;
3329  break;
3330  case PROARGMODE_INOUT:
3331  modename = "INOUT ";
3332  isinput = true;
3333  break;
3334  case PROARGMODE_OUT:
3335  modename = "OUT ";
3336  isinput = false;
3337  break;
3338  case PROARGMODE_VARIADIC:
3339  modename = "VARIADIC ";
3340  isinput = true;
3341  break;
3342  case PROARGMODE_TABLE:
3343  modename = "";
3344  isinput = false;
3345  break;
3346  default:
3347  elog(ERROR, "invalid parameter mode '%c'", argmode);
3348  modename = NULL; /* keep compiler quiet */
3349  isinput = false;
3350  break;
3351  }
3352  if (isinput)
3353  inputargno++; /* this is a 1-based counter */
3354 
3355  if (print_table_args != (argmode == PROARGMODE_TABLE))
3356  continue;
3357 
3358  if (argsprinted == insertorderbyat)
3359  {
3360  if (argsprinted)
3361  appendStringInfoChar(buf, ' ');
3362  appendStringInfoString(buf, "ORDER BY ");
3363  }
3364  else if (argsprinted)
3365  appendStringInfoString(buf, ", ");
3366 
3367  appendStringInfoString(buf, modename);
3368  if (argname && argname[0])
3369  appendStringInfo(buf, "%s ", quote_identifier(argname));
3371  if (print_defaults && isinput && inputargno > nlackdefaults)
3372  {
3373  Node *expr;
3374 
3375  Assert(nextargdefault != NULL);
3376  expr = (Node *) lfirst(nextargdefault);
3377  nextargdefault = lnext(argdefaults, nextargdefault);
3378 
3379  appendStringInfo(buf, " DEFAULT %s",
3380  deparse_expression(expr, NIL, false, false));
3381  }
3382  argsprinted++;
3383 
3384  /* nasty hack: print the last arg twice for variadic ordered-set agg */
3385  if (argsprinted == insertorderbyat && i == numargs - 1)
3386  {
3387  i--;
3388  /* aggs shouldn't have defaults anyway, but just to be sure ... */
3389  print_defaults = false;
3390  }
3391  }
3392 
3393  return argsprinted;
3394 }
3395 
3396 static bool
3397 is_input_argument(int nth, const char *argmodes)
3398 {
3399  return (!argmodes
3400  || argmodes[nth] == PROARGMODE_IN
3401  || argmodes[nth] == PROARGMODE_INOUT
3402  || argmodes[nth] == PROARGMODE_VARIADIC);
3403 }
3404 
3405 /*
3406  * Append used transformed types to specified buffer
3407  */
3408 static void
3410 {
3411  Oid *trftypes;
3412  int ntypes;
3413 
3414  ntypes = get_func_trftypes(proctup, &trftypes);
3415  if (ntypes > 0)
3416  {
3417  int i;
3418 
3419  appendStringInfoString(buf, " TRANSFORM ");
3420  for (i = 0; i < ntypes; i++)
3421  {
3422  if (i != 0)
3423  appendStringInfoString(buf, ", ");
3424  appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3425  }
3426  appendStringInfoChar(buf, '\n');
3427  }
3428 }
3429 
3430 /*
3431  * Get textual representation of a function argument's default value. The
3432  * second argument of this function is the argument number among all arguments
3433  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3434  * how information_schema.sql uses it.
3435  */
3436 Datum
3438 {
3439  Oid funcid = PG_GETARG_OID(0);
3440  int32 nth_arg = PG_GETARG_INT32(1);
3441  HeapTuple proctup;
3442  Form_pg_proc proc;
3443  int numargs;
3444  Oid *argtypes;
3445  char **argnames;
3446  char *argmodes;
3447  int i;
3448  List *argdefaults;
3449  Node *node;
3450  char *str;
3451  int nth_inputarg;
3452  Datum proargdefaults;
3453  bool isnull;
3454  int nth_default;
3455 
3456  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3457  if (!HeapTupleIsValid(proctup))
3458  PG_RETURN_NULL();
3459 
3460  numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3461  if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3462  {
3463  ReleaseSysCache(proctup);
3464  PG_RETURN_NULL();
3465  }
3466 
3467  nth_inputarg = 0;
3468  for (i = 0; i < nth_arg; i++)
3469  if (is_input_argument(i, argmodes))
3470  nth_inputarg++;
3471 
3472  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3473  Anum_pg_proc_proargdefaults,
3474  &isnull);
3475  if (isnull)
3476  {
3477  ReleaseSysCache(proctup);
3478  PG_RETURN_NULL();
3479  }
3480 
3481  str = TextDatumGetCString(proargdefaults);
3482  argdefaults = castNode(List, stringToNode(str));
3483  pfree(str);
3484 
3485  proc = (Form_pg_proc) GETSTRUCT(proctup);
3486 
3487  /*
3488  * Calculate index into proargdefaults: proargdefaults corresponds to the
3489  * last N input arguments, where N = pronargdefaults.
3490  */
3491  nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3492 
3493  if (nth_default < 0 || nth_default >= list_length(argdefaults))
3494  {
3495  ReleaseSysCache(proctup);
3496  PG_RETURN_NULL();
3497  }
3498  node = list_nth(argdefaults, nth_default);
3499  str = deparse_expression(node, NIL, false, false);
3500 
3501  ReleaseSysCache(proctup);
3502 
3504 }
3505 
3506 static void
3508 {
3509  int numargs;
3510  Oid *argtypes;
3511  char **argnames;
3512  char *argmodes;
3513  deparse_namespace dpns = {0};
3514  Datum tmp;
3515  bool isnull;
3516  Node *n;
3517 
3518  dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
3519  numargs = get_func_arg_info(proctup,
3520  &argtypes, &argnames, &argmodes);
3521  dpns.numargs = numargs;
3522  dpns.argnames = argnames;
3523 
3524  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3525  Assert(!isnull);
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 {
3630  deparse_context context;
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 */
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 *
4942 get_rtable_name(int rtindex, deparse_context *context)
4943 {
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, make the inner tlist point to the merge source tlist, which
4991  * is same as the targetlist that the ModifyTable's source plan provides.
4992  * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
4993  * excluded expression's tlist. (Similar to the SubqueryScan we don't want
4994  * to reuse OUTER, it's used for RETURNING in some modify table cases,
4995  * although not INSERT .. CONFLICT).
4996  */
4997  if (IsA(plan, SubqueryScan))
4998  dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
4999  else if (IsA(plan, CteScan))
5000  dpns->inner_plan = list_nth(dpns->subplans,
5001  ((CteScan *) plan)->ctePlanId - 1);
5002  else if (IsA(plan, WorkTableScan))
5003  dpns->inner_plan = find_recursive_union(dpns,
5004  (WorkTableScan *) plan);
5005  else if (IsA(plan, ModifyTable))
5006  dpns->inner_plan = plan;
5007  else
5008  dpns->inner_plan = innerPlan(plan);
5009 
5010  if (IsA(plan, ModifyTable))
5011  {
5012  if (((ModifyTable *) plan)->operation == CMD_MERGE)
5013  dpns->inner_tlist = dpns->outer_tlist;
5014  else
5015  dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
5016  }
5017  else if (dpns->inner_plan)
5018  dpns->inner_tlist = dpns->inner_plan->targetlist;
5019  else
5020  dpns->inner_tlist = NIL;
5021 
5022  /* Set up referent for INDEX_VAR Vars, if needed */
5023  if (IsA(plan, IndexOnlyScan))
5024  dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
5025  else if (IsA(plan, ForeignScan))
5026  dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
5027  else if (IsA(plan, CustomScan))
5028  dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
5029  else
5030  dpns->index_tlist = NIL;
5031 }
5032 
5033 /*
5034  * Locate the ancestor plan node that is the RecursiveUnion generating
5035  * the WorkTableScan's work table. We can match on wtParam, since that
5036  * should be unique within the plan tree.
5037  */
5038 static Plan *
5040 {
5041  ListCell *lc;
5042 
5043  foreach(lc, dpns->ancestors)
5044  {
5045  Plan *ancestor = (Plan *) lfirst(lc);
5046 
5047  if (IsA(ancestor, RecursiveUnion) &&
5048  ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
5049  return ancestor;
5050  }
5051  elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
5052  wtscan->wtParam);
5053  return NULL;
5054 }
5055 
5056 /*
5057  * push_child_plan: temporarily transfer deparsing attention to a child plan
5058  *
5059  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
5060  * deparse context in case the referenced expression itself uses
5061  * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
5062  * affecting levelsup issues (although in a Plan tree there really shouldn't
5063  * be any).
5064  *
5065  * Caller must provide a local deparse_namespace variable to save the
5066  * previous state for pop_child_plan.
5067  */
5068 static void
5070  deparse_namespace *save_dpns)
5071 {
5072  /* Save state for restoration later */
5073  *save_dpns = *dpns;
5074 
5075  /* Link current plan node into ancestors list */
5076  dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
5077 
5078  /* Set attention on selected child */
5079  set_deparse_plan(dpns, plan);
5080 }
5081 
5082 /*
5083  * pop_child_plan: undo the effects of push_child_plan
5084  */
5085 static void
5087 {
5088  List *ancestors;
5089 
5090  /* Get rid of ancestors list cell added by push_child_plan */
5091  ancestors = list_delete_first(dpns->ancestors);
5092 
5093  /* Restore fields changed by push_child_plan */
5094  *dpns = *save_dpns;
5095 
5096  /* Make sure dpns->ancestors is right (may be unnecessary) */
5097  dpns->ancestors = ancestors;
5098 }
5099 
5100 /*
5101  * push_ancestor_plan: temporarily transfer deparsing attention to an
5102  * ancestor plan
5103  *
5104  * When expanding a Param reference, we must adjust the deparse context
5105  * to match the plan node that contains the expression being printed;
5106  * otherwise we'd fail if that expression itself contains a Param or
5107  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
5108  *
5109  * The target ancestor is conveniently identified by the ListCell holding it
5110  * in dpns->ancestors.
5111  *
5112  * Caller must provide a local deparse_namespace variable to save the
5113  * previous state for pop_ancestor_plan.
5114  */
5115 static void
5117  deparse_namespace *save_dpns)
5118 {
5119  Plan *plan = (Plan *) lfirst(ancestor_cell);
5120 
5121  /* Save state for restoration later */
5122  *save_dpns = *dpns;
5123 
5124  /* Build a new ancestor list with just this node's ancestors */
5125  dpns->ancestors =
5126  list_copy_tail(dpns->ancestors,
5127  list_cell_number(dpns->ancestors, ancestor_cell) + 1);
5128 
5129  /* Set attention on selected ancestor */
5130  set_deparse_plan(dpns, plan);
5131 }
5132 
5133 /*
5134  * pop_ancestor_plan: undo the effects of push_ancestor_plan
5135  */
5136 static void
5138 {
5139  /* Free the ancestor list made in push_ancestor_plan */
5140  list_free(dpns->ancestors);
5141 
5142  /* Restore fields changed by push_ancestor_plan */
5143  *dpns = *save_dpns;
5144 }
5145 
5146 
5147 /* ----------
5148  * make_ruledef - reconstruct the CREATE RULE command
5149  * for a given pg_rewrite tuple
5150  * ----------
5151  */
5152 static void
5154  int prettyFlags)
5155 {
5156  char *rulename;
5157  char ev_type;
5158  Oid ev_class;
5159  bool is_instead;
5160  char *ev_qual;
5161  char *ev_action;
5162  List *actions;
5163  Relation ev_relation;
5164  TupleDesc viewResultDesc = NULL;
5165  int fno;
5166  Datum dat;
5167  bool isnull;
5168 
5169  /*
5170  * Get the attribute values from the rules tuple
5171  */
5172  fno = SPI_fnumber(rulettc, "rulename");
5173  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5174  Assert(!isnull);
5175  rulename = NameStr(*(DatumGetName(dat)));
5176 
5177  fno = SPI_fnumber(rulettc, "ev_type");
5178  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5179  Assert(!isnull);
5180  ev_type = DatumGetChar(dat);
5181 
5182  fno = SPI_fnumber(rulettc, "ev_class");
5183  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5184  Assert(!isnull);
5185  ev_class = DatumGetObjectId(dat);
5186 
5187  fno = SPI_fnumber(rulettc, "is_instead");
5188  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5189  Assert(!isnull);
5190  is_instead = DatumGetBool(dat);
5191 
5192  fno = SPI_fnumber(rulettc, "ev_qual");
5193  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5194  Assert(ev_qual != NULL);
5195 
5196  fno = SPI_fnumber(rulettc, "ev_action");
5197  ev_action = SPI_getvalue(ruletup, rulettc, fno);
5198  Assert(ev_action != NULL);
5199  actions = (List *) stringToNode(ev_action);
5200  if (actions == NIL)
5201  elog(ERROR, "invalid empty ev_action list");
5202 
5203  ev_relation = table_open(ev_class, AccessShareLock);
5204 
5205  /*
5206  * Build the rules definition text
5207  */
5208  appendStringInfo(buf, "CREATE RULE %s AS",
5209  quote_identifier(rulename));
5210 
5211  if (prettyFlags & PRETTYFLAG_INDENT)
5212  appendStringInfoString(buf, "\n ON ");
5213  else
5214  appendStringInfoString(buf, " ON ");
5215 
5216  /* The event the rule is fired for */
5217  switch (ev_type)
5218  {
5219  case '1':
5220  appendStringInfoString(buf, "SELECT");
5221  viewResultDesc = RelationGetDescr(ev_relation);
5222  break;
5223 
5224  case '2':
5225  appendStringInfoString(buf, "UPDATE");
5226  break;
5227 
5228  case '3':
5229  appendStringInfoString(buf, "INSERT");
5230  break;
5231 
5232  case '4':
5233  appendStringInfoString(buf, "DELETE");
5234  break;
5235 
5236  default:
5237  ereport(ERROR,
5238  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5239  errmsg("rule \"%s\" has unsupported event type %d",
5240  rulename, ev_type)));
5241  break;
5242  }
5243 
5244  /* The relation the rule is fired on */
5245  appendStringInfo(buf, " TO %s",
5246  (prettyFlags & PRETTYFLAG_SCHEMA) ?
5247  generate_relation_name(ev_class, NIL) :
5249 
5250  /* If the rule has an event qualification, add it */
5251  if (strcmp(ev_qual, "<>") != 0)
5252  {
5253  Node *qual;
5254  Query *query;
5255  deparse_context context;
5256  deparse_namespace dpns;
5257 
5258  if (prettyFlags & PRETTYFLAG_INDENT)
5259  appendStringInfoString(buf, "\n ");
5260  appendStringInfoString(buf, " WHERE ");
5261 
5262  qual = stringToNode(ev_qual);
5263 
5264  /*
5265  * We need to make a context for recognizing any Vars in the qual
5266  * (which can only be references to OLD and NEW). Use the rtable of
5267  * the first query in the action list for this purpose.
5268  */
5269  query = (Query *) linitial(actions);
5270 
5271  /*
5272  * If the action is INSERT...SELECT, OLD/NEW have been pushed down
5273  * into the SELECT, and that's what we need to look at. (Ugly kluge
5274  * ... try to fix this when we redesign querytrees.)
5275  */
5276  query = getInsertSelectQuery(query, NULL);
5277 
5278  /* Must acquire locks right away; see notes in get_query_def() */
5279  AcquireRewriteLocks(query, false, false);
5280 
5281  context.buf = buf;
5282  context.namespaces = list_make1(&dpns);
5283  context.windowClause = NIL;
5284  context.windowTList = NIL;
5285  context.varprefix = (list_length(query->rtable) != 1);
5286  context.prettyFlags = prettyFlags;
5287  context.wrapColumn = WRAP_COLUMN_DEFAULT;
5288  context.indentLevel = PRETTYINDENT_STD;
5289  context.special_exprkind = EXPR_KIND_NONE;
5290  context.appendparents = NULL;
5291 
5292  set_deparse_for_query(&dpns, query, NIL);
5293 
5294  get_rule_expr(qual, &context, false);
5295  }
5296 
5297  appendStringInfoString(buf, " DO ");
5298 
5299  /* The INSTEAD keyword (if so) */
5300  if (is_instead)
5301  appendStringInfoString(buf, "INSTEAD ");
5302 
5303  /* Finally the rules actions */
5304  if (list_length(actions) > 1)
5305  {
5306  ListCell *action;
5307  Query *query;
5308 
5309  appendStringInfoChar(buf, '(');
5310  foreach(action, actions)
5311  {
5312  query = (Query *) lfirst(action);
5313  get_query_def(query, buf, NIL, viewResultDesc, true,
5314  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5315  if (prettyFlags)
5316  appendStringInfoString(buf, ";\n");
5317  else
5318  appendStringInfoString(buf, "; ");
5319  }
5320  appendStringInfoString(buf, ");");
5321  }
5322  else
5323  {
5324  Query *query;
5325 
5326  query = (Query *) linitial(actions);
5327  get_query_def(query, buf, NIL, viewResultDesc, true,
5328  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5329  appendStringInfoChar(buf, ';');
5330  }
5331 
5332  table_close(ev_relation, AccessShareLock);
5333 }
5334 
5335 
5336 /* ----------
5337  * make_viewdef - reconstruct the SELECT part of a
5338  * view rewrite rule
5339  * ----------
5340  */
5341 static void
5343  int prettyFlags, int wrapColumn)
5344 {
5345  Query *query;
5346  char ev_type;
5347  Oid ev_class;
5348  bool is_instead;
5349  char *ev_qual;
5350  char *ev_action;
5351  List *actions;
5352  Relation ev_relation;
5353  int fno;
5354  Datum dat;
5355  bool isnull;
5356 
5357  /*
5358  * Get the attribute values from the rules tuple
5359  */
5360  fno = SPI_fnumber(rulettc, "ev_type");
5361  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5362  Assert(!isnull);
5363  ev_type = DatumGetChar(dat);
5364 
5365  fno = SPI_fnumber(rulettc, "ev_class");
5366  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5367  Assert(!isnull);
5368  ev_class = DatumGetObjectId(dat);
5369 
5370  fno = SPI_fnumber(rulettc, "is_instead");
5371  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5372  Assert(!isnull);
5373  is_instead = DatumGetBool(dat);
5374 
5375  fno = SPI_fnumber(rulettc, "ev_qual");
5376  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5377  Assert(ev_qual != NULL);
5378 
5379  fno = SPI_fnumber(rulettc, "ev_action");
5380  ev_action = SPI_getvalue(ruletup, rulettc, fno);
5381  Assert(ev_action != NULL);
5382  actions = (List *) stringToNode(ev_action);
5383 
5384  if (list_length(actions) != 1)
5385  {
5386  /* keep output buffer empty and leave */
5387  return;
5388  }
5389 
5390  query = (Query *) linitial(actions);
5391 
5392  if (ev_type != '1' || !is_instead ||
5393  strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
5394  {
5395  /* keep output buffer empty and leave */
5396  return;
5397  }
5398 
5399  ev_relation = table_open(ev_class, AccessShareLock);
5400 
5401  get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
5402  prettyFlags, wrapColumn, 0);
5403  appendStringInfoChar(buf, ';');
5404 
5405  table_close(ev_relation, AccessShareLock);
5406 }
5407 
5408 
5409 /* ----------
5410  * get_query_def - Parse back one query parsetree
5411  *
5412  * query: parsetree to be displayed
5413  * buf: output text is appended to buf
5414  * parentnamespace: list (initially empty) of outer-level deparse_namespace's
5415  * resultDesc: if not NULL, the output tuple descriptor for the view
5416  * represented by a SELECT query. We use the column names from it
5417  * to label SELECT output columns, in preference to names in the query
5418  * colNamesVisible: true if the surrounding context cares about the output
5419  * column names at all (as, for example, an EXISTS() context does not);
5420  * when false, we can suppress dummy column labels such as "?column?"
5421  * prettyFlags: bitmask of PRETTYFLAG_XXX options
5422  * wrapColumn: maximum line length, or -1 to disable wrapping
5423  * startIndent: initial indentation amount
5424  * ----------
5425  */
5426 static void
5427 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
5428  TupleDesc resultDesc, bool colNamesVisible,
5429  int prettyFlags, int wrapColumn, int startIndent)
5430 {
5431  deparse_context context;
5432  deparse_namespace dpns;
5433 
5434  /* Guard against excessively long or deeply-nested queries */
5437 
5438  /*
5439  * Before we begin to examine the query, acquire locks on referenced
5440  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5441  * consistent results. Note we assume it's OK to scribble on the passed
5442  * querytree!
5443  *
5444  * We are only deparsing the query (we are not about to execute it), so we
5445  * only need AccessShareLock on the relations it mentions.
5446  */
5447  AcquireRewriteLocks(query, false, false);
5448 
5449  context.buf = buf;
5450  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5451  context.windowClause = NIL;
5452  context.windowTList = NIL;
5453  context.varprefix = (parentnamespace != NIL ||
5454  list_length(query->rtable) != 1);
5455  context.prettyFlags = prettyFlags;
5456  context.wrapColumn = wrapColumn;
5457  context.indentLevel = startIndent;
5458  context.special_exprkind = EXPR_KIND_NONE;
5459  context.appendparents = NULL;
5460 
5461  set_deparse_for_query(&dpns, query, parentnamespace);
5462 
5463  switch (query->commandType)
5464  {
5465  case CMD_SELECT:
5466  get_select_query_def(query, &context, resultDesc, colNamesVisible);
5467  break;
5468 
5469  case CMD_UPDATE:
5470  get_update_query_def(query, &context, colNamesVisible);
5471  break;
5472 
5473  case CMD_INSERT:
5474  get_insert_query_def(query, &context, colNamesVisible);
5475  break;
5476 
5477  case CMD_DELETE:
5478  get_delete_query_def(query, &context, colNamesVisible);
5479  break;
5480 
5481  case CMD_NOTHING:
5482  appendStringInfoString(buf, "NOTHING");
5483  break;
5484 
5485  case CMD_UTILITY:
5486  get_utility_query_def(query, &context);
5487  break;
5488 
5489  default:
5490  elog(ERROR, "unrecognized query command type: %d",
5491  query->commandType);
5492  break;
5493  }
5494 }
5495 
5496 /* ----------
5497  * get_values_def - Parse back a VALUES list
5498  * ----------
5499  */
5500 static void
5501 get_values_def(List *values_lists, deparse_context *context)
5502 {
5503  StringInfo buf = context->buf;
5504  bool first_list = true;