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