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