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  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  decompile_column_index_array(val, conForm->conrelid, &buf);
2274 
2275  /* add foreign relation name */
2276  appendStringInfo(&buf, ") REFERENCES %s(",
2277  generate_relation_name(conForm->confrelid,
2278  NIL));
2279 
2280  /* Fetch and build referenced-column list */
2281  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2282  Anum_pg_constraint_confkey);
2283 
2284  decompile_column_index_array(val, conForm->confrelid, &buf);
2285 
2286  appendStringInfoChar(&buf, ')');
2287 
2288  /* Add match type */
2289  switch (conForm->confmatchtype)
2290  {
2291  case FKCONSTR_MATCH_FULL:
2292  string = " MATCH FULL";
2293  break;
2295  string = " MATCH PARTIAL";
2296  break;
2297  case FKCONSTR_MATCH_SIMPLE:
2298  string = "";
2299  break;
2300  default:
2301  elog(ERROR, "unrecognized confmatchtype: %d",
2302  conForm->confmatchtype);
2303  string = ""; /* keep compiler quiet */
2304  break;
2305  }
2306  appendStringInfoString(&buf, string);
2307 
2308  /* Add ON UPDATE and ON DELETE clauses, if needed */
2309  switch (conForm->confupdtype)
2310  {
2312  string = NULL; /* suppress default */
2313  break;
2315  string = "RESTRICT";
2316  break;
2318  string = "CASCADE";
2319  break;
2321  string = "SET NULL";
2322  break;
2324  string = "SET DEFAULT";
2325  break;
2326  default:
2327  elog(ERROR, "unrecognized confupdtype: %d",
2328  conForm->confupdtype);
2329  string = NULL; /* keep compiler quiet */
2330  break;
2331  }
2332  if (string)
2333  appendStringInfo(&buf, " ON UPDATE %s", string);
2334 
2335  switch (conForm->confdeltype)
2336  {
2338  string = NULL; /* suppress default */
2339  break;
2341  string = "RESTRICT";
2342  break;
2344  string = "CASCADE";
2345  break;
2347  string = "SET NULL";
2348  break;
2350  string = "SET DEFAULT";
2351  break;
2352  default:
2353  elog(ERROR, "unrecognized confdeltype: %d",
2354  conForm->confdeltype);
2355  string = NULL; /* keep compiler quiet */
2356  break;
2357  }
2358  if (string)
2359  appendStringInfo(&buf, " ON DELETE %s", string);
2360 
2361  /*
2362  * Add columns specified to SET NULL or SET DEFAULT if
2363  * provided.
2364  */
2365  val = SysCacheGetAttr(CONSTROID, tup,
2366  Anum_pg_constraint_confdelsetcols, &isnull);
2367  if (!isnull)
2368  {
2369  appendStringInfoString(&buf, " (");
2370  decompile_column_index_array(val, conForm->conrelid, &buf);
2371  appendStringInfoChar(&buf, ')');
2372  }
2373 
2374  break;
2375  }
2376  case CONSTRAINT_PRIMARY:
2377  case CONSTRAINT_UNIQUE:
2378  {
2379  Datum val;
2380  Oid indexId;
2381  int keyatts;
2382  HeapTuple indtup;
2383 
2384  /* Start off the constraint definition */
2385  if (conForm->contype == CONSTRAINT_PRIMARY)
2386  appendStringInfoString(&buf, "PRIMARY KEY ");
2387  else
2388  appendStringInfoString(&buf, "UNIQUE ");
2389 
2390  indexId = conForm->conindid;
2391 
2392  indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2393  if (!HeapTupleIsValid(indtup))
2394  elog(ERROR, "cache lookup failed for index %u", indexId);
2395  if (conForm->contype == CONSTRAINT_UNIQUE &&
2396  ((Form_pg_index) GETSTRUCT(indtup))->indnullsnotdistinct)
2397  appendStringInfoString(&buf, "NULLS NOT DISTINCT ");
2398 
2399  appendStringInfoChar(&buf, '(');
2400 
2401  /* Fetch and build target column list */
2402  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2403  Anum_pg_constraint_conkey);
2404 
2405  keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2406 
2407  appendStringInfoChar(&buf, ')');
2408 
2409  /* Build including column list (from pg_index.indkeys) */
2410  val = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2411  Anum_pg_index_indnatts);
2412  if (DatumGetInt32(val) > keyatts)
2413  {
2414  Datum cols;
2415  Datum *keys;
2416  int nKeys;
2417  int j;
2418 
2419  appendStringInfoString(&buf, " INCLUDE (");
2420 
2421  cols = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2422  Anum_pg_index_indkey);
2423 
2425  &keys, NULL, &nKeys);
2426 
2427  for (j = keyatts; j < nKeys; j++)
2428  {
2429  char *colName;
2430 
2431  colName = get_attname(conForm->conrelid,
2432  DatumGetInt16(keys[j]), false);
2433  if (j > keyatts)
2434  appendStringInfoString(&buf, ", ");
2436  }
2437 
2438  appendStringInfoChar(&buf, ')');
2439  }
2440  ReleaseSysCache(indtup);
2441 
2442  /* XXX why do we only print these bits if fullCommand? */
2443  if (fullCommand && OidIsValid(indexId))
2444  {
2445  char *options = flatten_reloptions(indexId);
2446  Oid tblspc;
2447 
2448  if (options)
2449  {
2450  appendStringInfo(&buf, " WITH (%s)", options);
2451  pfree(options);
2452  }
2453 
2454  /*
2455  * Print the tablespace, unless it's the database default.
2456  * This is to help ALTER TABLE usage of this facility,
2457  * which needs this behavior to recreate exact catalog
2458  * state.
2459  */
2460  tblspc = get_rel_tablespace(indexId);
2461  if (OidIsValid(tblspc))
2462  appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2464  }
2465 
2466  break;
2467  }
2468  case CONSTRAINT_CHECK:
2469  {
2470  Datum val;
2471  char *conbin;
2472  char *consrc;
2473  Node *expr;
2474  List *context;
2475 
2476  /* Fetch constraint expression in parsetree form */
2477  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2478  Anum_pg_constraint_conbin);
2479 
2480  conbin = TextDatumGetCString(val);
2481  expr = stringToNode(conbin);
2482 
2483  /* Set up deparsing context for Var nodes in constraint */
2484  if (conForm->conrelid != InvalidOid)
2485  {
2486  /* relation constraint */
2487  context = deparse_context_for(get_relation_name(conForm->conrelid),
2488  conForm->conrelid);
2489  }
2490  else
2491  {
2492  /* domain constraint --- can't have Vars */
2493  context = NIL;
2494  }
2495 
2496  consrc = deparse_expression_pretty(expr, context, false, false,
2497  prettyFlags, 0);
2498 
2499  /*
2500  * Now emit the constraint definition, adding NO INHERIT if
2501  * necessary.
2502  *
2503  * There are cases where the constraint expression will be
2504  * fully parenthesized and we don't need the outer parens ...
2505  * but there are other cases where we do need 'em. Be
2506  * conservative for now.
2507  *
2508  * Note that simply checking for leading '(' and trailing ')'
2509  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2510  */
2511  appendStringInfo(&buf, "CHECK (%s)%s",
2512  consrc,
2513  conForm->connoinherit ? " NO INHERIT" : "");
2514  break;
2515  }
2516  case CONSTRAINT_TRIGGER:
2517 
2518  /*
2519  * There isn't an ALTER TABLE syntax for creating a user-defined
2520  * constraint trigger, but it seems better to print something than
2521  * throw an error; if we throw error then this function couldn't
2522  * safely be applied to all rows of pg_constraint.
2523  */
2524  appendStringInfoString(&buf, "TRIGGER");
2525  break;
2526  case CONSTRAINT_EXCLUSION:
2527  {
2528  Oid indexOid = conForm->conindid;
2529  Datum val;
2530  Datum *elems;
2531  int nElems;
2532  int i;
2533  Oid *operators;
2534 
2535  /* Extract operator OIDs from the pg_constraint tuple */
2536  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2537  Anum_pg_constraint_conexclop);
2538 
2540  &elems, NULL, &nElems);
2541 
2542  operators = (Oid *) palloc(nElems * sizeof(Oid));
2543  for (i = 0; i < nElems; i++)
2544  operators[i] = DatumGetObjectId(elems[i]);
2545 
2546  /* pg_get_indexdef_worker does the rest */
2547  /* suppress tablespace because pg_dump wants it that way */
2549  pg_get_indexdef_worker(indexOid,
2550  0,
2551  operators,
2552  false,
2553  false,
2554  false,
2555  false,
2556  prettyFlags,
2557  false));
2558  break;
2559  }
2560  default:
2561  elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2562  break;
2563  }
2564 
2565  if (conForm->condeferrable)
2566  appendStringInfoString(&buf, " DEFERRABLE");
2567  if (conForm->condeferred)
2568  appendStringInfoString(&buf, " INITIALLY DEFERRED");
2569  if (!conForm->convalidated)
2570  appendStringInfoString(&buf, " NOT VALID");
2571 
2572  /* Cleanup */
2573  systable_endscan(scandesc);
2574  table_close(relation, AccessShareLock);
2575 
2576  return buf.data;
2577 }
2578 
2579 
2580 /*
2581  * Convert an int16[] Datum into a comma-separated list of column names
2582  * for the indicated relation; append the list to buf. Returns the number
2583  * of keys.
2584  */
2585 static int
2586 decompile_column_index_array(Datum column_index_array, Oid relId,
2587  StringInfo buf)
2588 {
2589  Datum *keys;
2590  int nKeys;
2591  int j;
2592 
2593  /* Extract data from array of int16 */
2594  deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID,
2595  &keys, NULL, &nKeys);
2596 
2597  for (j = 0; j < nKeys; j++)
2598  {
2599  char *colName;
2600 
2601  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2602 
2603  if (j == 0)
2605  else
2606  appendStringInfo(buf, ", %s", quote_identifier(colName));
2607  }
2608 
2609  return nKeys;
2610 }
2611 
2612 
2613 /* ----------
2614  * pg_get_expr - Decompile an expression tree
2615  *
2616  * Input: an expression tree in nodeToString form, and a relation OID
2617  *
2618  * Output: reverse-listed expression
2619  *
2620  * Currently, the expression can only refer to a single relation, namely
2621  * the one specified by the second parameter. This is sufficient for
2622  * partial indexes, column default expressions, etc. We also support
2623  * Var-free expressions, for which the OID can be InvalidOid.
2624  *
2625  * If the OID is nonzero but not actually valid, don't throw an error,
2626  * just return NULL. This is a bit questionable, but it's what we've
2627  * done historically, and it can help avoid unwanted failures when
2628  * examining catalog entries for just-deleted relations.
2629  *
2630  * We expect this function to work, or throw a reasonably clean error,
2631  * for any node tree that can appear in a catalog pg_node_tree column.
2632  * Query trees, such as those appearing in pg_rewrite.ev_action, are
2633  * not supported. Nor are expressions in more than one relation, which
2634  * can appear in places like pg_rewrite.ev_qual.
2635  * ----------
2636  */
2637 Datum
2639 {
2640  text *expr = PG_GETARG_TEXT_PP(0);
2641  Oid relid = PG_GETARG_OID(1);
2642  text *result;
2643  int prettyFlags;
2644 
2645  prettyFlags = PRETTYFLAG_INDENT;
2646 
2647  result = pg_get_expr_worker(expr, relid, prettyFlags);
2648  if (result)
2649  PG_RETURN_TEXT_P(result);
2650  else
2651  PG_RETURN_NULL();
2652 }
2653 
2654 Datum
2656 {
2657  text *expr = PG_GETARG_TEXT_PP(0);
2658  Oid relid = PG_GETARG_OID(1);
2659  bool pretty = PG_GETARG_BOOL(2);
2660  text *result;
2661  int prettyFlags;
2662 
2663  prettyFlags = GET_PRETTY_FLAGS(pretty);
2664 
2665  result = pg_get_expr_worker(expr, relid, prettyFlags);
2666  if (result)
2667  PG_RETURN_TEXT_P(result);
2668  else
2669  PG_RETURN_NULL();
2670 }
2671 
2672 static text *
2673 pg_get_expr_worker(text *expr, Oid relid, int prettyFlags)
2674 {
2675  Node *node;
2676  Node *tst;
2677  Relids relids;
2678  List *context;
2679  char *exprstr;
2680  Relation rel = NULL;
2681  char *str;
2682 
2683  /* Convert input pg_node_tree (really TEXT) object to C string */
2684  exprstr = text_to_cstring(expr);
2685 
2686  /* Convert expression to node tree */
2687  node = (Node *) stringToNode(exprstr);
2688 
2689  pfree(exprstr);
2690 
2691  /*
2692  * Throw error if the input is a querytree rather than an expression tree.
2693  * While we could support queries here, there seems no very good reason
2694  * to. In most such catalog columns, we'll see a List of Query nodes, or
2695  * even nested Lists, so drill down to a non-List node before checking.
2696  */
2697  tst = node;
2698  while (tst && IsA(tst, List))
2699  tst = linitial((List *) tst);
2700  if (tst && IsA(tst, Query))
2701  ereport(ERROR,
2702  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2703  errmsg("input is a query, not an expression")));
2704 
2705  /*
2706  * Throw error if the expression contains Vars we won't be able to
2707  * deparse.
2708  */
2709  relids = pull_varnos(NULL, node);
2710  if (OidIsValid(relid))
2711  {
2712  if (!bms_is_subset(relids, bms_make_singleton(1)))
2713  ereport(ERROR,
2714  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2715  errmsg("expression contains variables of more than one relation")));
2716  }
2717  else
2718  {
2719  if (!bms_is_empty(relids))
2720  ereport(ERROR,
2721  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2722  errmsg("expression contains variables")));
2723  }
2724 
2725  /*
2726  * Prepare deparse context if needed. If we are deparsing with a relid,
2727  * we need to transiently open and lock the rel, to make sure it won't go
2728  * away underneath us. (set_relation_column_names would lock it anyway,
2729  * so this isn't really introducing any new behavior.)
2730  */
2731  if (OidIsValid(relid))
2732  {
2733  rel = try_relation_open(relid, AccessShareLock);
2734  if (rel == NULL)
2735  return NULL;
2737  }
2738  else
2739  context = NIL;
2740 
2741  /* Deparse */
2742  str = deparse_expression_pretty(node, context, false, false,
2743  prettyFlags, 0);
2744 
2745  if (rel != NULL)
2747 
2748  return string_to_text(str);
2749 }
2750 
2751 
2752 /* ----------
2753  * pg_get_userbyid - Get a user name by roleid and
2754  * fallback to 'unknown (OID=n)'
2755  * ----------
2756  */
2757 Datum
2759 {
2760  Oid roleid = PG_GETARG_OID(0);
2761  Name result;
2762  HeapTuple roletup;
2763  Form_pg_authid role_rec;
2764 
2765  /*
2766  * Allocate space for the result
2767  */
2768  result = (Name) palloc(NAMEDATALEN);
2769  memset(NameStr(*result), 0, NAMEDATALEN);
2770 
2771  /*
2772  * Get the pg_authid entry and print the result
2773  */
2774  roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2775  if (HeapTupleIsValid(roletup))
2776  {
2777  role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2778  *result = role_rec->rolname;
2779  ReleaseSysCache(roletup);
2780  }
2781  else
2782  sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2783 
2784  PG_RETURN_NAME(result);
2785 }
2786 
2787 
2788 /*
2789  * pg_get_serial_sequence
2790  * Get the name of the sequence used by an identity or serial column,
2791  * formatted suitably for passing to setval, nextval or currval.
2792  * First parameter is not treated as double-quoted, second parameter
2793  * is --- see documentation for reason.
2794  */
2795 Datum
2797 {
2798  text *tablename = PG_GETARG_TEXT_PP(0);
2799  text *columnname = PG_GETARG_TEXT_PP(1);
2800  RangeVar *tablerv;
2801  Oid tableOid;
2802  char *column;
2804  Oid sequenceId = InvalidOid;
2805  Relation depRel;
2806  ScanKeyData key[3];
2807  SysScanDesc scan;
2808  HeapTuple tup;
2809 
2810  /* Look up table name. Can't lock it - we might not have privileges. */
2811  tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2812  tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2813 
2814  /* Get the number of the column */
2815  column = text_to_cstring(columnname);
2816 
2817  attnum = get_attnum(tableOid, column);
2818  if (attnum == InvalidAttrNumber)
2819  ereport(ERROR,
2820  (errcode(ERRCODE_UNDEFINED_COLUMN),
2821  errmsg("column \"%s\" of relation \"%s\" does not exist",
2822  column, tablerv->relname)));
2823 
2824  /* Search the dependency table for the dependent sequence */
2825  depRel = table_open(DependRelationId, AccessShareLock);
2826 
2827  ScanKeyInit(&key[0],
2828  Anum_pg_depend_refclassid,
2829  BTEqualStrategyNumber, F_OIDEQ,
2830  ObjectIdGetDatum(RelationRelationId));
2831  ScanKeyInit(&key[1],
2832  Anum_pg_depend_refobjid,
2833  BTEqualStrategyNumber, F_OIDEQ,
2834  ObjectIdGetDatum(tableOid));
2835  ScanKeyInit(&key[2],
2836  Anum_pg_depend_refobjsubid,
2837  BTEqualStrategyNumber, F_INT4EQ,
2839 
2840  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2841  NULL, 3, key);
2842 
2843  while (HeapTupleIsValid(tup = systable_getnext(scan)))
2844  {
2845  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2846 
2847  /*
2848  * Look for an auto dependency (serial column) or internal dependency
2849  * (identity column) of a sequence on a column. (We need the relkind
2850  * test because indexes can also have auto dependencies on columns.)
2851  */
2852  if (deprec->classid == RelationRelationId &&
2853  deprec->objsubid == 0 &&
2854  (deprec->deptype == DEPENDENCY_AUTO ||
2855  deprec->deptype == DEPENDENCY_INTERNAL) &&
2856  get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2857  {
2858  sequenceId = deprec->objid;
2859  break;
2860  }
2861  }
2862 
2863  systable_endscan(scan);
2864  table_close(depRel, AccessShareLock);
2865 
2866  if (OidIsValid(sequenceId))
2867  {
2868  char *result;
2869 
2870  result = generate_qualified_relation_name(sequenceId);
2871 
2873  }
2874 
2875  PG_RETURN_NULL();
2876 }
2877 
2878 
2879 /*
2880  * pg_get_functiondef
2881  * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2882  * the specified function.
2883  *
2884  * Note: if you change the output format of this function, be careful not
2885  * to break psql's rules (in \ef and \sf) for identifying the start of the
2886  * function body. To wit: the function body starts on a line that begins with
2887  * "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
2888  */
2889 Datum
2891 {
2892  Oid funcid = PG_GETARG_OID(0);
2894  StringInfoData dq;
2895  HeapTuple proctup;
2896  Form_pg_proc proc;
2897  bool isfunction;
2898  Datum tmp;
2899  bool isnull;
2900  const char *prosrc;
2901  const char *name;
2902  const char *nsp;
2903  float4 procost;
2904  int oldlen;
2905 
2906  initStringInfo(&buf);
2907 
2908  /* Look up the function */
2909  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2910  if (!HeapTupleIsValid(proctup))
2911  PG_RETURN_NULL();
2912 
2913  proc = (Form_pg_proc) GETSTRUCT(proctup);
2914  name = NameStr(proc->proname);
2915 
2916  if (proc->prokind == PROKIND_AGGREGATE)
2917  ereport(ERROR,
2918  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2919  errmsg("\"%s\" is an aggregate function", name)));
2920 
2921  isfunction = (proc->prokind != PROKIND_PROCEDURE);
2922 
2923  /*
2924  * We always qualify the function name, to ensure the right function gets
2925  * replaced.
2926  */
2927  nsp = get_namespace_name_or_temp(proc->pronamespace);
2928  appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2929  isfunction ? "FUNCTION" : "PROCEDURE",
2931  (void) print_function_arguments(&buf, proctup, false, true);
2932  appendStringInfoString(&buf, ")\n");
2933  if (isfunction)
2934  {
2935  appendStringInfoString(&buf, " RETURNS ");
2936  print_function_rettype(&buf, proctup);
2937  appendStringInfoChar(&buf, '\n');
2938  }
2939 
2940  print_function_trftypes(&buf, proctup);
2941 
2942  appendStringInfo(&buf, " LANGUAGE %s\n",
2943  quote_identifier(get_language_name(proc->prolang, false)));
2944 
2945  /* Emit some miscellaneous options on one line */
2946  oldlen = buf.len;
2947 
2948  if (proc->prokind == PROKIND_WINDOW)
2949  appendStringInfoString(&buf, " WINDOW");
2950  switch (proc->provolatile)
2951  {
2952  case PROVOLATILE_IMMUTABLE:
2953  appendStringInfoString(&buf, " IMMUTABLE");
2954  break;
2955  case PROVOLATILE_STABLE:
2956  appendStringInfoString(&buf, " STABLE");
2957  break;
2958  case PROVOLATILE_VOLATILE:
2959  break;
2960  }
2961 
2962  switch (proc->proparallel)
2963  {
2964  case PROPARALLEL_SAFE:
2965  appendStringInfoString(&buf, " PARALLEL SAFE");
2966  break;
2967  case PROPARALLEL_RESTRICTED:
2968  appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2969  break;
2970  case PROPARALLEL_UNSAFE:
2971  break;
2972  }
2973 
2974  if (proc->proisstrict)
2975  appendStringInfoString(&buf, " STRICT");
2976  if (proc->prosecdef)
2977  appendStringInfoString(&buf, " SECURITY DEFINER");
2978  if (proc->proleakproof)
2979  appendStringInfoString(&buf, " LEAKPROOF");
2980 
2981  /* This code for the default cost and rows should match functioncmds.c */
2982  if (proc->prolang == INTERNALlanguageId ||
2983  proc->prolang == ClanguageId)
2984  procost = 1;
2985  else
2986  procost = 100;
2987  if (proc->procost != procost)
2988  appendStringInfo(&buf, " COST %g", proc->procost);
2989 
2990  if (proc->prorows > 0 && proc->prorows != 1000)
2991  appendStringInfo(&buf, " ROWS %g", proc->prorows);
2992 
2993  if (proc->prosupport)
2994  {
2995  Oid argtypes[1];
2996 
2997  /*
2998  * We should qualify the support function's name if it wouldn't be
2999  * resolved by lookup in the current search path.
3000  */
3001  argtypes[0] = INTERNALOID;
3002  appendStringInfo(&buf, " SUPPORT %s",
3003  generate_function_name(proc->prosupport, 1,
3004  NIL, argtypes,
3005  false, NULL, false));
3006  }
3007 
3008  if (oldlen != buf.len)
3009  appendStringInfoChar(&buf, '\n');
3010 
3011  /* Emit any proconfig options, one per line */
3012  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
3013  if (!isnull)
3014  {
3015  ArrayType *a = DatumGetArrayTypeP(tmp);
3016  int i;
3017 
3018  Assert(ARR_ELEMTYPE(a) == TEXTOID);
3019  Assert(ARR_NDIM(a) == 1);
3020  Assert(ARR_LBOUND(a)[0] == 1);
3021 
3022  for (i = 1; i <= ARR_DIMS(a)[0]; i++)
3023  {
3024  Datum d;
3025 
3026  d = array_ref(a, 1, &i,
3027  -1 /* varlenarray */ ,
3028  -1 /* TEXT's typlen */ ,
3029  false /* TEXT's typbyval */ ,
3030  TYPALIGN_INT /* TEXT's typalign */ ,
3031  &isnull);
3032  if (!isnull)
3033  {
3034  char *configitem = TextDatumGetCString(d);
3035  char *pos;
3036 
3037  pos = strchr(configitem, '=');
3038  if (pos == NULL)
3039  continue;
3040  *pos++ = '\0';
3041 
3042  appendStringInfo(&buf, " SET %s TO ",
3043  quote_identifier(configitem));
3044 
3045  /*
3046  * Variables that are marked GUC_LIST_QUOTE were already fully
3047  * quoted by flatten_set_variable_args() before they were put
3048  * into the proconfig array. However, because the quoting
3049  * rules used there aren't exactly like SQL's, we have to
3050  * break the list value apart and then quote the elements as
3051  * string literals. (The elements may be double-quoted as-is,
3052  * but we can't just feed them to the SQL parser; it would do
3053  * the wrong thing with elements that are zero-length or
3054  * longer than NAMEDATALEN.)
3055  *
3056  * Variables that are not so marked should just be emitted as
3057  * simple string literals. If the variable is not known to
3058  * guc.c, we'll do that; this makes it unsafe to use
3059  * GUC_LIST_QUOTE for extension variables.
3060  */
3061  if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
3062  {
3063  List *namelist;
3064  ListCell *lc;
3065 
3066  /* Parse string into list of identifiers */
3067  if (!SplitGUCList(pos, ',', &namelist))
3068  {
3069  /* this shouldn't fail really */
3070  elog(ERROR, "invalid list syntax in proconfig item");
3071  }
3072  foreach(lc, namelist)
3073  {
3074  char *curname = (char *) lfirst(lc);
3075 
3076  simple_quote_literal(&buf, curname);
3077  if (lnext(namelist, lc))
3078  appendStringInfoString(&buf, ", ");
3079  }
3080  }
3081  else
3082  simple_quote_literal(&buf, pos);
3083  appendStringInfoChar(&buf, '\n');
3084  }
3085  }
3086  }
3087 
3088  /* And finally the function definition ... */
3089  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3090  if (proc->prolang == SQLlanguageId && !isnull)
3091  {
3092  print_function_sqlbody(&buf, proctup);
3093  }
3094  else
3095  {
3096  appendStringInfoString(&buf, "AS ");
3097 
3098  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
3099  if (!isnull)
3100  {
3102  appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
3103  }
3104 
3105  tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosrc);
3106  prosrc = TextDatumGetCString(tmp);
3107 
3108  /*
3109  * We always use dollar quoting. Figure out a suitable delimiter.
3110  *
3111  * Since the user is likely to be editing the function body string, we
3112  * shouldn't use a short delimiter that he might easily create a
3113  * conflict with. Hence prefer "$function$"/"$procedure$", but extend
3114  * if needed.
3115  */
3116  initStringInfo(&dq);
3117  appendStringInfoChar(&dq, '$');
3118  appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
3119  while (strstr(prosrc, dq.data) != NULL)
3120  appendStringInfoChar(&dq, 'x');
3121  appendStringInfoChar(&dq, '$');
3122 
3123  appendBinaryStringInfo(&buf, dq.data, dq.len);
3124  appendStringInfoString(&buf, prosrc);
3125  appendBinaryStringInfo(&buf, dq.data, dq.len);
3126  }
3127 
3128  appendStringInfoChar(&buf, '\n');
3129 
3130  ReleaseSysCache(proctup);
3131 
3133 }
3134 
3135 /*
3136  * pg_get_function_arguments
3137  * Get a nicely-formatted list of arguments for a function.
3138  * This is everything that would go between the parentheses in
3139  * CREATE FUNCTION.
3140  */
3141 Datum
3143 {
3144  Oid funcid = PG_GETARG_OID(0);
3146  HeapTuple proctup;
3147 
3148  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3149  if (!HeapTupleIsValid(proctup))
3150  PG_RETURN_NULL();
3151 
3152  initStringInfo(&buf);
3153 
3154  (void) print_function_arguments(&buf, proctup, false, true);
3155 
3156  ReleaseSysCache(proctup);
3157 
3159 }
3160 
3161 /*
3162  * pg_get_function_identity_arguments
3163  * Get a formatted list of arguments for a function.
3164  * This is everything that would go between the parentheses in
3165  * ALTER FUNCTION, etc. In particular, don't print defaults.
3166  */
3167 Datum
3169 {
3170  Oid funcid = PG_GETARG_OID(0);
3172  HeapTuple proctup;
3173 
3174  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3175  if (!HeapTupleIsValid(proctup))
3176  PG_RETURN_NULL();
3177 
3178  initStringInfo(&buf);
3179 
3180  (void) print_function_arguments(&buf, proctup, false, false);
3181 
3182  ReleaseSysCache(proctup);
3183 
3185 }
3186 
3187 /*
3188  * pg_get_function_result
3189  * Get a nicely-formatted version of the result type of a function.
3190  * This is what would appear after RETURNS in CREATE FUNCTION.
3191  */
3192 Datum
3194 {
3195  Oid funcid = PG_GETARG_OID(0);
3197  HeapTuple proctup;
3198 
3199  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3200  if (!HeapTupleIsValid(proctup))
3201  PG_RETURN_NULL();
3202 
3203  if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
3204  {
3205  ReleaseSysCache(proctup);
3206  PG_RETURN_NULL();
3207  }
3208 
3209  initStringInfo(&buf);
3210 
3211  print_function_rettype(&buf, proctup);
3212 
3213  ReleaseSysCache(proctup);
3214 
3216 }
3217 
3218 /*
3219  * Guts of pg_get_function_result: append the function's return type
3220  * to the specified buffer.
3221  */
3222 static void
3224 {
3225  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3226  int ntabargs = 0;
3227  StringInfoData rbuf;
3228 
3229  initStringInfo(&rbuf);
3230 
3231  if (proc->proretset)
3232  {
3233  /* It might be a table function; try to print the arguments */
3234  appendStringInfoString(&rbuf, "TABLE(");
3235  ntabargs = print_function_arguments(&rbuf, proctup, true, false);
3236  if (ntabargs > 0)
3237  appendStringInfoChar(&rbuf, ')');
3238  else
3239  resetStringInfo(&rbuf);
3240  }
3241 
3242  if (ntabargs == 0)
3243  {
3244  /* Not a table function, so do the normal thing */
3245  if (proc->proretset)
3246  appendStringInfoString(&rbuf, "SETOF ");
3247  appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
3248  }
3249 
3250  appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
3251 }
3252 
3253 /*
3254  * Common code for pg_get_function_arguments and pg_get_function_result:
3255  * append the desired subset of arguments to buf. We print only TABLE
3256  * arguments when print_table_args is true, and all the others when it's false.
3257  * We print argument defaults only if print_defaults is true.
3258  * Function return value is the number of arguments printed.
3259  */
3260 static int
3262  bool print_table_args, bool print_defaults)
3263 {
3264  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3265  int numargs;
3266  Oid *argtypes;
3267  char **argnames;
3268  char *argmodes;
3269  int insertorderbyat = -1;
3270  int argsprinted;
3271  int inputargno;
3272  int nlackdefaults;
3273  List *argdefaults = NIL;
3274  ListCell *nextargdefault = NULL;
3275  int i;
3276 
3277  numargs = get_func_arg_info(proctup,
3278  &argtypes, &argnames, &argmodes);
3279 
3280  nlackdefaults = numargs;
3281  if (print_defaults && proc->pronargdefaults > 0)
3282  {
3283  Datum proargdefaults;
3284  bool isnull;
3285 
3286  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3287  Anum_pg_proc_proargdefaults,
3288  &isnull);
3289  if (!isnull)
3290  {
3291  char *str;
3292 
3293  str = TextDatumGetCString(proargdefaults);
3294  argdefaults = castNode(List, stringToNode(str));
3295  pfree(str);
3296  nextargdefault = list_head(argdefaults);
3297  /* nlackdefaults counts only *input* arguments lacking defaults */
3298  nlackdefaults = proc->pronargs - list_length(argdefaults);
3299  }
3300  }
3301 
3302  /* Check for special treatment of ordered-set aggregates */
3303  if (proc->prokind == PROKIND_AGGREGATE)
3304  {
3305  HeapTuple aggtup;
3306  Form_pg_aggregate agg;
3307 
3308  aggtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(proc->oid));
3309  if (!HeapTupleIsValid(aggtup))
3310  elog(ERROR, "cache lookup failed for aggregate %u",
3311  proc->oid);
3312  agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3313  if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3314  insertorderbyat = agg->aggnumdirectargs;
3315  ReleaseSysCache(aggtup);
3316  }
3317 
3318  argsprinted = 0;
3319  inputargno = 0;
3320  for (i = 0; i < numargs; i++)
3321  {
3322  Oid argtype = argtypes[i];
3323  char *argname = argnames ? argnames[i] : NULL;
3324  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3325  const char *modename;
3326  bool isinput;
3327 
3328  switch (argmode)
3329  {
3330  case PROARGMODE_IN:
3331 
3332  /*
3333  * For procedures, explicitly mark all argument modes, so as
3334  * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
3335  */
3336  if (proc->prokind == PROKIND_PROCEDURE)
3337  modename = "IN ";
3338  else
3339  modename = "";
3340  isinput = true;
3341  break;
3342  case PROARGMODE_INOUT:
3343  modename = "INOUT ";
3344  isinput = true;
3345  break;
3346  case PROARGMODE_OUT:
3347  modename = "OUT ";
3348  isinput = false;
3349  break;
3350  case PROARGMODE_VARIADIC:
3351  modename = "VARIADIC ";
3352  isinput = true;
3353  break;
3354  case PROARGMODE_TABLE:
3355  modename = "";
3356  isinput = false;
3357  break;
3358  default:
3359  elog(ERROR, "invalid parameter mode '%c'", argmode);
3360  modename = NULL; /* keep compiler quiet */
3361  isinput = false;
3362  break;
3363  }
3364  if (isinput)
3365  inputargno++; /* this is a 1-based counter */
3366 
3367  if (print_table_args != (argmode == PROARGMODE_TABLE))
3368  continue;
3369 
3370  if (argsprinted == insertorderbyat)
3371  {
3372  if (argsprinted)
3373  appendStringInfoChar(buf, ' ');
3374  appendStringInfoString(buf, "ORDER BY ");
3375  }
3376  else if (argsprinted)
3377  appendStringInfoString(buf, ", ");
3378 
3379  appendStringInfoString(buf, modename);
3380  if (argname && argname[0])
3381  appendStringInfo(buf, "%s ", quote_identifier(argname));
3383  if (print_defaults && isinput && inputargno > nlackdefaults)
3384  {
3385  Node *expr;
3386 
3387  Assert(nextargdefault != NULL);
3388  expr = (Node *) lfirst(nextargdefault);
3389  nextargdefault = lnext(argdefaults, nextargdefault);
3390 
3391  appendStringInfo(buf, " DEFAULT %s",
3392  deparse_expression(expr, NIL, false, false));
3393  }
3394  argsprinted++;
3395 
3396  /* nasty hack: print the last arg twice for variadic ordered-set agg */
3397  if (argsprinted == insertorderbyat && i == numargs - 1)
3398  {
3399  i--;
3400  /* aggs shouldn't have defaults anyway, but just to be sure ... */
3401  print_defaults = false;
3402  }
3403  }
3404 
3405  return argsprinted;
3406 }
3407 
3408 static bool
3409 is_input_argument(int nth, const char *argmodes)
3410 {
3411  return (!argmodes
3412  || argmodes[nth] == PROARGMODE_IN
3413  || argmodes[nth] == PROARGMODE_INOUT
3414  || argmodes[nth] == PROARGMODE_VARIADIC);
3415 }
3416 
3417 /*
3418  * Append used transformed types to specified buffer
3419  */
3420 static void
3422 {
3423  Oid *trftypes;
3424  int ntypes;
3425 
3426  ntypes = get_func_trftypes(proctup, &trftypes);
3427  if (ntypes > 0)
3428  {
3429  int i;
3430 
3431  appendStringInfoString(buf, " TRANSFORM ");
3432  for (i = 0; i < ntypes; i++)
3433  {
3434  if (i != 0)
3435  appendStringInfoString(buf, ", ");
3436  appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3437  }
3438  appendStringInfoChar(buf, '\n');
3439  }
3440 }
3441 
3442 /*
3443  * Get textual representation of a function argument's default value. The
3444  * second argument of this function is the argument number among all arguments
3445  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3446  * how information_schema.sql uses it.
3447  */
3448 Datum
3450 {
3451  Oid funcid = PG_GETARG_OID(0);
3452  int32 nth_arg = PG_GETARG_INT32(1);
3453  HeapTuple proctup;
3454  Form_pg_proc proc;
3455  int numargs;
3456  Oid *argtypes;
3457  char **argnames;
3458  char *argmodes;
3459  int i;
3460  List *argdefaults;
3461  Node *node;
3462  char *str;
3463  int nth_inputarg;
3464  Datum proargdefaults;
3465  bool isnull;
3466  int nth_default;
3467 
3468  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3469  if (!HeapTupleIsValid(proctup))
3470  PG_RETURN_NULL();
3471 
3472  numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3473  if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3474  {
3475  ReleaseSysCache(proctup);
3476  PG_RETURN_NULL();
3477  }
3478 
3479  nth_inputarg = 0;
3480  for (i = 0; i < nth_arg; i++)
3481  if (is_input_argument(i, argmodes))
3482  nth_inputarg++;
3483 
3484  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3485  Anum_pg_proc_proargdefaults,
3486  &isnull);
3487  if (isnull)
3488  {
3489  ReleaseSysCache(proctup);
3490  PG_RETURN_NULL();
3491  }
3492 
3493  str = TextDatumGetCString(proargdefaults);
3494  argdefaults = castNode(List, stringToNode(str));
3495  pfree(str);
3496 
3497  proc = (Form_pg_proc) GETSTRUCT(proctup);
3498 
3499  /*
3500  * Calculate index into proargdefaults: proargdefaults corresponds to the
3501  * last N input arguments, where N = pronargdefaults.
3502  */
3503  nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3504 
3505  if (nth_default < 0 || nth_default >= list_length(argdefaults))
3506  {
3507  ReleaseSysCache(proctup);
3508  PG_RETURN_NULL();
3509  }
3510  node = list_nth(argdefaults, nth_default);
3511  str = deparse_expression(node, NIL, false, false);
3512 
3513  ReleaseSysCache(proctup);
3514 
3516 }
3517 
3518 static void
3520 {
3521  int numargs;
3522  Oid *argtypes;
3523  char **argnames;
3524  char *argmodes;
3525  deparse_namespace dpns = {0};
3526  Datum tmp;
3527  Node *n;
3528 
3529  dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
3530  numargs = get_func_arg_info(proctup,
3531  &argtypes, &argnames, &argmodes);
3532  dpns.numargs = numargs;
3533  dpns.argnames = argnames;
3534 
3535  tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosqlbody);
3537 
3538  if (IsA(n, List))
3539  {
3540  List *stmts;
3541  ListCell *lc;
3542 
3543  stmts = linitial(castNode(List, n));
3544 
3545  appendStringInfoString(buf, "BEGIN ATOMIC\n");
3546 
3547  foreach(lc, stmts)
3548  {
3549  Query *query = lfirst_node(Query, lc);
3550 
3551  /* It seems advisable to get at least AccessShareLock on rels */
3552  AcquireRewriteLocks(query, false, false);
3553  get_query_def(query, buf, list_make1(&dpns), NULL, false,
3555  appendStringInfoChar(buf, ';');
3556  appendStringInfoChar(buf, '\n');
3557  }
3558 
3559  appendStringInfoString(buf, "END");
3560  }
3561  else
3562  {
3563  Query *query = castNode(Query, n);
3564 
3565  /* It seems advisable to get at least AccessShareLock on rels */
3566  AcquireRewriteLocks(query, false, false);
3567  get_query_def(query, buf, list_make1(&dpns), NULL, false,
3568  0, WRAP_COLUMN_DEFAULT, 0);
3569  }
3570 }
3571 
3572 Datum
3574 {
3575  Oid funcid = PG_GETARG_OID(0);
3577  HeapTuple proctup;
3578  bool isnull;
3579 
3580  initStringInfo(&buf);
3581 
3582  /* Look up the function */
3583  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3584  if (!HeapTupleIsValid(proctup))
3585  PG_RETURN_NULL();
3586 
3587  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3588  if (isnull)
3589  {
3590  ReleaseSysCache(proctup);
3591  PG_RETURN_NULL();
3592  }
3593 
3594  print_function_sqlbody(&buf, proctup);
3595 
3596  ReleaseSysCache(proctup);
3597 
3599 }
3600 
3601 
3602 /*
3603  * deparse_expression - General utility for deparsing expressions
3604  *
3605  * calls deparse_expression_pretty with all prettyPrinting disabled
3606  */
3607 char *
3608 deparse_expression(Node *expr, List *dpcontext,
3609  bool forceprefix, bool showimplicit)
3610 {
3611  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3612  showimplicit, 0, 0);
3613 }
3614 
3615 /* ----------
3616  * deparse_expression_pretty - General utility for deparsing expressions
3617  *
3618  * expr is the node tree to be deparsed. It must be a transformed expression
3619  * tree (ie, not the raw output of gram.y).
3620  *
3621  * dpcontext is a list of deparse_namespace nodes representing the context
3622  * for interpreting Vars in the node tree. It can be NIL if no Vars are
3623  * expected.
3624  *
3625  * forceprefix is true to force all Vars to be prefixed with their table names.
3626  *
3627  * showimplicit is true to force all implicit casts to be shown explicitly.
3628  *
3629  * Tries to pretty up the output according to prettyFlags and startIndent.
3630  *
3631  * The result is a palloc'd string.
3632  * ----------
3633  */
3634 static char *
3636  bool forceprefix, bool showimplicit,
3637  int prettyFlags, int startIndent)
3638 {
3641 
3642  initStringInfo(&buf);
3643  context.buf = &buf;
3644  context.namespaces = dpcontext;
3645  context.resultDesc = NULL;
3646  context.targetList = NIL;
3647  context.windowClause = NIL;
3648  context.varprefix = forceprefix;
3649  context.prettyFlags = prettyFlags;
3650  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3651  context.indentLevel = startIndent;
3652  context.colNamesVisible = true;
3653  context.inGroupBy = false;
3654  context.varInOrderBy = false;
3655  context.appendparents = NULL;
3656 
3657  get_rule_expr(expr, &context, showimplicit);
3658 
3659  return buf.data;
3660 }
3661 
3662 /* ----------
3663  * deparse_context_for - Build deparse context for a single relation
3664  *
3665  * Given the reference name (alias) and OID of a relation, build deparsing
3666  * context for an expression referencing only that relation (as varno 1,
3667  * varlevelsup 0). This is sufficient for many uses of deparse_expression.
3668  * ----------
3669  */
3670 List *
3671 deparse_context_for(const char *aliasname, Oid relid)
3672 {
3673  deparse_namespace *dpns;
3674  RangeTblEntry *rte;
3675 
3676  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3677 
3678  /* Build a minimal RTE for the rel */
3679  rte = makeNode(RangeTblEntry);
3680  rte->rtekind = RTE_RELATION;
3681  rte->relid = relid;
3682  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3683  rte->rellockmode = AccessShareLock;
3684  rte->alias = makeAlias(aliasname, NIL);
3685  rte->eref = rte->alias;
3686  rte->lateral = false;
3687  rte->inh = false;
3688  rte->inFromCl = true;
3689 
3690  /* Build one-element rtable */
3691  dpns->rtable = list_make1(rte);
3692  dpns->subplans = NIL;
3693  dpns->ctes = NIL;
3694  dpns->appendrels = NULL;
3695  set_rtable_names(dpns, NIL, NULL);
3697 
3698  /* Return a one-deep namespace stack */
3699  return list_make1(dpns);
3700 }
3701 
3702 /*
3703  * deparse_context_for_plan_tree - Build deparse context for a Plan tree
3704  *
3705  * When deparsing an expression in a Plan tree, we use the plan's rangetable
3706  * to resolve names of simple Vars. The initialization of column names for
3707  * this is rather expensive if the rangetable is large, and it'll be the same
3708  * for every expression in the Plan tree; so we do it just once and re-use
3709  * the result of this function for each expression. (Note that the result
3710  * is not usable until set_deparse_context_plan() is applied to it.)
3711  *
3712  * In addition to the PlannedStmt, pass the per-RTE alias names
3713  * assigned by a previous call to select_rtable_names_for_explain.
3714  */
3715 List *
3717 {
3718  deparse_namespace *dpns;
3719 
3720  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3721 
3722  /* Initialize fields that stay the same across the whole plan tree */
3723  dpns->rtable = pstmt->rtable;
3724  dpns->rtable_names = rtable_names;
3725  dpns->subplans = pstmt->subplans;
3726  dpns->ctes = NIL;
3727  if (pstmt->appendRelations)
3728  {
3729  /* Set up the array, indexed by child relid */
3730  int ntables = list_length(dpns->rtable);
3731  ListCell *lc;
3732 
3733  dpns->appendrels = (AppendRelInfo **)
3734  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3735  foreach(lc, pstmt->appendRelations)
3736  {
3737  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3738  Index crelid = appinfo->child_relid;
3739 
3740  Assert(crelid > 0 && crelid <= ntables);
3741  Assert(dpns->appendrels[crelid] == NULL);
3742  dpns->appendrels[crelid] = appinfo;
3743  }
3744  }
3745  else
3746  dpns->appendrels = NULL; /* don't need it */
3747 
3748  /*
3749  * Set up column name aliases. We will get rather bogus results for join
3750  * RTEs, but that doesn't matter because plan trees don't contain any join
3751  * alias Vars.
3752  */
3754 
3755  /* Return a one-deep namespace stack */
3756  return list_make1(dpns);
3757 }
3758 
3759 /*
3760  * set_deparse_context_plan - Specify Plan node containing expression
3761  *
3762  * When deparsing an expression in a Plan tree, we might have to resolve
3763  * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
3764  * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
3765  * can be resolved by drilling down into the left and right child plans.
3766  * Similarly, INDEX_VAR references can be resolved by reference to the
3767  * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
3768  * ForeignScan and CustomScan nodes. (Note that we don't currently support
3769  * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
3770  * for those, we can only deparse the indexqualorig fields, which won't
3771  * contain INDEX_VAR Vars.)
3772  *
3773  * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
3774  * the most-closely-nested first. This is needed to resolve PARAM_EXEC
3775  * Params. Note we assume that all the Plan nodes share the same rtable.
3776  *
3777  * Once this function has been called, deparse_expression() can be called on
3778  * subsidiary expression(s) of the specified Plan node. To deparse
3779  * expressions of a different Plan node in the same Plan tree, re-call this
3780  * function to identify the new parent Plan node.
3781  *
3782  * The result is the same List passed in; this is a notational convenience.
3783  */
3784 List *
3785 set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
3786 {
3787  deparse_namespace *dpns;
3788 
3789  /* Should always have one-entry namespace list for Plan deparsing */
3790  Assert(list_length(dpcontext) == 1);
3791  dpns = (deparse_namespace *) linitial(dpcontext);
3792 
3793  /* Set our attention on the specific plan node passed in */
3794  dpns->ancestors = ancestors;
3795  set_deparse_plan(dpns, plan);
3796 
3797  return dpcontext;
3798 }
3799 
3800 /*
3801  * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
3802  *
3803  * Determine the relation aliases we'll use during an EXPLAIN operation.
3804  * This is just a frontend to set_rtable_names. We have to expose the aliases
3805  * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
3806  */
3807 List *
3809 {
3810  deparse_namespace dpns;
3811 
3812  memset(&dpns, 0, sizeof(dpns));
3813  dpns.rtable = rtable;
3814  dpns.subplans = NIL;
3815  dpns.ctes = NIL;
3816  dpns.appendrels = NULL;
3817  set_rtable_names(&dpns, NIL, rels_used);
3818  /* We needn't bother computing column aliases yet */
3819 
3820  return dpns.rtable_names;
3821 }
3822 
3823 /*
3824  * set_rtable_names: select RTE aliases to be used in printing a query
3825  *
3826  * We fill in dpns->rtable_names with a list of names that is one-for-one with
3827  * the already-filled dpns->rtable list. Each RTE name is unique among those
3828  * in the new namespace plus any ancestor namespaces listed in
3829  * parent_namespaces.
3830  *
3831  * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
3832  *
3833  * Note that this function is only concerned with relation names, not column
3834  * names.
3835  */
3836 static void
3837 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
3838  Bitmapset *rels_used)
3839 {
3840  HASHCTL hash_ctl;
3841  HTAB *names_hash;
3842  NameHashEntry *hentry;
3843  bool found;
3844  int rtindex;
3845  ListCell *lc;
3846 
3847  dpns->rtable_names = NIL;
3848  /* nothing more to do if empty rtable */
3849  if (dpns->rtable == NIL)
3850  return;
3851 
3852  /*
3853  * We use a hash table to hold known names, so that this process is O(N)
3854  * not O(N^2) for N names.
3855  */
3856  hash_ctl.keysize = NAMEDATALEN;
3857  hash_ctl.entrysize = sizeof(NameHashEntry);
3858  hash_ctl.hcxt = CurrentMemoryContext;
3859  names_hash = hash_create("set_rtable_names names",
3860  list_length(dpns->rtable),
3861  &hash_ctl,
3863 
3864  /* Preload the hash table with names appearing in parent_namespaces */
3865  foreach(lc, parent_namespaces)
3866  {
3867  deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
3868  ListCell *lc2;
3869 
3870  foreach(lc2, olddpns->rtable_names)
3871  {
3872  char *oldname = (char *) lfirst(lc2);
3873 
3874  if (oldname == NULL)
3875  continue;
3876  hentry = (NameHashEntry *) hash_search(names_hash,
3877  oldname,
3878  HASH_ENTER,
3879  &found);
3880  /* we do not complain about duplicate names in parent namespaces */
3881  hentry->counter = 0;
3882  }
3883  }
3884 
3885  /* Now we can scan the rtable */
3886  rtindex = 1;
3887  foreach(lc, dpns->rtable)
3888  {
3889  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3890  char *refname;
3891 
3892  /* Just in case this takes an unreasonable amount of time ... */
3894 
3895  if (rels_used && !bms_is_member(rtindex, rels_used))
3896  {
3897  /* Ignore unreferenced RTE */
3898  refname = NULL;
3899  }
3900  else if (rte->alias)
3901  {
3902  /* If RTE has a user-defined alias, prefer that */
3903  refname = rte->alias->aliasname;
3904  }
3905  else if (rte->rtekind == RTE_RELATION)
3906  {
3907  /* Use the current actual name of the relation */
3908  refname = get_rel_name(rte->relid);
3909  }
3910  else if (rte->rtekind == RTE_JOIN)
3911  {
3912  /* Unnamed join has no refname */
3913  refname = NULL;
3914  }
3915  else
3916  {
3917  /* Otherwise use whatever the parser assigned */
3918  refname = rte->eref->aliasname;
3919  }
3920 
3921  /*
3922  * If the selected name isn't unique, append digits to make it so, and
3923  * make a new hash entry for it once we've got a unique name. For a
3924  * very long input name, we might have to truncate to stay within
3925  * NAMEDATALEN.
3926  */
3927  if (refname)
3928  {
3929  hentry = (NameHashEntry *) hash_search(names_hash,
3930  refname,
3931  HASH_ENTER,
3932  &found);
3933  if (found)
3934  {
3935  /* Name already in use, must choose a new one */
3936  int refnamelen = strlen(refname);
3937  char *modname = (char *) palloc(refnamelen + 16);
3938  NameHashEntry *hentry2;
3939 
3940  do
3941  {
3942  hentry->counter++;
3943  for (;;)
3944  {
3945  memcpy(modname, refname, refnamelen);
3946  sprintf(modname + refnamelen, "_%d", hentry->counter);
3947  if (strlen(modname) < NAMEDATALEN)
3948  break;
3949  /* drop chars from refname to keep all the digits */
3950  refnamelen = pg_mbcliplen(refname, refnamelen,
3951  refnamelen - 1);
3952  }
3953  hentry2 = (NameHashEntry *) hash_search(names_hash,
3954  modname,
3955  HASH_ENTER,
3956  &found);
3957  } while (found);
3958  hentry2->counter = 0; /* init new hash entry */
3959  refname = modname;
3960  }
3961  else
3962  {
3963  /* Name not previously used, need only initialize hentry */
3964  hentry->counter = 0;
3965  }
3966  }
3967 
3968  dpns->rtable_names = lappend(dpns->rtable_names, refname);
3969  rtindex++;
3970  }
3971 
3972  hash_destroy(names_hash);
3973 }
3974 
3975 /*
3976  * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
3977  *
3978  * For convenience, this is defined to initialize the deparse_namespace struct
3979  * from scratch.
3980  */
3981 static void
3983  List *parent_namespaces)
3984 {
3985  ListCell *lc;
3986  ListCell *lc2;
3987 
3988  /* Initialize *dpns and fill rtable/ctes links */
3989  memset(dpns, 0, sizeof(deparse_namespace));
3990  dpns->rtable = query->rtable;
3991  dpns->subplans = NIL;
3992  dpns->ctes = query->cteList;
3993  dpns->appendrels = NULL;
3994 
3995  /* Assign a unique relation alias to each RTE */
3996  set_rtable_names(dpns, parent_namespaces, NULL);
3997 
3998  /* Initialize dpns->rtable_columns to contain zeroed structs */
3999  dpns->rtable_columns = NIL;
4000  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
4001  dpns->rtable_columns = lappend(dpns->rtable_columns,
4002  palloc0(sizeof(deparse_columns)));
4003 
4004  /* If it's a utility query, it won't have a jointree */
4005  if (query->jointree)
4006  {
4007  /* Detect whether global uniqueness of USING names is needed */
4008  dpns->unique_using =
4009  has_dangerous_join_using(dpns, (Node *) query->jointree);
4010 
4011  /*
4012  * Select names for columns merged by USING, via a recursive pass over
4013  * the query jointree.
4014  */
4015  set_using_names(dpns, (Node *) query->jointree, NIL);
4016  }
4017 
4018  /*
4019  * Now assign remaining column aliases for each RTE. We do this in a
4020  * linear scan of the rtable, so as to process RTEs whether or not they
4021  * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
4022  * etc). JOIN RTEs must be processed after their children, but this is
4023  * okay because they appear later in the rtable list than their children
4024  * (cf Asserts in identify_join_columns()).
4025  */
4026  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4027  {
4028  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4029  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4030 
4031  if (rte->rtekind == RTE_JOIN)
4032  set_join_column_names(dpns, rte, colinfo);
4033  else
4034  set_relation_column_names(dpns, rte, colinfo);
4035  }
4036 }
4037 
4038 /*
4039  * set_simple_column_names: fill in column aliases for non-query situations
4040  *
4041  * This handles EXPLAIN and cases where we only have relation RTEs. Without
4042  * a join tree, we can't do anything smart about join RTEs, but we don't
4043  * need to (note that EXPLAIN should never see join alias Vars anyway).
4044  * If we do hit a join RTE we'll just process it like a non-table base RTE.
4045  */
4046 static void
4048 {
4049  ListCell *lc;
4050  ListCell *lc2;
4051 
4052  /* Initialize dpns->rtable_columns to contain zeroed structs */
4053  dpns->rtable_columns = NIL;
4054  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
4055  dpns->rtable_columns = lappend(dpns->rtable_columns,
4056  palloc0(sizeof(deparse_columns)));
4057 
4058  /* Assign unique column aliases within each RTE */
4059  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4060  {
4061  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4062  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4063 
4064  set_relation_column_names(dpns, rte, colinfo);
4065  }
4066 }
4067 
4068 /*
4069  * has_dangerous_join_using: search jointree for unnamed JOIN USING
4070  *
4071  * Merged columns of a JOIN USING may act differently from either of the input
4072  * columns, either because they are merged with COALESCE (in a FULL JOIN) or
4073  * because an implicit coercion of the underlying input column is required.
4074  * In such a case the column must be referenced as a column of the JOIN not as
4075  * a column of either input. And this is problematic if the join is unnamed
4076  * (alias-less): we cannot qualify the column's name with an RTE name, since
4077  * there is none. (Forcibly assigning an alias to the join is not a solution,
4078  * since that will prevent legal references to tables below the join.)
4079  * To ensure that every column in the query is unambiguously referenceable,
4080  * we must assign such merged columns names that are globally unique across
4081  * the whole query, aliasing other columns out of the way as necessary.
4082  *
4083  * Because the ensuing re-aliasing is fairly damaging to the readability of
4084  * the query, we don't do this unless we have to. So, we must pre-scan
4085  * the join tree to see if we have to, before starting set_using_names().
4086  */
4087 static bool
4089 {
4090  if (IsA(jtnode, RangeTblRef))
4091  {
4092  /* nothing to do here */
4093  }
4094  else if (IsA(jtnode, FromExpr))
4095  {
4096  FromExpr *f = (FromExpr *) jtnode;
4097  ListCell *lc;
4098 
4099  foreach(lc, f->fromlist)
4100  {
4101  if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
4102  return true;
4103  }
4104  }
4105  else if (IsA(jtnode, JoinExpr))
4106  {
4107  JoinExpr *j = (JoinExpr *) jtnode;
4108 
4109  /* Is it an unnamed JOIN with USING? */
4110  if (j->alias == NULL && j->usingClause)
4111  {
4112  /*
4113  * Yes, so check each join alias var to see if any of them are not
4114  * simple references to underlying columns. If so, we have a
4115  * dangerous situation and must pick unique aliases.
4116  */
4117  RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
4118 
4119  /* We need only examine the merged columns */
4120  for (int i = 0; i < jrte->joinmergedcols; i++)
4121  {
4122  Node *aliasvar = list_nth(jrte->joinaliasvars, i);
4123 
4124  if (!IsA(aliasvar, Var))
4125  return true;
4126  }
4127  }
4128 
4129  /* Nope, but inspect children */
4130  if (has_dangerous_join_using(dpns, j->larg))
4131  return true;
4132  if (has_dangerous_join_using(dpns, j->rarg))
4133  return true;
4134  }
4135  else
4136  elog(ERROR, "unrecognized node type: %d",
4137  (int) nodeTag(jtnode));
4138  return false;
4139 }
4140 
4141 /*
4142  * set_using_names: select column aliases to be used for merged USING columns
4143  *
4144  * We do this during a recursive descent of the query jointree.
4145  * dpns->unique_using must already be set to determine the global strategy.
4146  *
4147  * Column alias info is saved in the dpns->rtable_columns list, which is
4148  * assumed to be filled with pre-zeroed deparse_columns structs.
4149  *
4150  * parentUsing is a list of all USING aliases assigned in parent joins of
4151  * the current jointree node. (The passed-in list must not be modified.)
4152  *
4153  * Note that we do not use per-deparse_columns hash tables in this function.
4154  * The number of names that need to be assigned should be small enough that
4155  * we don't need to trouble with that.
4156  */
4157 static void
4158 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
4159 {
4160  if (IsA(jtnode, RangeTblRef))
4161  {
4162  /* nothing to do now */
4163  }
4164  else if (IsA(jtnode, FromExpr))
4165  {
4166  FromExpr *f = (FromExpr *) jtnode;
4167  ListCell *lc;
4168 
4169  foreach(lc, f->fromlist)
4170  set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
4171  }
4172  else if (IsA(jtnode, JoinExpr))
4173  {
4174  JoinExpr *j = (JoinExpr *) jtnode;
4175  RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
4176  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
4177  int *leftattnos;
4178  int *rightattnos;
4179  deparse_columns *leftcolinfo;
4180  deparse_columns *rightcolinfo;
4181  int i;
4182  ListCell *lc;
4183 
4184  /* Get info about the shape of the join */
4185  identify_join_columns(j, rte, colinfo);
4186  leftattnos = colinfo->leftattnos;
4187  rightattnos = colinfo->rightattnos;
4188 
4189  /* Look up the not-yet-filled-in child deparse_columns structs */
4190  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4191  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4192 
4193  /*
4194  * If this join is unnamed, then we cannot substitute new aliases at
4195  * this level, so any name requirements pushed down to here must be
4196  * pushed down again to the children.
4197  */
4198  if (rte->alias == NULL)
4199  {
4200  for (i = 0; i < colinfo->num_cols; i++)
4201  {
4202  char *colname = colinfo->colnames[i];
4203 
4204  if (colname == NULL)
4205  continue;
4206 
4207  /* Push down to left column, unless it's a system column */
4208  if (leftattnos[i] > 0)
4209  {
4210  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4211  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4212  }
4213 
4214  /* Same on the righthand side */
4215  if (rightattnos[i] > 0)
4216  {
4217  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4218  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4219  }
4220  }
4221  }
4222 
4223  /*
4224  * If there's a USING clause, select the USING column names and push
4225  * those names down to the children. We have two strategies:
4226  *
4227  * If dpns->unique_using is true, we force all USING names to be
4228  * unique across the whole query level. In principle we'd only need
4229  * the names of dangerous USING columns to be globally unique, but to
4230  * safely assign all USING names in a single pass, we have to enforce
4231  * the same uniqueness rule for all of them. However, if a USING
4232  * column's name has been pushed down from the parent, we should use
4233  * it as-is rather than making a uniqueness adjustment. This is
4234  * necessary when we're at an unnamed join, and it creates no risk of
4235  * ambiguity. Also, if there's a user-written output alias for a
4236  * merged column, we prefer to use that rather than the input name;
4237  * this simplifies the logic and seems likely to lead to less aliasing
4238  * overall.
4239  *
4240  * If dpns->unique_using is false, we only need USING names to be
4241  * unique within their own join RTE. We still need to honor
4242  * pushed-down names, though.
4243  *
4244  * Though significantly different in results, these two strategies are
4245  * implemented by the same code, with only the difference of whether
4246  * to put assigned names into dpns->using_names.
4247  */
4248  if (j->usingClause)
4249  {
4250  /* Copy the input parentUsing list so we don't modify it */
4251  parentUsing = list_copy(parentUsing);
4252 
4253  /* USING names must correspond to the first join output columns */
4254  expand_colnames_array_to(colinfo, list_length(j->usingClause));
4255  i = 0;
4256  foreach(lc, j->usingClause)
4257  {
4258  char *colname = strVal(lfirst(lc));
4259 
4260  /* Assert it's a merged column */
4261  Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
4262 
4263  /* Adopt passed-down name if any, else select unique name */
4264  if (colinfo->colnames[i] != NULL)
4265  colname = colinfo->colnames[i];
4266  else
4267  {
4268  /* Prefer user-written output alias if any */
4269  if (rte->alias && i < list_length(rte->alias->colnames))
4270  colname = strVal(list_nth(rte->alias->colnames, i));
4271  /* Make it appropriately unique */
4272  colname = make_colname_unique(colname, dpns, colinfo);
4273  if (dpns->unique_using)
4274  dpns->using_names = lappend(dpns->using_names,
4275  colname);
4276  /* Save it as output column name, too */
4277  colinfo->colnames[i] = colname;
4278  }
4279 
4280  /* Remember selected names for use later */
4281  colinfo->usingNames = lappend(colinfo->usingNames, colname);
4282  parentUsing = lappend(parentUsing, colname);
4283 
4284  /* Push down to left column, unless it's a system column */
4285  if (leftattnos[i] > 0)
4286  {
4287  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4288  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4289  }
4290 
4291  /* Same on the righthand side */
4292  if (rightattnos[i] > 0)
4293  {
4294  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4295  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4296  }
4297 
4298  i++;
4299  }
4300  }
4301 
4302  /* Mark child deparse_columns structs with correct parentUsing info */
4303  leftcolinfo->parentUsing = parentUsing;
4304  rightcolinfo->parentUsing = parentUsing;
4305 
4306  /* Now recursively assign USING column names in children */
4307  set_using_names(dpns, j->larg, parentUsing);
4308  set_using_names(dpns, j->rarg, parentUsing);
4309  }
4310  else
4311  elog(ERROR, "unrecognized node type: %d",
4312  (int) nodeTag(jtnode));
4313 }
4314 
4315 /*
4316  * set_relation_column_names: select column aliases for a non-join RTE
4317  *
4318  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4319  * If any colnames entries are already filled in, those override local
4320  * choices.
4321  */
4322 static void
4324  deparse_columns *colinfo)
4325 {
4326  int ncolumns;
4327  char **real_colnames;
4328  bool changed_any;
4329  int noldcolumns;
4330  int i;
4331  int j;
4332 
4333  /*
4334  * Construct an array of the current "real" column names of the RTE.
4335  * real_colnames[] will be indexed by physical column number, with NULL
4336  * entries for dropped columns.
4337  */
4338  if (rte->rtekind == RTE_RELATION)
4339  {
4340  /* Relation --- look to the system catalogs for up-to-date info */
4341  Relation rel;
4342  TupleDesc tupdesc;
4343 
4344  rel = relation_open(rte->relid, AccessShareLock);
4345  tupdesc = RelationGetDescr(rel);
4346 
4347  ncolumns = tupdesc->natts;
4348  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4349 
4350  for (i = 0; i < ncolumns; i++)
4351  {
4352  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
4353 
4354  if (attr->attisdropped)
4355  real_colnames[i] = NULL;
4356  else
4357  real_colnames[i] = pstrdup(NameStr(attr->attname));
4358  }
4360  }
4361  else
4362  {
4363  /* Otherwise get the column names from eref or expandRTE() */
4364  List *colnames;
4365  ListCell *lc;
4366 
4367  /*
4368  * Functions returning composites have the annoying property that some
4369  * of the composite type's columns might have been dropped since the
4370  * query was parsed. If possible, use expandRTE() to handle that
4371  * case, since it has the tedious logic needed to find out about
4372  * dropped columns. However, if we're explaining a plan, then we
4373  * don't have rte->functions because the planner thinks that won't be
4374  * needed later, and that breaks expandRTE(). So in that case we have
4375  * to rely on rte->eref, which may lead us to report a dropped
4376  * column's old name; that seems close enough for EXPLAIN's purposes.
4377  *
4378  * For non-RELATION, non-FUNCTION RTEs, we can just look at rte->eref,
4379  * which should be sufficiently up-to-date: no other RTE types can
4380  * have columns get dropped from under them after parsing.
4381  */
4382  if (rte->rtekind == RTE_FUNCTION && rte->functions != NIL)
4383  {
4384  /* Since we're not creating Vars, rtindex etc. don't matter */
4385  expandRTE(rte, 1, 0, -1, true /* include dropped */ ,
4386  &colnames, NULL);
4387  }
4388  else
4389  colnames = rte->eref->colnames;
4390 
4391  ncolumns = list_length(colnames);
4392  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4393 
4394  i = 0;
4395  foreach(lc, colnames)
4396  {
4397  /*
4398  * If the column name we find here is an empty string, then it's a
4399  * dropped column, so change to NULL.
4400  */
4401  char *cname = strVal(lfirst(lc));
4402 
4403  if (cname[0] == '\0')
4404  cname = NULL;
4405  real_colnames[i] = cname;
4406  i++;
4407  }
4408  }
4409 
4410  /*
4411  * Ensure colinfo->colnames has a slot for each column. (It could be long
4412  * enough already, if we pushed down a name for the last column.) Note:
4413  * it's possible that there are now more columns than there were when the
4414  * query was parsed, ie colnames could be longer than rte->eref->colnames.
4415  * We must assign unique aliases to the new columns too, else there could
4416  * be unresolved conflicts when the view/rule is reloaded.
4417  */
4418  expand_colnames_array_to(colinfo, ncolumns);
4419  Assert(colinfo->num_cols == ncolumns);
4420 
4421  /*
4422  * Make sufficiently large new_colnames and is_new_col arrays, too.
4423  *
4424  * Note: because we leave colinfo->num_new_cols zero until after the loop,
4425  * colname_is_unique will not consult that array, which is fine because it
4426  * would only be duplicate effort.
4427  */
4428  colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
4429  colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
4430 
4431  /* If the RTE is wide enough, use a hash table to avoid O(N^2) costs */
4432  build_colinfo_names_hash(colinfo);
4433 
4434  /*
4435  * Scan the columns, select a unique alias for each one, and store it in
4436  * colinfo->colnames and colinfo->new_colnames. The former array has NULL
4437  * entries for dropped columns, the latter omits them. Also mark
4438  * new_colnames entries as to whether they are new since parse time; this
4439  * is the case for entries beyond the length of rte->eref->colnames.
4440  */
4441  noldcolumns = list_length(rte->eref->colnames);
4442  changed_any = false;
4443  j = 0;
4444  for (i = 0; i < ncolumns; i++)
4445  {
4446  char *real_colname = real_colnames[i];
4447  char *colname = colinfo->colnames[i];
4448 
4449  /* Skip dropped columns */
4450  if (real_colname == NULL)
4451  {
4452  Assert(colname == NULL); /* colnames[i] is already NULL */
4453  continue;
4454  }
4455 
4456  /* If alias already assigned, that's what to use */
4457  if (colname == NULL)
4458  {
4459  /* If user wrote an alias, prefer that over real column name */
4460  if (rte->alias && i < list_length(rte->alias->colnames))
4461  colname = strVal(list_nth(rte->alias->colnames, i));
4462  else
4463  colname = real_colname;
4464 
4465  /* Unique-ify and insert into colinfo */
4466  colname = make_colname_unique(colname, dpns, colinfo);
4467 
4468  colinfo->colnames[i] = colname;
4469  add_to_names_hash(colinfo, colname);
4470  }
4471 
4472  /* Put names of non-dropped columns in new_colnames[] too */
4473  colinfo->new_colnames[j] = colname;
4474  /* And mark them as new or not */
4475  colinfo->is_new_col[j] = (i >= noldcolumns);
4476  j++;
4477 
4478  /* Remember if any assigned aliases differ from "real" name */
4479  if (!changed_any && strcmp(colname, real_colname) != 0)
4480  changed_any = true;
4481  }
4482 
4483  /* We're now done needing the colinfo's names_hash */
4484  destroy_colinfo_names_hash(colinfo);
4485 
4486  /*
4487  * Set correct length for new_colnames[] array. (Note: if columns have
4488  * been added, colinfo->num_cols includes them, which is not really quite
4489  * right but is harmless, since any new columns must be at the end where
4490  * they won't affect varattnos of pre-existing columns.)
4491  */
4492  colinfo->num_new_cols = j;
4493 
4494  /*
4495  * For a relation RTE, we need only print the alias column names if any
4496  * are different from the underlying "real" names. For a function RTE,
4497  * always emit a complete column alias list; this is to protect against
4498  * possible instability of the default column names (eg, from altering
4499  * parameter names). For tablefunc RTEs, we never print aliases, because
4500  * the column names are part of the clause itself. For other RTE types,
4501  * print if we changed anything OR if there were user-written column
4502  * aliases (since the latter would be part of the underlying "reality").
4503  */
4504  if (rte->rtekind == RTE_RELATION)
4505  colinfo->printaliases = changed_any;
4506  else if (rte->rtekind == RTE_FUNCTION)
4507  colinfo->printaliases = true;
4508  else if (rte->rtekind == RTE_TABLEFUNC)
4509  colinfo->printaliases = false;
4510  else if (rte->alias && rte->alias->colnames != NIL)
4511  colinfo->printaliases = true;
4512  else
4513  colinfo->printaliases = changed_any;
4514 }
4515 
4516 /*
4517  * set_join_column_names: select column aliases for a join RTE
4518  *
4519  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4520  * If any colnames entries are already filled in, those override local
4521  * choices. Also, names for USING columns were already chosen by
4522  * set_using_names(). We further expect that column alias selection has been
4523  * completed for both input RTEs.
4524  */
4525 static void
4527  deparse_columns *colinfo)
4528 {
4529  deparse_columns *leftcolinfo;
4530  deparse_columns *rightcolinfo;
4531  bool changed_any;
4532  int noldcolumns;
4533  int nnewcolumns;
4534  Bitmapset *leftmerged = NULL;
4535  Bitmapset *rightmerged = NULL;
4536  int i;
4537  int j;
4538  int ic;
4539  int jc;
4540 
4541  /* Look up the previously-filled-in child deparse_columns structs */
4542  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4543  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4544 
4545  /*
4546  * Ensure colinfo->colnames has a slot for each column. (It could be long
4547  * enough already, if we pushed down a name for the last column.) Note:
4548  * it's possible that one or both inputs now have more columns than there
4549  * were when the query was parsed, but we'll deal with that below. We
4550  * only need entries in colnames for pre-existing columns.
4551  */
4552  noldcolumns = list_length(rte->eref->colnames);
4553  expand_colnames_array_to(colinfo, noldcolumns);
4554  Assert(colinfo->num_cols == noldcolumns);
4555 
4556  /* If the RTE is wide enough, use a hash table to avoid O(N^2) costs */
4557  build_colinfo_names_hash(colinfo);
4558 
4559  /*
4560  * Scan the join output columns, select an alias for each one, and store
4561  * it in colinfo->colnames. If there are USING columns, set_using_names()
4562  * already selected their names, so we can start the loop at the first
4563  * non-merged column.
4564  */
4565  changed_any = false;
4566  for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
4567  {
4568  char *colname = colinfo->colnames[i];
4569  char *real_colname;
4570 
4571  /* Join column must refer to at least one input column */
4572  Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
4573 
4574  /* Get the child column name */
4575  if (colinfo->leftattnos[i] > 0)
4576  real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
4577  else if (colinfo->rightattnos[i] > 0)
4578  real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
4579  else
4580  {
4581  /* We're joining system columns --- use eref name */
4582  real_colname = strVal(list_nth(rte->eref->colnames, i));
4583  }
4584 
4585  /* If child col has been dropped, no need to assign a join colname */
4586  if (real_colname == NULL)
4587  {
4588  colinfo->colnames[i] = NULL;
4589  continue;
4590  }
4591 
4592  /* In an unnamed join, just report child column names as-is */
4593  if (rte->alias == NULL)
4594  {
4595  colinfo->colnames[i] = real_colname;
4596  add_to_names_hash(colinfo, real_colname);
4597  continue;
4598  }
4599 
4600  /* If alias already assigned, that's what to use */
4601  if (colname == NULL)
4602  {
4603  /* If user wrote an alias, prefer that over real column name */
4604  if (rte->alias && i < list_length(rte->alias->colnames))
4605  colname = strVal(list_nth(rte->alias->colnames, i));
4606  else
4607  colname = real_colname;
4608 
4609  /* Unique-ify and insert into colinfo */
4610  colname = make_colname_unique(colname, dpns, colinfo);
4611 
4612  colinfo->colnames[i] = colname;
4613  add_to_names_hash(colinfo, colname);
4614  }
4615 
4616  /* Remember if any assigned aliases differ from "real" name */
4617  if (!changed_any && strcmp(colname, real_colname) != 0)
4618  changed_any = true;
4619  }
4620 
4621  /*
4622  * Calculate number of columns the join would have if it were re-parsed
4623  * now, and create storage for the new_colnames and is_new_col arrays.
4624  *
4625  * Note: colname_is_unique will be consulting new_colnames[] during the
4626  * loops below, so its not-yet-filled entries must be zeroes.
4627  */
4628  nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
4629  list_length(colinfo->usingNames);
4630  colinfo->num_new_cols = nnewcolumns;
4631  colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
4632  colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
4633 
4634  /*
4635  * Generating the new_colnames array is a bit tricky since any new columns
4636  * added since parse time must be inserted in the right places. This code
4637  * must match the parser, which will order a join's columns as merged
4638  * columns first (in USING-clause order), then non-merged columns from the
4639  * left input (in attnum order), then non-merged columns from the right
4640  * input (ditto). If one of the inputs is itself a join, its columns will
4641  * be ordered according to the same rule, which means newly-added columns
4642  * might not be at the end. We can figure out what's what by consulting
4643  * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
4644  *
4645  * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
4646  * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
4647  * meanings for the current child RTE.
4648  */
4649 
4650  /* Handle merged columns; they are first and can't be new */
4651  i = j = 0;
4652  while (i < noldcolumns &&
4653  colinfo->leftattnos[i] != 0 &&
4654  colinfo->rightattnos[i] != 0)
4655  {
4656  /* column name is already determined and known unique */
4657  colinfo->new_colnames[j] = colinfo->colnames[i];
4658  colinfo->is_new_col[j] = false;
4659 
4660  /* build bitmapsets of child attnums of merged columns */
4661  if (colinfo->leftattnos[i] > 0)
4662  leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
4663  if (colinfo->rightattnos[i] > 0)
4664  rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
4665 
4666  i++, j++;
4667  }
4668 
4669  /* Handle non-merged left-child columns */
4670  ic = 0;
4671  for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
4672  {
4673  char *child_colname = leftcolinfo->new_colnames[jc];
4674 
4675  if (!leftcolinfo->is_new_col[jc])
4676  {
4677  /* Advance ic to next non-dropped old column of left child */
4678  while (ic < leftcolinfo->num_cols &&
4679  leftcolinfo->colnames[ic] == NULL)
4680  ic++;
4681  Assert(ic < leftcolinfo->num_cols);
4682  ic++;
4683  /* If it is a merged column, we already processed it */
4684  if (bms_is_member(ic, leftmerged))
4685  continue;
4686  /* Else, advance i to the corresponding existing join column */
4687  while (i < colinfo->num_cols &&
4688  colinfo->colnames[i] == NULL)
4689  i++;
4690  Assert(i < colinfo->num_cols);
4691  Assert(ic == colinfo->leftattnos[i]);
4692  /* Use the already-assigned name of this column */
4693  colinfo->new_colnames[j] = colinfo->colnames[i];
4694  i++;
4695  }
4696  else
4697  {
4698  /*
4699  * Unique-ify the new child column name and assign, unless we're
4700  * in an unnamed join, in which case just copy
4701  */
4702  if (rte->alias != NULL)
4703  {
4704  colinfo->new_colnames[j] =
4705  make_colname_unique(child_colname, dpns, colinfo);
4706  if (!changed_any &&
4707  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4708  changed_any = true;
4709  }
4710  else
4711  colinfo->new_colnames[j] = child_colname;
4712  add_to_names_hash(colinfo, colinfo->new_colnames[j]);
4713  }
4714 
4715  colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
4716  j++;
4717  }
4718 
4719  /* Handle non-merged right-child columns in exactly the same way */
4720  ic = 0;
4721  for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
4722  {
4723  char *child_colname = rightcolinfo->new_colnames[jc];
4724 
4725  if (!rightcolinfo->is_new_col[jc])
4726  {
4727  /* Advance ic to next non-dropped old column of right child */
4728  while (ic < rightcolinfo->num_cols &&
4729  rightcolinfo->colnames[ic] == NULL)
4730  ic++;
4731  Assert(ic < rightcolinfo->num_cols);
4732  ic++;
4733  /* If it is a merged column, we already processed it */
4734  if (bms_is_member(ic, rightmerged))
4735  continue;
4736  /* Else, advance i to the corresponding existing join column */
4737  while (i < colinfo->num_cols &&
4738  colinfo->colnames[i] == NULL)
4739  i++;
4740  Assert(i < colinfo->num_cols);
4741  Assert(ic == colinfo->rightattnos[i]);
4742  /* Use the already-assigned name of this column */
4743  colinfo->new_colnames[j] = colinfo->colnames[i];
4744  i++;
4745  }
4746  else
4747  {
4748  /*
4749  * Unique-ify the new child column name and assign, unless we're
4750  * in an unnamed join, in which case just copy
4751  */
4752  if (rte->alias != NULL)
4753  {
4754  colinfo->new_colnames[j] =
4755  make_colname_unique(child_colname, dpns, colinfo);
4756  if (!changed_any &&
4757  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4758  changed_any = true;
4759  }
4760  else
4761  colinfo->new_colnames[j] = child_colname;
4762  add_to_names_hash(colinfo, colinfo->new_colnames[j]);
4763  }
4764 
4765  colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
4766  j++;
4767  }
4768 
4769  /* Assert we processed the right number of columns */
4770 #ifdef USE_ASSERT_CHECKING
4771  while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
4772  i++;
4773  Assert(i == colinfo->num_cols);
4774  Assert(j == nnewcolumns);
4775 #endif
4776 
4777  /* We're now done needing the colinfo's names_hash */
4778  destroy_colinfo_names_hash(colinfo);
4779 
4780  /*
4781  * For a named join, print column aliases if we changed any from the child
4782  * names. Unnamed joins cannot print aliases.
4783  */
4784  if (rte->alias != NULL)
4785  colinfo->printaliases = changed_any;
4786  else
4787  colinfo->printaliases = false;
4788 }
4789 
4790 /*
4791  * colname_is_unique: is colname distinct from already-chosen column names?
4792  *
4793  * dpns is query-wide info, colinfo is for the column's RTE
4794  */
4795 static bool
4796 colname_is_unique(const char *colname, deparse_namespace *dpns,
4797  deparse_columns *colinfo)
4798 {
4799  int i;
4800  ListCell *lc;
4801 
4802  /*
4803  * If we have a hash table, consult that instead of linearly scanning the
4804  * colinfo's strings.
4805  */
4806  if (colinfo->names_hash)
4807  {
4808  if (hash_search(colinfo->names_hash,
4809  colname,
4810  HASH_FIND,
4811  NULL) != NULL)
4812  return false;
4813  }
4814  else
4815  {
4816  /* Check against already-assigned column aliases within RTE */
4817  for (i = 0; i < colinfo->num_cols; i++)
4818  {
4819  char *oldname = colinfo->colnames[i];
4820 
4821  if (oldname && strcmp(oldname, colname) == 0)
4822  return false;
4823  }
4824 
4825  /*
4826  * If we're building a new_colnames array, check that too (this will
4827  * be partially but not completely redundant with the previous checks)
4828  */
4829  for (i = 0; i < colinfo->num_new_cols; i++)
4830  {
4831  char *oldname = colinfo->new_colnames[i];
4832 
4833  if (oldname && strcmp(oldname, colname) == 0)
4834  return false;
4835  }
4836 
4837  /*
4838  * Also check against names already assigned for parent-join USING
4839  * cols
4840  */
4841  foreach(lc, colinfo->parentUsing)
4842  {
4843  char *oldname = (char *) lfirst(lc);
4844 
4845  if (strcmp(oldname, colname) == 0)
4846  return false;
4847  }
4848  }
4849 
4850  /*
4851  * Also check against USING-column names that must be globally unique.
4852  * These are not hashed, but there should be few of them.
4853  */
4854  foreach(lc, dpns->using_names)
4855  {
4856  char *oldname = (char *) lfirst(lc);
4857 
4858  if (strcmp(oldname, colname) == 0)
4859  return false;
4860  }
4861 
4862  return true;
4863 }
4864 
4865 /*
4866  * make_colname_unique: modify colname if necessary to make it unique
4867  *
4868  * dpns is query-wide info, colinfo is for the column's RTE
4869  */
4870 static char *
4872  deparse_columns *colinfo)
4873 {
4874  /*
4875  * If the selected name isn't unique, append digits to make it so. For a
4876  * very long input name, we might have to truncate to stay within
4877  * NAMEDATALEN.
4878  */
4879  if (!colname_is_unique(colname, dpns, colinfo))
4880  {
4881  int colnamelen = strlen(colname);
4882  char *modname = (char *) palloc(colnamelen + 16);
4883  int i = 0;
4884 
4885  do
4886  {
4887  i++;
4888  for (;;)
4889  {
4890  memcpy(modname, colname, colnamelen);
4891  sprintf(modname + colnamelen, "_%d", i);
4892  if (strlen(modname) < NAMEDATALEN)
4893  break;
4894  /* drop chars from colname to keep all the digits */
4895  colnamelen = pg_mbcliplen(colname, colnamelen,
4896  colnamelen - 1);
4897  }
4898  } while (!colname_is_unique(modname, dpns, colinfo));
4899  colname = modname;
4900  }
4901  return colname;
4902 }
4903 
4904 /*
4905  * expand_colnames_array_to: make colinfo->colnames at least n items long
4906  *
4907  * Any added array entries are initialized to zero.
4908  */
4909 static void
4911 {
4912  if (n > colinfo->num_cols)
4913  {
4914  if (colinfo->colnames == NULL)
4915  colinfo->colnames = palloc0_array(char *, n);
4916  else
4917  colinfo->colnames = repalloc0_array(colinfo->colnames, char *, colinfo->num_cols, n);
4918  colinfo->num_cols = n;
4919  }
4920 }
4921 
4922 /*
4923  * build_colinfo_names_hash: optionally construct a hash table for colinfo
4924  */
4925 static void
4927 {
4928  HASHCTL hash_ctl;
4929  int i;
4930  ListCell *lc;
4931 
4932  /*
4933  * Use a hash table only for RTEs with at least 32 columns. (The cutoff
4934  * is somewhat arbitrary, but let's choose it so that this code does get
4935  * exercised in the regression tests.)
4936  */
4937  if (colinfo->num_cols < 32)
4938  return;
4939 
4940  /*
4941  * Set up the hash table. The entries are just strings with no other
4942  * payload.
4943  */
4944  hash_ctl.keysize = NAMEDATALEN;
4945  hash_ctl.entrysize = NAMEDATALEN;
4946  hash_ctl.hcxt = CurrentMemoryContext;
4947  colinfo->names_hash = hash_create("deparse_columns names",
4948  colinfo->num_cols + colinfo->num_new_cols,
4949  &hash_ctl,
4951 
4952  /*
4953  * Preload the hash table with any names already present (these would have
4954  * come from set_using_names).
4955  */
4956  for (i = 0; i < colinfo->num_cols; i++)
4957  {
4958  char *oldname = colinfo->colnames[i];
4959 
4960  if (oldname)
4961  add_to_names_hash(colinfo, oldname);
4962  }
4963 
4964  for (i = 0; i < colinfo->num_new_cols; i++)
4965  {
4966  char *oldname = colinfo->new_colnames[i];
4967 
4968  if (oldname)
4969  add_to_names_hash(colinfo, oldname);
4970  }
4971 
4972  foreach(lc, colinfo->parentUsing)
4973  {
4974  char *oldname = (char *) lfirst(lc);
4975 
4976  add_to_names_hash(colinfo, oldname);
4977  }
4978 }
4979 
4980 /*
4981  * add_to_names_hash: add a string to the names_hash, if we're using one
4982  */
4983 static void
4985 {
4986  if (colinfo->names_hash)
4987  (void) hash_search(colinfo->names_hash,
4988  name,
4989  HASH_ENTER,
4990  NULL);
4991 }
4992 
4993 /*
4994  * destroy_colinfo_names_hash: destroy hash table when done with it
4995  */
4996 static void
4998 {
4999  if (colinfo->names_hash)
5000  {
5001  hash_destroy(colinfo->names_hash);
5002  colinfo->names_hash = NULL;
5003  }
5004 }
5005 
5006 /*
5007  * identify_join_columns: figure out where columns of a join come from
5008  *
5009  * Fills the join-specific fields of the colinfo struct, except for
5010  * usingNames which is filled later.
5011  */
5012 static void
5014  deparse_columns *colinfo)
5015 {
5016  int numjoincols;
5017  int jcolno;
5018  int rcolno;
5019  ListCell *lc;
5020 
5021  /* Extract left/right child RT indexes */
5022  if (IsA(j->larg, RangeTblRef))
5023  colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
5024  else if (IsA(j->larg, JoinExpr))
5025  colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
5026  else
5027  elog(ERROR, "unrecognized node type in jointree: %d",
5028  (int) nodeTag(j->larg));
5029  if (IsA(j->rarg, RangeTblRef))
5030  colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
5031  else if (IsA(j->rarg, JoinExpr))
5032  colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
5033  else
5034  elog(ERROR, "unrecognized node type in jointree: %d",
5035  (int) nodeTag(j->rarg));
5036 
5037  /* Assert children will be processed earlier than join in second pass */
5038  Assert(colinfo->leftrti < j->rtindex);
5039  Assert(colinfo->rightrti < j->rtindex);
5040 
5041  /* Initialize result arrays with zeroes */
5042  numjoincols = list_length(jrte->joinaliasvars);
5043  Assert(numjoincols == list_length(jrte->eref->colnames));
5044  colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
5045  colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
5046 
5047  /*
5048  * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
5049  * Recall that the column(s) merged due to USING are the first column(s)
5050  * of the join output. We need not do anything special while scanning
5051  * joinleftcols, but while scanning joinrightcols we must distinguish
5052  * merged from unmerged columns.
5053  */
5054  jcolno = 0;
5055  foreach(lc, jrte->joinleftcols)
5056  {
5057  int leftattno = lfirst_int(lc);
5058 
5059  colinfo->leftattnos[jcolno++] = leftattno;
5060  }
5061  rcolno = 0;
5062  foreach(lc, jrte->joinrightcols)
5063  {
5064  int rightattno = lfirst_int(lc);
5065 
5066  if (rcolno < jrte->joinmergedcols) /* merged column? */
5067  colinfo->rightattnos[rcolno] = rightattno;
5068  else
5069  colinfo->rightattnos[jcolno++] = rightattno;
5070  rcolno++;
5071  }
5072  Assert(jcolno == numjoincols);
5073 }
5074 
5075 /*
5076  * get_rtable_name: convenience function to get a previously assigned RTE alias
5077  *
5078  * The RTE must belong to the topmost namespace level in "context".
5079  */
5080 static char *
5082 {
5083  deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
5084 
5085  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
5086  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
5087 }
5088 
5089 /*
5090  * set_deparse_plan: set up deparse_namespace to parse subexpressions
5091  * of a given Plan node
5092  *
5093  * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
5094  * and index_tlist fields. Caller must already have adjusted the ancestors
5095  * list if necessary. Note that the rtable, subplans, and ctes fields do
5096  * not need to change when shifting attention to different plan nodes in a
5097  * single plan tree.
5098  */
5099 static void
5101 {
5102  dpns->plan = plan;
5103 
5104  /*
5105  * We special-case Append and MergeAppend to pretend that the first child
5106  * plan is the OUTER referent; we have to interpret OUTER Vars in their
5107  * tlists according to one of the children, and the first one is the most
5108  * natural choice.
5109  */
5110  if (IsA(plan, Append))
5111  dpns->outer_plan = linitial(((Append *) plan)->appendplans);
5112  else if (IsA(plan, MergeAppend))
5113  dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
5114  else
5115  dpns->outer_plan = outerPlan(plan);
5116 
5117  if (dpns->outer_plan)
5118  dpns->outer_tlist = dpns->outer_plan->targetlist;
5119  else
5120  dpns->outer_tlist = NIL;
5121 
5122  /*
5123  * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
5124  * use OUTER because that could someday conflict with the normal meaning.)
5125  * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
5126  * For a WorkTableScan, locate the parent RecursiveUnion plan node and use
5127  * that as INNER referent.
5128  *
5129  * For MERGE, pretend the ModifyTable's source plan (its outer plan) is
5130  * INNER referent. This is the join from the target relation to the data
5131  * source, and all INNER_VAR Vars in other parts of the query refer to its
5132  * targetlist.
5133  *
5134  * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
5135  * excluded expression's tlist. (Similar to the SubqueryScan we don't want
5136  * to reuse OUTER, it's used for RETURNING in some modify table cases,
5137  * although not INSERT .. CONFLICT).
5138  */
5139  if (IsA(plan, SubqueryScan))
5140  dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
5141  else if (IsA(plan, CteScan))
5142  dpns->inner_plan = list_nth(dpns->subplans,
5143  ((CteScan *) plan)->ctePlanId - 1);
5144  else if (IsA(plan, WorkTableScan))
5145  dpns->inner_plan = find_recursive_union(dpns,
5146  (WorkTableScan *) plan);
5147  else if (IsA(plan, ModifyTable))
5148  {
5149  if (((ModifyTable *) plan)->operation == CMD_MERGE)
5150  dpns->inner_plan = outerPlan(plan);
5151  else
5152  dpns->inner_plan = plan;
5153  }
5154  else
5155  dpns->inner_plan = innerPlan(plan);
5156 
5157  if (IsA(plan, ModifyTable) && ((ModifyTable *) plan)->operation == CMD_INSERT)
5158  dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
5159  else if (dpns->inner_plan)
5160  dpns->inner_tlist = dpns->inner_plan->targetlist;
5161  else
5162  dpns->inner_tlist = NIL;
5163 
5164  /* Set up referent for INDEX_VAR Vars, if needed */
5165  if (IsA(plan, IndexOnlyScan))
5166  dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
5167  else if (IsA(plan, ForeignScan))
5168  dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
5169  else if (IsA(plan, CustomScan))
5170  dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
5171  else
5172  dpns->index_tlist = NIL;
5173 }
5174 
5175 /*
5176  * Locate the ancestor plan node that is the RecursiveUnion generating
5177  * the WorkTableScan's work table. We can match on wtParam, since that
5178  * should be unique within the plan tree.
5179  */
5180 static Plan *
5182 {
5183  ListCell *lc;
5184 
5185  foreach(lc, dpns->ancestors)
5186  {
5187  Plan *ancestor = (Plan *) lfirst(lc);
5188 
5189  if (IsA(ancestor, RecursiveUnion) &&
5190  ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
5191  return ancestor;
5192  }
5193  elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
5194  wtscan->wtParam);
5195  return NULL;
5196 }
5197 
5198 /*
5199  * push_child_plan: temporarily transfer deparsing attention to a child plan
5200  *
5201  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
5202  * deparse context in case the referenced expression itself uses
5203  * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
5204  * affecting levelsup issues (although in a Plan tree there really shouldn't
5205  * be any).
5206  *
5207  * Caller must provide a local deparse_namespace variable to save the
5208  * previous state for pop_child_plan.
5209  */
5210 static void
5212  deparse_namespace *save_dpns)
5213 {
5214  /* Save state for restoration later */
5215  *save_dpns = *dpns;
5216 
5217  /* Link current plan node into ancestors list */
5218  dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
5219 
5220  /* Set attention on selected child */
5221  set_deparse_plan(dpns, plan);
5222 }
5223 
5224 /*
5225  * pop_child_plan: undo the effects of push_child_plan
5226  */
5227 static void
5229 {
5230  List *ancestors;
5231 
5232  /* Get rid of ancestors list cell added by push_child_plan */
5233  ancestors = list_delete_first(dpns->ancestors);
5234 
5235  /* Restore fields changed by push_child_plan */
5236  *dpns = *save_dpns;
5237 
5238  /* Make sure dpns->ancestors is right (may be unnecessary) */
5239  dpns->ancestors = ancestors;
5240 }
5241 
5242 /*
5243  * push_ancestor_plan: temporarily transfer deparsing attention to an
5244  * ancestor plan
5245  *
5246  * When expanding a Param reference, we must adjust the deparse context
5247  * to match the plan node that contains the expression being printed;
5248  * otherwise we'd fail if that expression itself contains a Param or
5249  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
5250  *
5251  * The target ancestor is conveniently identified by the ListCell holding it
5252  * in dpns->ancestors.
5253  *
5254  * Caller must provide a local deparse_namespace variable to save the
5255  * previous state for pop_ancestor_plan.
5256  */
5257 static void
5259  deparse_namespace *save_dpns)
5260 {
5261  Plan *plan = (Plan *) lfirst(ancestor_cell);
5262 
5263  /* Save state for restoration later */
5264  *save_dpns = *dpns;
5265 
5266  /* Build a new ancestor list with just this node's ancestors */
5267  dpns->ancestors =
5268  list_copy_tail(dpns->ancestors,
5269  list_cell_number(dpns->ancestors, ancestor_cell) + 1);
5270 
5271  /* Set attention on selected ancestor */
5272  set_deparse_plan(dpns, plan);
5273 }
5274 
5275 /*
5276  * pop_ancestor_plan: undo the effects of push_ancestor_plan
5277  */
5278 static void
5280 {
5281  /* Free the ancestor list made in push_ancestor_plan */
5282  list_free(dpns->ancestors);
5283 
5284  /* Restore fields changed by push_ancestor_plan */
5285  *dpns = *save_dpns;
5286 }
5287 
5288 
5289 /* ----------
5290  * make_ruledef - reconstruct the CREATE RULE command
5291  * for a given pg_rewrite tuple
5292  * ----------
5293  */
5294 static void
5296  int prettyFlags)
5297 {
5298  char *rulename;
5299  char ev_type;
5300  Oid ev_class;
5301  bool is_instead;
5302  char *ev_qual;
5303  char *ev_action;
5304  List *actions;
5305  Relation ev_relation;
5306  TupleDesc viewResultDesc = NULL;
5307  int fno;
5308  Datum dat;
5309  bool isnull;
5310 
5311  /*
5312  * Get the attribute values from the rules tuple
5313  */
5314  fno = SPI_fnumber(rulettc, "rulename");
5315  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5316  Assert(!isnull);
5317  rulename = NameStr(*(DatumGetName(dat)));
5318 
5319  fno = SPI_fnumber(rulettc, "ev_type");
5320  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5321  Assert(!isnull);
5322  ev_type = DatumGetChar(dat);
5323 
5324  fno = SPI_fnumber(rulettc, "ev_class");
5325  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5326  Assert(!isnull);
5327  ev_class = DatumGetObjectId(dat);
5328 
5329  fno = SPI_fnumber(rulettc, "is_instead");
5330  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5331  Assert(!isnull);
5332  is_instead = DatumGetBool(dat);
5333 
5334  fno = SPI_fnumber(rulettc, "ev_qual");
5335  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5336  Assert(ev_qual != NULL);
5337 
5338  fno = SPI_fnumber(rulettc, "ev_action");
5339  ev_action = SPI_getvalue(ruletup, rulettc, fno);
5340  Assert(ev_action != NULL);
5341  actions = (List *) stringToNode(ev_action);
5342  if (actions == NIL)
5343  elog(ERROR, "invalid empty ev_action list");
5344 
5345  ev_relation = table_open(ev_class, AccessShareLock);
5346 
5347  /*
5348  * Build the rules definition text
5349  */
5350  appendStringInfo(buf, "CREATE RULE %s AS",
5351  quote_identifier(rulename));
5352 
5353  if (prettyFlags & PRETTYFLAG_INDENT)
5354  appendStringInfoString(buf, "\n ON ");
5355  else
5356  appendStringInfoString(buf, " ON ");
5357 
5358  /* The event the rule is fired for */
5359  switch (ev_type)
5360  {
5361  case '1':
5362  appendStringInfoString(buf, "SELECT");
5363  viewResultDesc = RelationGetDescr(ev_relation);
5364  break;
5365 
5366  case '2':
5367  appendStringInfoString(buf, "UPDATE");
5368  break;
5369 
5370  case '3':
5371  appendStringInfoString(buf, "INSERT");
5372  break;
5373 
5374  case '4':
5375  appendStringInfoString(buf, "DELETE");
5376  break;
5377 
5378  default:
5379  ereport(ERROR,
5380  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5381  errmsg("rule \"%s\" has unsupported event type %d",
5382  rulename, ev_type)));
5383  break;
5384  }
5385 
5386  /* The relation the rule is fired on */
5387  appendStringInfo(buf, " TO %s",
5388  (prettyFlags & PRETTYFLAG_SCHEMA) ?
5389  generate_relation_name(ev_class, NIL) :
5391 
5392  /* If the rule has an event qualification, add it */
5393  if (strcmp(ev_qual, "<>") != 0)
5394  {
5395  Node *qual;
5396  Query *query;
5398  deparse_namespace dpns;
5399 
5400  if (prettyFlags & PRETTYFLAG_INDENT)
5401  appendStringInfoString(buf, "\n ");
5402  appendStringInfoString(buf, " WHERE ");
5403 
5404  qual = stringToNode(ev_qual);
5405 
5406  /*
5407  * We need to make a context for recognizing any Vars in the qual
5408  * (which can only be references to OLD and NEW). Use the rtable of
5409  * the first query in the action list for this purpose.
5410  */
5411  query = (Query *) linitial(actions);
5412 
5413  /*
5414  * If the action is INSERT...SELECT, OLD/NEW have been pushed down
5415  * into the SELECT, and that's what we need to look at. (Ugly kluge
5416  * ... try to fix this when we redesign querytrees.)
5417  */
5418  query = getInsertSelectQuery(query, NULL);
5419 
5420  /* Must acquire locks right away; see notes in get_query_def() */
5421  AcquireRewriteLocks(query, false, false);
5422 
5423  context.buf = buf;
5424  context.namespaces = list_make1(&dpns);
5425  context.resultDesc = NULL;
5426  context.targetList = NIL;
5427  context.windowClause = NIL;
5428  context.varprefix = (list_length(query->rtable) != 1);
5429  context.prettyFlags = prettyFlags;
5430  context.wrapColumn = WRAP_COLUMN_DEFAULT;
5431  context.indentLevel = PRETTYINDENT_STD;
5432  context.colNamesVisible = true;
5433  context.inGroupBy = false;
5434  context.varInOrderBy = false;
5435  context.appendparents = NULL;
5436 
5437  set_deparse_for_query(&dpns, query, NIL);
5438 
5439  get_rule_expr(qual, &context, false);
5440  }
5441 
5442  appendStringInfoString(buf, " DO ");
5443 
5444  /* The INSTEAD keyword (if so) */
5445  if (is_instead)
5446  appendStringInfoString(buf, "INSTEAD ");
5447 
5448  /* Finally the rules actions */
5449  if (list_length(actions) > 1)
5450  {
5451  ListCell *action;
5452  Query *query;
5453 
5454  appendStringInfoChar(buf, '(');
5455  foreach(action, actions)
5456  {
5457  query = (Query *) lfirst(action);
5458  get_query_def(query, buf, NIL, viewResultDesc, true,
5459  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5460  if (prettyFlags)
5461  appendStringInfoString(buf, ";\n");
5462  else
5463  appendStringInfoString(buf, "; ");
5464  }
5465  appendStringInfoString(buf, ");");
5466  }
5467  else
5468  {
5469  Query *query;
5470 
5471  query = (Query *) linitial(actions);
5472  get_query_def(query, buf, NIL, viewResultDesc, true,
5473  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5474  appendStringInfoChar(buf, ';');
5475  }
5476 
5477  table_close(ev_relation, AccessShareLock);
5478 }
5479 
5480 
5481 /* ----------
5482  * make_viewdef - reconstruct the SELECT part of a
5483  * view rewrite rule
5484  * ----------
5485  */
5486 static void
5488  int prettyFlags, int wrapColumn)
5489 {
5490  Query *query;
5491  char ev_type;
5492