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