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