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