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