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