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