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