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