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