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