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