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-2016, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/utils/adt/ruleutils.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 
22 #include "access/amapi.h"
23 #include "access/htup_details.h"
24 #include "access/sysattr.h"
25 #include "catalog/dependency.h"
26 #include "catalog/indexing.h"
27 #include "catalog/pg_aggregate.h"
28 #include "catalog/pg_am.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_collation.h"
31 #include "catalog/pg_constraint.h"
32 #include "catalog/pg_depend.h"
33 #include "catalog/pg_language.h"
34 #include "catalog/pg_opclass.h"
35 #include "catalog/pg_operator.h"
36 #include "catalog/pg_proc.h"
37 #include "catalog/pg_trigger.h"
38 #include "catalog/pg_type.h"
39 #include "commands/defrem.h"
40 #include "commands/tablespace.h"
41 #include "common/keywords.h"
42 #include "executor/spi.h"
43 #include "funcapi.h"
44 #include "mb/pg_wchar.h"
45 #include "miscadmin.h"
46 #include "nodes/makefuncs.h"
47 #include "nodes/nodeFuncs.h"
48 #include "optimizer/tlist.h"
49 #include "parser/parse_node.h"
50 #include "parser/parse_agg.h"
51 #include "parser/parse_func.h"
52 #include "parser/parse_oper.h"
53 #include "parser/parser.h"
54 #include "parser/parsetree.h"
55 #include "rewrite/rewriteHandler.h"
56 #include "rewrite/rewriteManip.h"
57 #include "rewrite/rewriteSupport.h"
58 #include "utils/array.h"
59 #include "utils/builtins.h"
60 #include "utils/fmgroids.h"
61 #include "utils/hsearch.h"
62 #include "utils/lsyscache.h"
63 #include "utils/rel.h"
64 #include "utils/ruleutils.h"
65 #include "utils/snapmgr.h"
66 #include "utils/syscache.h"
67 #include "utils/tqual.h"
68 #include "utils/typcache.h"
69 #include "utils/xml.h"
70 
71 
72 /* ----------
73  * Pretty formatting constants
74  * ----------
75  */
76 
77 /* Indent counts */
78 #define PRETTYINDENT_STD 8
79 #define PRETTYINDENT_JOIN 4
80 #define PRETTYINDENT_VAR 4
81 
82 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
83 
84 /* Pretty flags */
85 #define PRETTYFLAG_PAREN 1
86 #define PRETTYFLAG_INDENT 2
87 
88 /* Default line length for pretty-print wrapping: 0 means wrap always */
89 #define WRAP_COLUMN_DEFAULT 0
90 
91 /* macro to test if pretty action needed */
92 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
93 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
94 
95 
96 /* ----------
97  * Local data types
98  * ----------
99  */
100 
101 /* Context info needed for invoking a recursive querytree display routine */
102 typedef struct
103 {
104  StringInfo buf; /* output buffer to append to */
105  List *namespaces; /* List of deparse_namespace nodes */
106  List *windowClause; /* Current query level's WINDOW clause */
107  List *windowTList; /* targetlist for resolving WINDOW clause */
108  int prettyFlags; /* enabling of pretty-print functions */
109  int wrapColumn; /* max line length, or -1 for no limit */
110  int indentLevel; /* current indent level for prettyprint */
111  bool varprefix; /* TRUE to print prefixes on Vars */
112  ParseExprKind special_exprkind; /* set only for exprkinds needing
113  * special handling */
115 
116 /*
117  * Each level of query context around a subtree needs a level of Var namespace.
118  * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
119  * the current context's namespaces list.
120  *
121  * The rangetable is the list of actual RTEs from the query tree, and the
122  * cte list is the list of actual CTEs.
123  *
124  * rtable_names holds the alias name to be used for each RTE (either a C
125  * string, or NULL for nameless RTEs such as unnamed joins).
126  * rtable_columns holds the column alias names to be used for each RTE.
127  *
128  * In some cases we need to make names of merged JOIN USING columns unique
129  * across the whole query, not only per-RTE. If so, unique_using is TRUE
130  * and using_names is a list of C strings representing names already assigned
131  * to USING columns.
132  *
133  * When deparsing plan trees, there is always just a single item in the
134  * deparse_namespace list (since a plan tree never contains Vars with
135  * varlevelsup > 0). We store the PlanState node that is the immediate
136  * parent of the expression to be deparsed, as well as a list of that
137  * PlanState's ancestors. In addition, we store its outer and inner subplan
138  * state nodes, as well as their plan nodes' targetlists, and the index tlist
139  * if the current plan node might contain INDEX_VAR Vars. (These fields could
140  * be derived on-the-fly from the current PlanState, but it seems notationally
141  * clearer to set them up as separate fields.)
142  */
143 typedef struct
144 {
145  List *rtable; /* List of RangeTblEntry nodes */
146  List *rtable_names; /* Parallel list of names for RTEs */
147  List *rtable_columns; /* Parallel list of deparse_columns structs */
148  List *ctes; /* List of CommonTableExpr nodes */
149  /* Workspace for column alias assignment: */
150  bool unique_using; /* Are we making USING names globally unique */
151  List *using_names; /* List of assigned names for USING columns */
152  /* Remaining fields are used only when deparsing a Plan tree: */
153  PlanState *planstate; /* immediate parent of current expression */
154  List *ancestors; /* ancestors of planstate */
155  PlanState *outer_planstate; /* outer subplan state, or NULL if none */
156  PlanState *inner_planstate; /* inner subplan state, or NULL if none */
157  List *outer_tlist; /* referent for OUTER_VAR Vars */
158  List *inner_tlist; /* referent for INNER_VAR Vars */
159  List *index_tlist; /* referent for INDEX_VAR Vars */
161 
162 /*
163  * Per-relation data about column alias names.
164  *
165  * Selecting aliases is unreasonably complicated because of the need to dump
166  * rules/views whose underlying tables may have had columns added, deleted, or
167  * renamed since the query was parsed. We must nonetheless print the rule/view
168  * in a form that can be reloaded and will produce the same results as before.
169  *
170  * For each RTE used in the query, we must assign column aliases that are
171  * unique within that RTE. SQL does not require this of the original query,
172  * but due to factors such as *-expansion we need to be able to uniquely
173  * reference every column in a decompiled query. As long as we qualify all
174  * column references, per-RTE uniqueness is sufficient for that.
175  *
176  * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
177  * since they just inherit column names from their input RTEs, and we can't
178  * rename the columns at the join level. Most of the time this isn't an issue
179  * because we don't need to reference the join's output columns as such; we
180  * can reference the input columns instead. That approach can fail for merged
181  * JOIN USING columns, however, so when we have one of those in an unnamed
182  * join, we have to make that column's alias globally unique across the whole
183  * query to ensure it can be referenced unambiguously.
184  *
185  * Another problem is that a JOIN USING clause requires the columns to be
186  * merged to have the same aliases in both input RTEs, and that no other
187  * columns in those RTEs or their children conflict with the USING names.
188  * To handle that, we do USING-column alias assignment in a recursive
189  * traversal of the query's jointree. When descending through a JOIN with
190  * USING, we preassign the USING column names to the child columns, overriding
191  * other rules for column alias assignment. We also mark each RTE with a list
192  * of all USING column names selected for joins containing that RTE, so that
193  * when we assign other columns' aliases later, we can avoid conflicts.
194  *
195  * Another problem is that if a JOIN's input tables have had columns added or
196  * deleted since the query was parsed, we must generate a column alias list
197  * for the join that matches the current set of input columns --- otherwise, a
198  * change in the number of columns in the left input would throw off matching
199  * of aliases to columns of the right input. Thus, positions in the printable
200  * column alias list are not necessarily one-for-one with varattnos of the
201  * JOIN, so we need a separate new_colnames[] array for printing purposes.
202  */
203 typedef struct
204 {
205  /*
206  * colnames is an array containing column aliases to use for columns that
207  * existed when the query was parsed. Dropped columns have NULL entries.
208  * This array can be directly indexed by varattno to get a Var's name.
209  *
210  * Non-NULL entries are guaranteed unique within the RTE, *except* when
211  * this is for an unnamed JOIN RTE. In that case we merely copy up names
212  * from the two input RTEs.
213  *
214  * During the recursive descent in set_using_names(), forcible assignment
215  * of a child RTE's column name is represented by pre-setting that element
216  * of the child's colnames array. So at that stage, NULL entries in this
217  * array just mean that no name has been preassigned, not necessarily that
218  * the column is dropped.
219  */
220  int num_cols; /* length of colnames[] array */
221  char **colnames; /* array of C strings and NULLs */
222 
223  /*
224  * new_colnames is an array containing column aliases to use for columns
225  * that would exist if the query was re-parsed against the current
226  * definitions of its base tables. This is what to print as the column
227  * alias list for the RTE. This array does not include dropped columns,
228  * but it will include columns added since original parsing. Indexes in
229  * it therefore have little to do with current varattno values. As above,
230  * entries are unique unless this is for an unnamed JOIN RTE. (In such an
231  * RTE, we never actually print this array, but we must compute it anyway
232  * for possible use in computing column names of upper joins.) The
233  * parallel array is_new_col marks which of these columns are new since
234  * original parsing. Entries with is_new_col false must match the
235  * non-NULL colnames entries one-for-one.
236  */
237  int num_new_cols; /* length of new_colnames[] array */
238  char **new_colnames; /* array of C strings */
239  bool *is_new_col; /* array of bool flags */
240 
241  /* This flag tells whether we should actually print a column alias list */
243 
244  /* This list has all names used as USING names in joins above this RTE */
245  List *parentUsing; /* names assigned to parent merged columns */
246 
247  /*
248  * If this struct is for a JOIN RTE, we fill these fields during the
249  * set_using_names() pass to describe its relationship to its child RTEs.
250  *
251  * leftattnos and rightattnos are arrays with one entry per existing
252  * output column of the join (hence, indexable by join varattno). For a
253  * simple reference to a column of the left child, leftattnos[i] is the
254  * child RTE's attno and rightattnos[i] is zero; and conversely for a
255  * column of the right child. But for merged columns produced by JOIN
256  * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
257  * Also, if the column has been dropped, both are zero.
258  *
259  * If it's a JOIN USING, usingNames holds the alias names selected for the
260  * merged columns (these might be different from the original USING list,
261  * if we had to modify names to achieve uniqueness).
262  */
263  int leftrti; /* rangetable index of left child */
264  int rightrti; /* rangetable index of right child */
265  int *leftattnos; /* left-child varattnos of join cols, or 0 */
266  int *rightattnos; /* right-child varattnos of join cols, or 0 */
267  List *usingNames; /* names assigned to merged columns */
269 
270 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
271 #define deparse_columns_fetch(rangetable_index, dpns) \
272  ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
273 
274 /*
275  * Entry in set_rtable_names' hash table
276  */
277 typedef struct
278 {
279  char name[NAMEDATALEN]; /* Hash key --- must be first */
280  int counter; /* Largest addition used so far for name */
281 } NameHashEntry;
282 
283 
284 /* ----------
285  * Global data
286  * ----------
287  */
289 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
291 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
292 
293 /* GUC parameters */
295 
296 
297 /* ----------
298  * Local functions
299  *
300  * Most of these functions used to use fixed-size buffers to build their
301  * results. Now, they take an (already initialized) StringInfo object
302  * as a parameter, and append their text output to its contents.
303  * ----------
304  */
305 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
306  bool forceprefix, bool showimplicit,
307  int prettyFlags, int startIndent);
308 static char *pg_get_viewdef_worker(Oid viewoid,
309  int prettyFlags, int wrapColumn);
310 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
311 static void decompile_column_index_array(Datum column_index_array, Oid relId,
312  StringInfo buf);
313 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
314 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
315  const Oid *excludeOps,
316  bool attrsOnly, bool showTblSpc,
317  int prettyFlags);
318 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
319  int prettyFlags);
320 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
321  int prettyFlags);
323  bool print_table_args, bool print_defaults);
324 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
325 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
326 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
327  Bitmapset *rels_used);
328 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
329  List *parent_namespaces);
330 static void set_simple_column_names(deparse_namespace *dpns);
331 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
332 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
333  List *parentUsing);
335  RangeTblEntry *rte,
336  deparse_columns *colinfo);
338  deparse_columns *colinfo);
339 static bool colname_is_unique(char *colname, deparse_namespace *dpns,
340  deparse_columns *colinfo);
341 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
342  deparse_columns *colinfo);
343 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
344 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
345  deparse_columns *colinfo);
346 static void flatten_join_using_qual(Node *qual,
347  List **leftvars, List **rightvars);
348 static char *get_rtable_name(int rtindex, deparse_context *context);
349 static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps);
350 static void push_child_plan(deparse_namespace *dpns, PlanState *ps,
351  deparse_namespace *save_dpns);
352 static void pop_child_plan(deparse_namespace *dpns,
353  deparse_namespace *save_dpns);
354 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
355  deparse_namespace *save_dpns);
356 static void pop_ancestor_plan(deparse_namespace *dpns,
357  deparse_namespace *save_dpns);
358 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
359  int prettyFlags);
360 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
361  int prettyFlags, int wrapColumn);
362 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
363  TupleDesc resultDesc,
364  int prettyFlags, int wrapColumn, int startIndent);
365 static void get_values_def(List *values_lists, deparse_context *context);
366 static void get_with_clause(Query *query, deparse_context *context);
367 static void get_select_query_def(Query *query, deparse_context *context,
368  TupleDesc resultDesc);
369 static void get_insert_query_def(Query *query, deparse_context *context);
370 static void get_update_query_def(Query *query, deparse_context *context);
371 static void get_update_query_targetlist_def(Query *query, List *targetList,
372  deparse_context *context,
373  RangeTblEntry *rte);
374 static void get_delete_query_def(Query *query, deparse_context *context);
375 static void get_utility_query_def(Query *query, deparse_context *context);
376 static void get_basic_select_query(Query *query, deparse_context *context,
377  TupleDesc resultDesc);
378 static void get_target_list(List *targetList, deparse_context *context,
379  TupleDesc resultDesc);
380 static void get_setop_query(Node *setOp, Query *query,
381  deparse_context *context,
382  TupleDesc resultDesc);
383 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
384  bool force_colno,
385  deparse_context *context);
386 static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
387  bool omit_parens, deparse_context *context);
388 static void get_rule_orderby(List *orderList, List *targetList,
389  bool force_colno, deparse_context *context);
390 static void get_rule_windowclause(Query *query, deparse_context *context);
391 static void get_rule_windowspec(WindowClause *wc, List *targetList,
392  deparse_context *context);
393 static char *get_variable(Var *var, int levelsup, bool istoplevel,
394  deparse_context *context);
395 static void get_special_variable(Node *node, deparse_context *context,
396  void *private);
397 static void resolve_special_varno(Node *node, deparse_context *context,
398  void *private,
399  void (*callback) (Node *, deparse_context *, void *));
400 static Node *find_param_referent(Param *param, deparse_context *context,
401  deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
402 static void get_parameter(Param *param, deparse_context *context);
403 static const char *get_simple_binary_op_name(OpExpr *expr);
404 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
405 static void appendContextKeyword(deparse_context *context, const char *str,
406  int indentBefore, int indentAfter, int indentPlus);
407 static void removeStringInfoSpaces(StringInfo str);
408 static void get_rule_expr(Node *node, deparse_context *context,
409  bool showimplicit);
410 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
411  bool showimplicit);
412 static void get_oper_expr(OpExpr *expr, deparse_context *context);
413 static void get_func_expr(FuncExpr *expr, deparse_context *context,
414  bool showimplicit);
415 static void get_agg_expr(Aggref *aggref, deparse_context *context,
416  Aggref *original_aggref);
417 static void get_agg_combine_expr(Node *node, deparse_context *context,
418  void *private);
419 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
420 static void get_coercion_expr(Node *arg, deparse_context *context,
421  Oid resulttype, int32 resulttypmod,
422  Node *parentNode);
423 static void get_const_expr(Const *constval, deparse_context *context,
424  int showtype);
425 static void get_const_collation(Const *constval, deparse_context *context);
426 static void simple_quote_literal(StringInfo buf, const char *val);
427 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
428 static void get_from_clause(Query *query, const char *prefix,
429  deparse_context *context);
430 static void get_from_clause_item(Node *jtnode, Query *query,
431  deparse_context *context);
432 static void get_column_alias_list(deparse_columns *colinfo,
433  deparse_context *context);
434 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
435  deparse_columns *colinfo,
436  deparse_context *context);
437 static void get_tablesample_def(TableSampleClause *tablesample,
438  deparse_context *context);
439 static void get_opclass_name(Oid opclass, Oid actual_datatype,
440  StringInfo buf);
441 static Node *processIndirection(Node *node, deparse_context *context,
442  bool printit);
443 static void printSubscripts(ArrayRef *aref, deparse_context *context);
444 static char *get_relation_name(Oid relid);
445 static char *generate_relation_name(Oid relid, List *namespaces);
446 static char *generate_qualified_relation_name(Oid relid);
447 static char *generate_function_name(Oid funcid, int nargs,
448  List *argnames, Oid *argtypes,
449  bool has_variadic, bool *use_variadic_p,
450  ParseExprKind special_exprkind);
451 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
452 static text *string_to_text(char *str);
453 static char *flatten_reloptions(Oid relid);
454 
455 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
456 
457 
458 /* ----------
459  * get_ruledef - Do it all and return a text
460  * that could be used as a statement
461  * to recreate the rule
462  * ----------
463  */
464 Datum
466 {
467  Oid ruleoid = PG_GETARG_OID(0);
468  int prettyFlags;
469 
470  prettyFlags = PRETTYFLAG_INDENT;
471  PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
472 }
473 
474 
475 Datum
477 {
478  Oid ruleoid = PG_GETARG_OID(0);
479  bool pretty = PG_GETARG_BOOL(1);
480  int prettyFlags;
481 
482  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
483  PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
484 }
485 
486 
487 static char *
488 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
489 {
490  Datum args[1];
491  char nulls[1];
492  int spirc;
493  HeapTuple ruletup;
494  TupleDesc rulettc;
496 
497  /*
498  * Do this first so that string is alloc'd in outer context not SPI's.
499  */
500  initStringInfo(&buf);
501 
502  /*
503  * Connect to SPI manager
504  */
505  if (SPI_connect() != SPI_OK_CONNECT)
506  elog(ERROR, "SPI_connect failed");
507 
508  /*
509  * On the first call prepare the plan to lookup pg_rewrite. We read
510  * pg_rewrite over the SPI manager instead of using the syscache to be
511  * checked for read access on pg_rewrite.
512  */
513  if (plan_getrulebyoid == NULL)
514  {
515  Oid argtypes[1];
516  SPIPlanPtr plan;
517 
518  argtypes[0] = OIDOID;
519  plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
520  if (plan == NULL)
521  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
522  SPI_keepplan(plan);
523  plan_getrulebyoid = plan;
524  }
525 
526  /*
527  * Get the pg_rewrite tuple for this rule
528  */
529  args[0] = ObjectIdGetDatum(ruleoid);
530  nulls[0] = ' ';
531  spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
532  if (spirc != SPI_OK_SELECT)
533  elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
534  if (SPI_processed != 1)
535  appendStringInfoChar(&buf, '-');
536  else
537  {
538  /*
539  * Get the rule's definition and put it into executor's memory
540  */
541  ruletup = SPI_tuptable->vals[0];
542  rulettc = SPI_tuptable->tupdesc;
543  make_ruledef(&buf, ruletup, rulettc, prettyFlags);
544  }
545 
546  /*
547  * Disconnect from SPI manager
548  */
549  if (SPI_finish() != SPI_OK_FINISH)
550  elog(ERROR, "SPI_finish failed");
551 
552  return buf.data;
553 }
554 
555 
556 /* ----------
557  * get_viewdef - Mainly the same thing, but we
558  * only return the SELECT part of a view
559  * ----------
560  */
561 Datum
563 {
564  /* By OID */
565  Oid viewoid = PG_GETARG_OID(0);
566  int prettyFlags;
567 
568  prettyFlags = PRETTYFLAG_INDENT;
570 }
571 
572 
573 Datum
575 {
576  /* By OID */
577  Oid viewoid = PG_GETARG_OID(0);
578  bool pretty = PG_GETARG_BOOL(1);
579  int prettyFlags;
580 
581  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
583 }
584 
585 Datum
587 {
588  /* By OID */
589  Oid viewoid = PG_GETARG_OID(0);
590  int wrap = PG_GETARG_INT32(1);
591  int prettyFlags;
592 
593  /* calling this implies we want pretty printing */
594  prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT;
595  PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags, wrap)));
596 }
597 
598 Datum
600 {
601  /* By qualified name */
602  text *viewname = PG_GETARG_TEXT_P(0);
603  int prettyFlags;
604  RangeVar *viewrel;
605  Oid viewoid;
606 
607  prettyFlags = PRETTYFLAG_INDENT;
608 
609  /* Look up view name. Can't lock it - we might not have privileges. */
611  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
612 
614 }
615 
616 
617 Datum
619 {
620  /* By qualified name */
621  text *viewname = PG_GETARG_TEXT_P(0);
622  bool pretty = PG_GETARG_BOOL(1);
623  int prettyFlags;
624  RangeVar *viewrel;
625  Oid viewoid;
626 
627  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
628 
629  /* Look up view name. Can't lock it - we might not have privileges. */
631  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
632 
634 }
635 
636 /*
637  * Common code for by-OID and by-name variants of pg_get_viewdef
638  */
639 static char *
640 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
641 {
642  Datum args[2];
643  char nulls[2];
644  int spirc;
645  HeapTuple ruletup;
646  TupleDesc rulettc;
648 
649  /*
650  * Do this first so that string is alloc'd in outer context not SPI's.
651  */
652  initStringInfo(&buf);
653 
654  /*
655  * Connect to SPI manager
656  */
657  if (SPI_connect() != SPI_OK_CONNECT)
658  elog(ERROR, "SPI_connect failed");
659 
660  /*
661  * On the first call prepare the plan to lookup pg_rewrite. We read
662  * pg_rewrite over the SPI manager instead of using the syscache to be
663  * checked for read access on pg_rewrite.
664  */
665  if (plan_getviewrule == NULL)
666  {
667  Oid argtypes[2];
668  SPIPlanPtr plan;
669 
670  argtypes[0] = OIDOID;
671  argtypes[1] = NAMEOID;
672  plan = SPI_prepare(query_getviewrule, 2, argtypes);
673  if (plan == NULL)
674  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
675  SPI_keepplan(plan);
676  plan_getviewrule = plan;
677  }
678 
679  /*
680  * Get the pg_rewrite tuple for the view's SELECT rule
681  */
682  args[0] = ObjectIdGetDatum(viewoid);
684  nulls[0] = ' ';
685  nulls[1] = ' ';
686  spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
687  if (spirc != SPI_OK_SELECT)
688  elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
689  if (SPI_processed != 1)
690  appendStringInfoString(&buf, "Not a view");
691  else
692  {
693  /*
694  * Get the rule's definition and put it into executor's memory
695  */
696  ruletup = SPI_tuptable->vals[0];
697  rulettc = SPI_tuptable->tupdesc;
698  make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
699  }
700 
701  /*
702  * Disconnect from SPI manager
703  */
704  if (SPI_finish() != SPI_OK_FINISH)
705  elog(ERROR, "SPI_finish failed");
706 
707  return buf.data;
708 }
709 
710 /* ----------
711  * get_triggerdef - Get the definition of a trigger
712  * ----------
713  */
714 Datum
716 {
717  Oid trigid = PG_GETARG_OID(0);
718 
720 }
721 
722 Datum
724 {
725  Oid trigid = PG_GETARG_OID(0);
726  bool pretty = PG_GETARG_BOOL(1);
727 
729 }
730 
731 static char *
732 pg_get_triggerdef_worker(Oid trigid, bool pretty)
733 {
734  HeapTuple ht_trig;
735  Form_pg_trigger trigrec;
737  Relation tgrel;
738  ScanKeyData skey[1];
739  SysScanDesc tgscan;
740  int findx = 0;
741  char *tgname;
742  Oid argtypes[1]; /* dummy */
743  Datum value;
744  bool isnull;
745 
746  /*
747  * Fetch the pg_trigger tuple by the Oid of the trigger
748  */
750 
751  ScanKeyInit(&skey[0],
753  BTEqualStrategyNumber, F_OIDEQ,
754  ObjectIdGetDatum(trigid));
755 
756  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
757  NULL, 1, skey);
758 
759  ht_trig = systable_getnext(tgscan);
760 
761  if (!HeapTupleIsValid(ht_trig))
762  elog(ERROR, "could not find tuple for trigger %u", trigid);
763 
764  trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
765 
766  /*
767  * Start the trigger definition. Note that the trigger's name should never
768  * be schema-qualified, but the trigger rel's name may be.
769  */
770  initStringInfo(&buf);
771 
772  tgname = NameStr(trigrec->tgname);
773  appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
774  OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
775  quote_identifier(tgname));
776 
777  if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
778  appendStringInfoString(&buf, "BEFORE");
779  else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
780  appendStringInfoString(&buf, "AFTER");
781  else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
782  appendStringInfoString(&buf, "INSTEAD OF");
783  else
784  elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
785 
786  if (TRIGGER_FOR_INSERT(trigrec->tgtype))
787  {
788  appendStringInfoString(&buf, " INSERT");
789  findx++;
790  }
791  if (TRIGGER_FOR_DELETE(trigrec->tgtype))
792  {
793  if (findx > 0)
794  appendStringInfoString(&buf, " OR DELETE");
795  else
796  appendStringInfoString(&buf, " DELETE");
797  findx++;
798  }
799  if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
800  {
801  if (findx > 0)
802  appendStringInfoString(&buf, " OR UPDATE");
803  else
804  appendStringInfoString(&buf, " UPDATE");
805  findx++;
806  /* tgattr is first var-width field, so OK to access directly */
807  if (trigrec->tgattr.dim1 > 0)
808  {
809  int i;
810 
811  appendStringInfoString(&buf, " OF ");
812  for (i = 0; i < trigrec->tgattr.dim1; i++)
813  {
814  char *attname;
815 
816  if (i > 0)
817  appendStringInfoString(&buf, ", ");
818  attname = get_relid_attribute_name(trigrec->tgrelid,
819  trigrec->tgattr.values[i]);
821  }
822  }
823  }
824  if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
825  {
826  if (findx > 0)
827  appendStringInfoString(&buf, " OR TRUNCATE");
828  else
829  appendStringInfoString(&buf, " TRUNCATE");
830  findx++;
831  }
832  appendStringInfo(&buf, " ON %s ",
833  generate_relation_name(trigrec->tgrelid, NIL));
834 
835  if (OidIsValid(trigrec->tgconstraint))
836  {
837  if (OidIsValid(trigrec->tgconstrrelid))
838  appendStringInfo(&buf, "FROM %s ",
839  generate_relation_name(trigrec->tgconstrrelid, NIL));
840  if (!trigrec->tgdeferrable)
841  appendStringInfoString(&buf, "NOT ");
842  appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
843  if (trigrec->tginitdeferred)
844  appendStringInfoString(&buf, "DEFERRED ");
845  else
846  appendStringInfoString(&buf, "IMMEDIATE ");
847  }
848 
849  if (TRIGGER_FOR_ROW(trigrec->tgtype))
850  appendStringInfoString(&buf, "FOR EACH ROW ");
851  else
852  appendStringInfoString(&buf, "FOR EACH STATEMENT ");
853 
854  /* If the trigger has a WHEN qualification, add that */
855  value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
856  tgrel->rd_att, &isnull);
857  if (!isnull)
858  {
859  Node *qual;
860  char relkind;
861  deparse_context context;
862  deparse_namespace dpns;
863  RangeTblEntry *oldrte;
864  RangeTblEntry *newrte;
865 
866  appendStringInfoString(&buf, "WHEN (");
867 
868  qual = stringToNode(TextDatumGetCString(value));
869 
870  relkind = get_rel_relkind(trigrec->tgrelid);
871 
872  /* Build minimal OLD and NEW RTEs for the rel */
873  oldrte = makeNode(RangeTblEntry);
874  oldrte->rtekind = RTE_RELATION;
875  oldrte->relid = trigrec->tgrelid;
876  oldrte->relkind = relkind;
877  oldrte->alias = makeAlias("old", NIL);
878  oldrte->eref = oldrte->alias;
879  oldrte->lateral = false;
880  oldrte->inh = false;
881  oldrte->inFromCl = true;
882 
883  newrte = makeNode(RangeTblEntry);
884  newrte->rtekind = RTE_RELATION;
885  newrte->relid = trigrec->tgrelid;
886  newrte->relkind = relkind;
887  newrte->alias = makeAlias("new", NIL);
888  newrte->eref = newrte->alias;
889  newrte->lateral = false;
890  newrte->inh = false;
891  newrte->inFromCl = true;
892 
893  /* Build two-element rtable */
894  memset(&dpns, 0, sizeof(dpns));
895  dpns.rtable = list_make2(oldrte, newrte);
896  dpns.ctes = NIL;
897  set_rtable_names(&dpns, NIL, NULL);
899 
900  /* Set up context with one-deep namespace stack */
901  context.buf = &buf;
902  context.namespaces = list_make1(&dpns);
903  context.windowClause = NIL;
904  context.windowTList = NIL;
905  context.varprefix = true;
908  context.indentLevel = PRETTYINDENT_STD;
910 
911  get_rule_expr(qual, &context, false);
912 
913  appendStringInfoString(&buf, ") ");
914  }
915 
916  appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
917  generate_function_name(trigrec->tgfoid, 0,
918  NIL, argtypes,
919  false, NULL, EXPR_KIND_NONE));
920 
921  if (trigrec->tgnargs > 0)
922  {
923  char *p;
924  int i;
925 
926  value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
927  tgrel->rd_att, &isnull);
928  if (isnull)
929  elog(ERROR, "tgargs is null for trigger %u", trigid);
930  p = (char *) VARDATA(DatumGetByteaP(value));
931  for (i = 0; i < trigrec->tgnargs; i++)
932  {
933  if (i > 0)
934  appendStringInfoString(&buf, ", ");
935  simple_quote_literal(&buf, p);
936  /* advance p to next string embedded in tgargs */
937  while (*p)
938  p++;
939  p++;
940  }
941  }
942 
943  /* We deliberately do not put semi-colon at end */
944  appendStringInfoChar(&buf, ')');
945 
946  /* Clean up */
947  systable_endscan(tgscan);
948 
949  heap_close(tgrel, AccessShareLock);
950 
951  return buf.data;
952 }
953 
954 /* ----------
955  * get_indexdef - Get the definition of an index
956  *
957  * In the extended version, there is a colno argument as well as pretty bool.
958  * if colno == 0, we want a complete index definition.
959  * if colno > 0, we only want the Nth index key's variable or expression.
960  *
961  * Note that the SQL-function versions of this omit any info about the
962  * index tablespace; this is intentional because pg_dump wants it that way.
963  * However pg_get_indexdef_string() includes index tablespace if not default.
964  * ----------
965  */
966 Datum
968 {
969  Oid indexrelid = PG_GETARG_OID(0);
970  int prettyFlags;
971 
972  prettyFlags = PRETTYFLAG_INDENT;
974  NULL,
975  false, false,
976  prettyFlags)));
977 }
978 
979 Datum
981 {
982  Oid indexrelid = PG_GETARG_OID(0);
983  int32 colno = PG_GETARG_INT32(1);
984  bool pretty = PG_GETARG_BOOL(2);
985  int prettyFlags;
986 
987  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
989  NULL,
990  colno != 0,
991  false,
992  prettyFlags)));
993 }
994 
995 /* Internal version that returns a palloc'd C string; no pretty-printing */
996 char *
998 {
999  return pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, 0);
1000 }
1001 
1002 /* Internal version that just reports the column definitions */
1003 char *
1004 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1005 {
1006  int prettyFlags;
1007 
1008  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
1009  return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, prettyFlags);
1010 }
1011 
1012 /*
1013  * Internal workhorse to decompile an index definition.
1014  *
1015  * This is now used for exclusion constraints as well: if excludeOps is not
1016  * NULL then it points to an array of exclusion operator OIDs.
1017  */
1018 static char *
1019 pg_get_indexdef_worker(Oid indexrelid, int colno,
1020  const Oid *excludeOps,
1021  bool attrsOnly, bool showTblSpc,
1022  int prettyFlags)
1023 {
1024  /* might want a separate isConstraint parameter later */
1025  bool isConstraint = (excludeOps != NULL);
1026  HeapTuple ht_idx;
1027  HeapTuple ht_idxrel;
1028  HeapTuple ht_am;
1029  Form_pg_index idxrec;
1030  Form_pg_class idxrelrec;
1031  Form_pg_am amrec;
1032  IndexAmRoutine *amroutine;
1033  List *indexprs;
1034  ListCell *indexpr_item;
1035  List *context;
1036  Oid indrelid;
1037  int keyno;
1038  Datum indcollDatum;
1039  Datum indclassDatum;
1040  Datum indoptionDatum;
1041  bool isnull;
1042  oidvector *indcollation;
1043  oidvector *indclass;
1044  int2vector *indoption;
1046  char *str;
1047  char *sep;
1048 
1049  /*
1050  * Fetch the pg_index tuple by the Oid of the index
1051  */
1052  ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1053  if (!HeapTupleIsValid(ht_idx))
1054  elog(ERROR, "cache lookup failed for index %u", indexrelid);
1055  idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1056 
1057  indrelid = idxrec->indrelid;
1058  Assert(indexrelid == idxrec->indexrelid);
1059 
1060  /* Must get indcollation, indclass, and indoption the hard way */
1061  indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1062  Anum_pg_index_indcollation, &isnull);
1063  Assert(!isnull);
1064  indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1065 
1066  indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1067  Anum_pg_index_indclass, &isnull);
1068  Assert(!isnull);
1069  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1070 
1071  indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1072  Anum_pg_index_indoption, &isnull);
1073  Assert(!isnull);
1074  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1075 
1076  /*
1077  * Fetch the pg_class tuple of the index relation
1078  */
1079  ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1080  if (!HeapTupleIsValid(ht_idxrel))
1081  elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1082  idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1083 
1084  /*
1085  * Fetch the pg_am tuple of the index' access method
1086  */
1087  ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1088  if (!HeapTupleIsValid(ht_am))
1089  elog(ERROR, "cache lookup failed for access method %u",
1090  idxrelrec->relam);
1091  amrec = (Form_pg_am) GETSTRUCT(ht_am);
1092 
1093  /* Fetch the index AM's API struct */
1094  amroutine = GetIndexAmRoutine(amrec->amhandler);
1095 
1096  /*
1097  * Get the index expressions, if any. (NOTE: we do not use the relcache
1098  * versions of the expressions and predicate, because we want to display
1099  * non-const-folded expressions.)
1100  */
1101  if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
1102  {
1103  Datum exprsDatum;
1104  bool isnull;
1105  char *exprsString;
1106 
1107  exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1108  Anum_pg_index_indexprs, &isnull);
1109  Assert(!isnull);
1110  exprsString = TextDatumGetCString(exprsDatum);
1111  indexprs = (List *) stringToNode(exprsString);
1112  pfree(exprsString);
1113  }
1114  else
1115  indexprs = NIL;
1116 
1117  indexpr_item = list_head(indexprs);
1118 
1119  context = deparse_context_for(get_relation_name(indrelid), indrelid);
1120 
1121  /*
1122  * Start the index definition. Note that the index's name should never be
1123  * schema-qualified, but the indexed rel's name may be.
1124  */
1125  initStringInfo(&buf);
1126 
1127  if (!attrsOnly)
1128  {
1129  if (!isConstraint)
1130  appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
1131  idxrec->indisunique ? "UNIQUE " : "",
1132  quote_identifier(NameStr(idxrelrec->relname)),
1133  generate_relation_name(indrelid, NIL),
1134  quote_identifier(NameStr(amrec->amname)));
1135  else /* currently, must be EXCLUDE constraint */
1136  appendStringInfo(&buf, "EXCLUDE USING %s (",
1137  quote_identifier(NameStr(amrec->amname)));
1138  }
1139 
1140  /*
1141  * Report the indexed attributes
1142  */
1143  sep = "";
1144  for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1145  {
1146  AttrNumber attnum = idxrec->indkey.values[keyno];
1147  int16 opt = indoption->values[keyno];
1148  Oid keycoltype;
1149  Oid keycolcollation;
1150 
1151  if (!colno)
1152  appendStringInfoString(&buf, sep);
1153  sep = ", ";
1154 
1155  if (attnum != 0)
1156  {
1157  /* Simple index column */
1158  char *attname;
1159  int32 keycoltypmod;
1160 
1161  attname = get_relid_attribute_name(indrelid, attnum);
1162  if (!colno || colno == keyno + 1)
1163  appendStringInfoString(&buf, quote_identifier(attname));
1164  get_atttypetypmodcoll(indrelid, attnum,
1165  &keycoltype, &keycoltypmod,
1166  &keycolcollation);
1167  }
1168  else
1169  {
1170  /* expressional index */
1171  Node *indexkey;
1172 
1173  if (indexpr_item == NULL)
1174  elog(ERROR, "too few entries in indexprs list");
1175  indexkey = (Node *) lfirst(indexpr_item);
1176  indexpr_item = lnext(indexpr_item);
1177  /* Deparse */
1178  str = deparse_expression_pretty(indexkey, context, false, false,
1179  prettyFlags, 0);
1180  if (!colno || colno == keyno + 1)
1181  {
1182  /* Need parens if it's not a bare function call */
1183  if (indexkey && IsA(indexkey, FuncExpr) &&
1184  ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
1185  appendStringInfoString(&buf, str);
1186  else
1187  appendStringInfo(&buf, "(%s)", str);
1188  }
1189  keycoltype = exprType(indexkey);
1190  keycolcollation = exprCollation(indexkey);
1191  }
1192 
1193  if (!attrsOnly && (!colno || colno == keyno + 1))
1194  {
1195  Oid indcoll;
1196 
1197  /* Add collation, if not default for column */
1198  indcoll = indcollation->values[keyno];
1199  if (OidIsValid(indcoll) && indcoll != keycolcollation)
1200  appendStringInfo(&buf, " COLLATE %s",
1201  generate_collation_name((indcoll)));
1202 
1203  /* Add the operator class name, if not default */
1204  get_opclass_name(indclass->values[keyno], keycoltype, &buf);
1205 
1206  /* Add options if relevant */
1207  if (amroutine->amcanorder)
1208  {
1209  /* if it supports sort ordering, report DESC and NULLS opts */
1210  if (opt & INDOPTION_DESC)
1211  {
1212  appendStringInfoString(&buf, " DESC");
1213  /* NULLS FIRST is the default in this case */
1214  if (!(opt & INDOPTION_NULLS_FIRST))
1215  appendStringInfoString(&buf, " NULLS LAST");
1216  }
1217  else
1218  {
1219  if (opt & INDOPTION_NULLS_FIRST)
1220  appendStringInfoString(&buf, " NULLS FIRST");
1221  }
1222  }
1223 
1224  /* Add the exclusion operator if relevant */
1225  if (excludeOps != NULL)
1226  appendStringInfo(&buf, " WITH %s",
1227  generate_operator_name(excludeOps[keyno],
1228  keycoltype,
1229  keycoltype));
1230  }
1231  }
1232 
1233  if (!attrsOnly)
1234  {
1235  appendStringInfoChar(&buf, ')');
1236 
1237  /*
1238  * If it has options, append "WITH (options)"
1239  */
1240  str = flatten_reloptions(indexrelid);
1241  if (str)
1242  {
1243  appendStringInfo(&buf, " WITH (%s)", str);
1244  pfree(str);
1245  }
1246 
1247  /*
1248  * If it's in a nondefault tablespace, say so, but only if requested
1249  */
1250  if (showTblSpc)
1251  {
1252  Oid tblspc;
1253 
1254  tblspc = get_rel_tablespace(indexrelid);
1255  if (OidIsValid(tblspc))
1256  {
1257  if (isConstraint)
1258  appendStringInfoString(&buf, " USING INDEX");
1259  appendStringInfo(&buf, " TABLESPACE %s",
1261  }
1262  }
1263 
1264  /*
1265  * If it's a partial index, decompile and append the predicate
1266  */
1267  if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
1268  {
1269  Node *node;
1270  Datum predDatum;
1271  bool isnull;
1272  char *predString;
1273 
1274  /* Convert text string to node tree */
1275  predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1276  Anum_pg_index_indpred, &isnull);
1277  Assert(!isnull);
1278  predString = TextDatumGetCString(predDatum);
1279  node = (Node *) stringToNode(predString);
1280  pfree(predString);
1281 
1282  /* Deparse */
1283  str = deparse_expression_pretty(node, context, false, false,
1284  prettyFlags, 0);
1285  if (isConstraint)
1286  appendStringInfo(&buf, " WHERE (%s)", str);
1287  else
1288  appendStringInfo(&buf, " WHERE %s", str);
1289  }
1290  }
1291 
1292  /* Clean up */
1293  ReleaseSysCache(ht_idx);
1294  ReleaseSysCache(ht_idxrel);
1295  ReleaseSysCache(ht_am);
1296 
1297  return buf.data;
1298 }
1299 
1300 
1301 /*
1302  * pg_get_constraintdef
1303  *
1304  * Returns the definition for the constraint, ie, everything that needs to
1305  * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
1306  */
1307 Datum
1309 {
1310  Oid constraintId = PG_GETARG_OID(0);
1311  int prettyFlags;
1312 
1313  prettyFlags = PRETTYFLAG_INDENT;
1315  false,
1316  prettyFlags)));
1317 }
1318 
1319 Datum
1321 {
1322  Oid constraintId = PG_GETARG_OID(0);
1323  bool pretty = PG_GETARG_BOOL(1);
1324  int prettyFlags;
1325 
1326  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
1328  false,
1329  prettyFlags)));
1330 }
1331 
1332 /*
1333  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
1334  */
1335 char *
1337 {
1338  return pg_get_constraintdef_worker(constraintId, true, 0);
1339 }
1340 
1341 /*
1342  * As of 9.4, we now use an MVCC snapshot for this.
1343  */
1344 static char *
1345 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
1346  int prettyFlags)
1347 {
1348  HeapTuple tup;
1349  Form_pg_constraint conForm;
1351  SysScanDesc scandesc;
1352  ScanKeyData scankey[1];
1355 
1356  ScanKeyInit(&scankey[0],
1358  BTEqualStrategyNumber, F_OIDEQ,
1359  ObjectIdGetDatum(constraintId));
1360 
1361  scandesc = systable_beginscan(relation,
1363  true,
1364  snapshot,
1365  1,
1366  scankey);
1367 
1368  /*
1369  * We later use the tuple with SysCacheGetAttr() as if we had obtained it
1370  * via SearchSysCache, which works fine.
1371  */
1372  tup = systable_getnext(scandesc);
1373 
1374  UnregisterSnapshot(snapshot);
1375 
1376  if (!HeapTupleIsValid(tup)) /* should not happen */
1377  elog(ERROR, "cache lookup failed for constraint %u", constraintId);
1378 
1379  conForm = (Form_pg_constraint) GETSTRUCT(tup);
1380 
1381  initStringInfo(&buf);
1382 
1383  if (fullCommand)
1384  {
1385  /*
1386  * Currently, callers want ALTER TABLE (without ONLY) for CHECK
1387  * constraints, and other types of constraints don't inherit anyway so
1388  * it doesn't matter whether we say ONLY or not. Someday we might
1389  * need to let callers specify whether to put ONLY in the command.
1390  */
1391  appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
1392  generate_qualified_relation_name(conForm->conrelid),
1393  quote_identifier(NameStr(conForm->conname)));
1394  }
1395 
1396  switch (conForm->contype)
1397  {
1398  case CONSTRAINT_FOREIGN:
1399  {
1400  Datum val;
1401  bool isnull;
1402  const char *string;
1403 
1404  /* Start off the constraint definition */
1405  appendStringInfoString(&buf, "FOREIGN KEY (");
1406 
1407  /* Fetch and build referencing-column list */
1408  val = SysCacheGetAttr(CONSTROID, tup,
1409  Anum_pg_constraint_conkey, &isnull);
1410  if (isnull)
1411  elog(ERROR, "null conkey for constraint %u",
1412  constraintId);
1413 
1414  decompile_column_index_array(val, conForm->conrelid, &buf);
1415 
1416  /* add foreign relation name */
1417  appendStringInfo(&buf, ") REFERENCES %s(",
1418  generate_relation_name(conForm->confrelid,
1419  NIL));
1420 
1421  /* Fetch and build referenced-column list */
1422  val = SysCacheGetAttr(CONSTROID, tup,
1423  Anum_pg_constraint_confkey, &isnull);
1424  if (isnull)
1425  elog(ERROR, "null confkey for constraint %u",
1426  constraintId);
1427 
1428  decompile_column_index_array(val, conForm->confrelid, &buf);
1429 
1430  appendStringInfoChar(&buf, ')');
1431 
1432  /* Add match type */
1433  switch (conForm->confmatchtype)
1434  {
1435  case FKCONSTR_MATCH_FULL:
1436  string = " MATCH FULL";
1437  break;
1439  string = " MATCH PARTIAL";
1440  break;
1441  case FKCONSTR_MATCH_SIMPLE:
1442  string = "";
1443  break;
1444  default:
1445  elog(ERROR, "unrecognized confmatchtype: %d",
1446  conForm->confmatchtype);
1447  string = ""; /* keep compiler quiet */
1448  break;
1449  }
1450  appendStringInfoString(&buf, string);
1451 
1452  /* Add ON UPDATE and ON DELETE clauses, if needed */
1453  switch (conForm->confupdtype)
1454  {
1456  string = NULL; /* suppress default */
1457  break;
1459  string = "RESTRICT";
1460  break;
1462  string = "CASCADE";
1463  break;
1465  string = "SET NULL";
1466  break;
1468  string = "SET DEFAULT";
1469  break;
1470  default:
1471  elog(ERROR, "unrecognized confupdtype: %d",
1472  conForm->confupdtype);
1473  string = NULL; /* keep compiler quiet */
1474  break;
1475  }
1476  if (string)
1477  appendStringInfo(&buf, " ON UPDATE %s", string);
1478 
1479  switch (conForm->confdeltype)
1480  {
1482  string = NULL; /* suppress default */
1483  break;
1485  string = "RESTRICT";
1486  break;
1488  string = "CASCADE";
1489  break;
1491  string = "SET NULL";
1492  break;
1494  string = "SET DEFAULT";
1495  break;
1496  default:
1497  elog(ERROR, "unrecognized confdeltype: %d",
1498  conForm->confdeltype);
1499  string = NULL; /* keep compiler quiet */
1500  break;
1501  }
1502  if (string)
1503  appendStringInfo(&buf, " ON DELETE %s", string);
1504 
1505  break;
1506  }
1507  case CONSTRAINT_PRIMARY:
1508  case CONSTRAINT_UNIQUE:
1509  {
1510  Datum val;
1511  bool isnull;
1512  Oid indexId;
1513 
1514  /* Start off the constraint definition */
1515  if (conForm->contype == CONSTRAINT_PRIMARY)
1516  appendStringInfoString(&buf, "PRIMARY KEY (");
1517  else
1518  appendStringInfoString(&buf, "UNIQUE (");
1519 
1520  /* Fetch and build target column list */
1521  val = SysCacheGetAttr(CONSTROID, tup,
1522  Anum_pg_constraint_conkey, &isnull);
1523  if (isnull)
1524  elog(ERROR, "null conkey for constraint %u",
1525  constraintId);
1526 
1527  decompile_column_index_array(val, conForm->conrelid, &buf);
1528 
1529  appendStringInfoChar(&buf, ')');
1530 
1531  indexId = get_constraint_index(constraintId);
1532 
1533  /* XXX why do we only print these bits if fullCommand? */
1534  if (fullCommand && OidIsValid(indexId))
1535  {
1536  char *options = flatten_reloptions(indexId);
1537  Oid tblspc;
1538 
1539  if (options)
1540  {
1541  appendStringInfo(&buf, " WITH (%s)", options);
1542  pfree(options);
1543  }
1544 
1545  tblspc = get_rel_tablespace(indexId);
1546  if (OidIsValid(tblspc))
1547  appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1549  }
1550 
1551  break;
1552  }
1553  case CONSTRAINT_CHECK:
1554  {
1555  Datum val;
1556  bool isnull;
1557  char *conbin;
1558  char *consrc;
1559  Node *expr;
1560  List *context;
1561 
1562  /* Fetch constraint expression in parsetree form */
1563  val = SysCacheGetAttr(CONSTROID, tup,
1564  Anum_pg_constraint_conbin, &isnull);
1565  if (isnull)
1566  elog(ERROR, "null conbin for constraint %u",
1567  constraintId);
1568 
1569  conbin = TextDatumGetCString(val);
1570  expr = stringToNode(conbin);
1571 
1572  /* Set up deparsing context for Var nodes in constraint */
1573  if (conForm->conrelid != InvalidOid)
1574  {
1575  /* relation constraint */
1576  context = deparse_context_for(get_relation_name(conForm->conrelid),
1577  conForm->conrelid);
1578  }
1579  else
1580  {
1581  /* domain constraint --- can't have Vars */
1582  context = NIL;
1583  }
1584 
1585  consrc = deparse_expression_pretty(expr, context, false, false,
1586  prettyFlags, 0);
1587 
1588  /*
1589  * Now emit the constraint definition, adding NO INHERIT if
1590  * necessary.
1591  *
1592  * There are cases where the constraint expression will be
1593  * fully parenthesized and we don't need the outer parens ...
1594  * but there are other cases where we do need 'em. Be
1595  * conservative for now.
1596  *
1597  * Note that simply checking for leading '(' and trailing ')'
1598  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1599  */
1600  appendStringInfo(&buf, "CHECK (%s)%s",
1601  consrc,
1602  conForm->connoinherit ? " NO INHERIT" : "");
1603  break;
1604  }
1605  case CONSTRAINT_TRIGGER:
1606 
1607  /*
1608  * There isn't an ALTER TABLE syntax for creating a user-defined
1609  * constraint trigger, but it seems better to print something than
1610  * throw an error; if we throw error then this function couldn't
1611  * safely be applied to all rows of pg_constraint.
1612  */
1613  appendStringInfoString(&buf, "TRIGGER");
1614  break;
1615  case CONSTRAINT_EXCLUSION:
1616  {
1617  Oid indexOid = conForm->conindid;
1618  Datum val;
1619  bool isnull;
1620  Datum *elems;
1621  int nElems;
1622  int i;
1623  Oid *operators;
1624 
1625  /* Extract operator OIDs from the pg_constraint tuple */
1626  val = SysCacheGetAttr(CONSTROID, tup,
1628  &isnull);
1629  if (isnull)
1630  elog(ERROR, "null conexclop for constraint %u",
1631  constraintId);
1632 
1634  OIDOID, sizeof(Oid), true, 'i',
1635  &elems, NULL, &nElems);
1636 
1637  operators = (Oid *) palloc(nElems * sizeof(Oid));
1638  for (i = 0; i < nElems; i++)
1639  operators[i] = DatumGetObjectId(elems[i]);
1640 
1641  /* pg_get_indexdef_worker does the rest */
1642  /* suppress tablespace because pg_dump wants it that way */
1644  pg_get_indexdef_worker(indexOid,
1645  0,
1646  operators,
1647  false,
1648  false,
1649  prettyFlags));
1650  break;
1651  }
1652  default:
1653  elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1654  break;
1655  }
1656 
1657  if (conForm->condeferrable)
1658  appendStringInfoString(&buf, " DEFERRABLE");
1659  if (conForm->condeferred)
1660  appendStringInfoString(&buf, " INITIALLY DEFERRED");
1661  if (!conForm->convalidated)
1662  appendStringInfoString(&buf, " NOT VALID");
1663 
1664  /* Cleanup */
1665  systable_endscan(scandesc);
1666  heap_close(relation, AccessShareLock);
1667 
1668  return buf.data;
1669 }
1670 
1671 
1672 /*
1673  * Convert an int16[] Datum into a comma-separated list of column names
1674  * for the indicated relation; append the list to buf.
1675  */
1676 static void
1677 decompile_column_index_array(Datum column_index_array, Oid relId,
1678  StringInfo buf)
1679 {
1680  Datum *keys;
1681  int nKeys;
1682  int j;
1683 
1684  /* Extract data from array of int16 */
1685  deconstruct_array(DatumGetArrayTypeP(column_index_array),
1686  INT2OID, 2, true, 's',
1687  &keys, NULL, &nKeys);
1688 
1689  for (j = 0; j < nKeys; j++)
1690  {
1691  char *colName;
1692 
1693  colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1694 
1695  if (j == 0)
1697  else
1698  appendStringInfo(buf, ", %s", quote_identifier(colName));
1699  }
1700 }
1701 
1702 
1703 /* ----------
1704  * get_expr - Decompile an expression tree
1705  *
1706  * Input: an expression tree in nodeToString form, and a relation OID
1707  *
1708  * Output: reverse-listed expression
1709  *
1710  * Currently, the expression can only refer to a single relation, namely
1711  * the one specified by the second parameter. This is sufficient for
1712  * partial indexes, column default expressions, etc. We also support
1713  * Var-free expressions, for which the OID can be InvalidOid.
1714  * ----------
1715  */
1716 Datum
1718 {
1719  text *expr = PG_GETARG_TEXT_P(0);
1720  Oid relid = PG_GETARG_OID(1);
1721  int prettyFlags;
1722  char *relname;
1723 
1724  prettyFlags = PRETTYFLAG_INDENT;
1725 
1726  if (OidIsValid(relid))
1727  {
1728  /* Get the name for the relation */
1729  relname = get_rel_name(relid);
1730 
1731  /*
1732  * If the OID isn't actually valid, don't throw an error, just return
1733  * NULL. This is a bit questionable, but it's what we've done
1734  * historically, and it can help avoid unwanted failures when
1735  * examining catalog entries for just-deleted relations.
1736  */
1737  if (relname == NULL)
1738  PG_RETURN_NULL();
1739  }
1740  else
1741  relname = NULL;
1742 
1743  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
1744 }
1745 
1746 Datum
1748 {
1749  text *expr = PG_GETARG_TEXT_P(0);
1750  Oid relid = PG_GETARG_OID(1);
1751  bool pretty = PG_GETARG_BOOL(2);
1752  int prettyFlags;
1753  char *relname;
1754 
1755  prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
1756 
1757  if (OidIsValid(relid))
1758  {
1759  /* Get the name for the relation */
1760  relname = get_rel_name(relid);
1761  /* See notes above */
1762  if (relname == NULL)
1763  PG_RETURN_NULL();
1764  }
1765  else
1766  relname = NULL;
1767 
1768  PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
1769 }
1770 
1771 static text *
1772 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
1773 {
1774  Node *node;
1775  List *context;
1776  char *exprstr;
1777  char *str;
1778 
1779  /* Convert input TEXT object to C string */
1780  exprstr = text_to_cstring(expr);
1781 
1782  /* Convert expression to node tree */
1783  node = (Node *) stringToNode(exprstr);
1784 
1785  pfree(exprstr);
1786 
1787  /* Prepare deparse context if needed */
1788  if (OidIsValid(relid))
1789  context = deparse_context_for(relname, relid);
1790  else
1791  context = NIL;
1792 
1793  /* Deparse */
1794  str = deparse_expression_pretty(node, context, false, false,
1795  prettyFlags, 0);
1796 
1797  return string_to_text(str);
1798 }
1799 
1800 
1801 /* ----------
1802  * get_userbyid - Get a user name by roleid and
1803  * fallback to 'unknown (OID=n)'
1804  * ----------
1805  */
1806 Datum
1808 {
1809  Oid roleid = PG_GETARG_OID(0);
1810  Name result;
1811  HeapTuple roletup;
1812  Form_pg_authid role_rec;
1813 
1814  /*
1815  * Allocate space for the result
1816  */
1817  result = (Name) palloc(NAMEDATALEN);
1818  memset(NameStr(*result), 0, NAMEDATALEN);
1819 
1820  /*
1821  * Get the pg_authid entry and print the result
1822  */
1823  roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1824  if (HeapTupleIsValid(roletup))
1825  {
1826  role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1827  StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1828  ReleaseSysCache(roletup);
1829  }
1830  else
1831  sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1832 
1833  PG_RETURN_NAME(result);
1834 }
1835 
1836 
1837 /*
1838  * pg_get_serial_sequence
1839  * Get the name of the sequence used by a serial column,
1840  * formatted suitably for passing to setval, nextval or currval.
1841  * First parameter is not treated as double-quoted, second parameter
1842  * is --- see documentation for reason.
1843  */
1844 Datum
1846 {
1847  text *tablename = PG_GETARG_TEXT_P(0);
1848  text *columnname = PG_GETARG_TEXT_PP(1);
1849  RangeVar *tablerv;
1850  Oid tableOid;
1851  char *column;
1852  AttrNumber attnum;
1853  Oid sequenceId = InvalidOid;
1854  Relation depRel;
1855  ScanKeyData key[3];
1856  SysScanDesc scan;
1857  HeapTuple tup;
1858 
1859  /* Look up table name. Can't lock it - we might not have privileges. */
1860  tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1861  tableOid = RangeVarGetRelid(tablerv, NoLock, false);
1862 
1863  /* Get the number of the column */
1864  column = text_to_cstring(columnname);
1865 
1866  attnum = get_attnum(tableOid, column);
1867  if (attnum == InvalidAttrNumber)
1868  ereport(ERROR,
1869  (errcode(ERRCODE_UNDEFINED_COLUMN),
1870  errmsg("column \"%s\" of relation \"%s\" does not exist",
1871  column, tablerv->relname)));
1872 
1873  /* Search the dependency table for the dependent sequence */
1875 
1876  ScanKeyInit(&key[0],
1878  BTEqualStrategyNumber, F_OIDEQ,
1880  ScanKeyInit(&key[1],
1882  BTEqualStrategyNumber, F_OIDEQ,
1883  ObjectIdGetDatum(tableOid));
1884  ScanKeyInit(&key[2],
1886  BTEqualStrategyNumber, F_INT4EQ,
1887  Int32GetDatum(attnum));
1888 
1889  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1890  NULL, 3, key);
1891 
1892  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1893  {
1894  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1895 
1896  /*
1897  * We assume any auto dependency of a sequence on a column must be
1898  * what we are looking for. (We need the relkind test because indexes
1899  * can also have auto dependencies on columns.)
1900  */
1901  if (deprec->classid == RelationRelationId &&
1902  deprec->objsubid == 0 &&
1903  deprec->deptype == DEPENDENCY_AUTO &&
1904  get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1905  {
1906  sequenceId = deprec->objid;
1907  break;
1908  }
1909  }
1910 
1911  systable_endscan(scan);
1912  heap_close(depRel, AccessShareLock);
1913 
1914  if (OidIsValid(sequenceId))
1915  {
1916  char *result;
1917 
1918  result = generate_qualified_relation_name(sequenceId);
1919 
1921  }
1922 
1923  PG_RETURN_NULL();
1924 }
1925 
1926 
1927 /*
1928  * pg_get_functiondef
1929  * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1930  * the specified function.
1931  *
1932  * Note: if you change the output format of this function, be careful not
1933  * to break psql's rules (in \ef and \sf) for identifying the start of the
1934  * function body. To wit: the function body starts on a line that begins
1935  * with "AS ", and no preceding line will look like that.
1936  */
1937 Datum
1939 {
1940  Oid funcid = PG_GETARG_OID(0);
1942  StringInfoData dq;
1943  HeapTuple proctup;
1944  Form_pg_proc proc;
1945  Datum tmp;
1946  bool isnull;
1947  const char *prosrc;
1948  const char *name;
1949  const char *nsp;
1950  float4 procost;
1951  int oldlen;
1952 
1953  initStringInfo(&buf);
1954 
1955  /* Look up the function */
1956  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1957  if (!HeapTupleIsValid(proctup))
1958  elog(ERROR, "cache lookup failed for function %u", funcid);
1959  proc = (Form_pg_proc) GETSTRUCT(proctup);
1960  name = NameStr(proc->proname);
1961 
1962  if (proc->proisagg)
1963  ereport(ERROR,
1964  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1965  errmsg("\"%s\" is an aggregate function", name)));
1966 
1967  /*
1968  * We always qualify the function name, to ensure the right function gets
1969  * replaced.
1970  */
1971  nsp = get_namespace_name(proc->pronamespace);
1972  appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1973  quote_qualified_identifier(nsp, name));
1974  (void) print_function_arguments(&buf, proctup, false, true);
1975  appendStringInfoString(&buf, ")\n RETURNS ");
1976  print_function_rettype(&buf, proctup);
1977 
1978  print_function_trftypes(&buf, proctup);
1979 
1980  appendStringInfo(&buf, "\n LANGUAGE %s\n",
1981  quote_identifier(get_language_name(proc->prolang, false)));
1982 
1983  /* Emit some miscellaneous options on one line */
1984  oldlen = buf.len;
1985 
1986  if (proc->proiswindow)
1987  appendStringInfoString(&buf, " WINDOW");
1988  switch (proc->provolatile)
1989  {
1990  case PROVOLATILE_IMMUTABLE:
1991  appendStringInfoString(&buf, " IMMUTABLE");
1992  break;
1993  case PROVOLATILE_STABLE:
1994  appendStringInfoString(&buf, " STABLE");
1995  break;
1996  case PROVOLATILE_VOLATILE:
1997  break;
1998  }
1999 
2000  switch (proc->proparallel)
2001  {
2002  case PROPARALLEL_SAFE:
2003  appendStringInfoString(&buf, " PARALLEL SAFE");
2004  break;
2006  appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2007  break;
2008  case PROPARALLEL_UNSAFE:
2009  break;
2010  }
2011 
2012  if (proc->proisstrict)
2013  appendStringInfoString(&buf, " STRICT");
2014  if (proc->prosecdef)
2015  appendStringInfoString(&buf, " SECURITY DEFINER");
2016  if (proc->proleakproof)
2017  appendStringInfoString(&buf, " LEAKPROOF");
2018 
2019  /* This code for the default cost and rows should match functioncmds.c */
2020  if (proc->prolang == INTERNALlanguageId ||
2021  proc->prolang == ClanguageId)
2022  procost = 1;
2023  else
2024  procost = 100;
2025  if (proc->procost != procost)
2026  appendStringInfo(&buf, " COST %g", proc->procost);
2027 
2028  if (proc->prorows > 0 && proc->prorows != 1000)
2029  appendStringInfo(&buf, " ROWS %g", proc->prorows);
2030 
2031  if (oldlen != buf.len)
2032  appendStringInfoChar(&buf, '\n');
2033 
2034  /* Emit any proconfig options, one per line */
2035  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
2036  if (!isnull)
2037  {
2038  ArrayType *a = DatumGetArrayTypeP(tmp);
2039  int i;
2040 
2041  Assert(ARR_ELEMTYPE(a) == TEXTOID);
2042  Assert(ARR_NDIM(a) == 1);
2043  Assert(ARR_LBOUND(a)[0] == 1);
2044 
2045  for (i = 1; i <= ARR_DIMS(a)[0]; i++)
2046  {
2047  Datum d;
2048 
2049  d = array_ref(a, 1, &i,
2050  -1 /* varlenarray */ ,
2051  -1 /* TEXT's typlen */ ,
2052  false /* TEXT's typbyval */ ,
2053  'i' /* TEXT's typalign */ ,
2054  &isnull);
2055  if (!isnull)
2056  {
2057  char *configitem = TextDatumGetCString(d);
2058  char *pos;
2059 
2060  pos = strchr(configitem, '=');
2061  if (pos == NULL)
2062  continue;
2063  *pos++ = '\0';
2064 
2065  appendStringInfo(&buf, " SET %s TO ",
2066  quote_identifier(configitem));
2067 
2068  /*
2069  * Some GUC variable names are 'LIST' type and hence must not
2070  * be quoted.
2071  */
2072  if (pg_strcasecmp(configitem, "DateStyle") == 0
2073  || pg_strcasecmp(configitem, "search_path") == 0)
2074  appendStringInfoString(&buf, pos);
2075  else
2076  simple_quote_literal(&buf, pos);
2077  appendStringInfoChar(&buf, '\n');
2078  }
2079  }
2080  }
2081 
2082  /* And finally the function definition ... */
2083  appendStringInfoString(&buf, "AS ");
2084 
2085  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
2086  if (!isnull)
2087  {
2089  appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
2090  }
2091 
2092  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
2093  if (isnull)
2094  elog(ERROR, "null prosrc");
2095  prosrc = TextDatumGetCString(tmp);
2096 
2097  /*
2098  * We always use dollar quoting. Figure out a suitable delimiter.
2099  *
2100  * Since the user is likely to be editing the function body string, we
2101  * shouldn't use a short delimiter that he might easily create a conflict
2102  * with. Hence prefer "$function$", but extend if needed.
2103  */
2104  initStringInfo(&dq);
2105  appendStringInfoString(&dq, "$function");
2106  while (strstr(prosrc, dq.data) != NULL)
2107  appendStringInfoChar(&dq, 'x');
2108  appendStringInfoChar(&dq, '$');
2109 
2110  appendStringInfoString(&buf, dq.data);
2111  appendStringInfoString(&buf, prosrc);
2112  appendStringInfoString(&buf, dq.data);
2113 
2114  appendStringInfoChar(&buf, '\n');
2115 
2116  ReleaseSysCache(proctup);
2117 
2119 }
2120 
2121 /*
2122  * pg_get_function_arguments
2123  * Get a nicely-formatted list of arguments for a function.
2124  * This is everything that would go between the parentheses in
2125  * CREATE FUNCTION.
2126  */
2127 Datum
2129 {
2130  Oid funcid = PG_GETARG_OID(0);
2132  HeapTuple proctup;
2133 
2134  initStringInfo(&buf);
2135 
2136  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2137  if (!HeapTupleIsValid(proctup))
2138  elog(ERROR, "cache lookup failed for function %u", funcid);
2139 
2140  (void) print_function_arguments(&buf, proctup, false, true);
2141 
2142  ReleaseSysCache(proctup);
2143 
2145 }
2146 
2147 /*
2148  * pg_get_function_identity_arguments
2149  * Get a formatted list of arguments for a function.
2150  * This is everything that would go between the parentheses in
2151  * ALTER FUNCTION, etc. In particular, don't print defaults.
2152  */
2153 Datum
2155 {
2156  Oid funcid = PG_GETARG_OID(0);
2158  HeapTuple proctup;
2159 
2160  initStringInfo(&buf);
2161 
2162  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2163  if (!HeapTupleIsValid(proctup))
2164  elog(ERROR, "cache lookup failed for function %u", funcid);
2165 
2166  (void) print_function_arguments(&buf, proctup, false, false);
2167 
2168  ReleaseSysCache(proctup);
2169 
2171 }
2172 
2173 /*
2174  * pg_get_function_result
2175  * Get a nicely-formatted version of the result type of a function.
2176  * This is what would appear after RETURNS in CREATE FUNCTION.
2177  */
2178 Datum
2180 {
2181  Oid funcid = PG_GETARG_OID(0);
2183  HeapTuple proctup;
2184 
2185  initStringInfo(&buf);
2186 
2187  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2188  if (!HeapTupleIsValid(proctup))
2189  elog(ERROR, "cache lookup failed for function %u", funcid);
2190 
2191  print_function_rettype(&buf, proctup);
2192 
2193  ReleaseSysCache(proctup);
2194 
2196 }
2197 
2198 /*
2199  * Guts of pg_get_function_result: append the function's return type
2200  * to the specified buffer.
2201  */
2202 static void
2204 {
2205  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
2206  int ntabargs = 0;
2207  StringInfoData rbuf;
2208 
2209  initStringInfo(&rbuf);
2210 
2211  if (proc->proretset)
2212  {
2213  /* It might be a table function; try to print the arguments */
2214  appendStringInfoString(&rbuf, "TABLE(");
2215  ntabargs = print_function_arguments(&rbuf, proctup, true, false);
2216  if (ntabargs > 0)
2217  appendStringInfoChar(&rbuf, ')');
2218  else
2219  resetStringInfo(&rbuf);
2220  }
2221 
2222  if (ntabargs == 0)
2223  {
2224  /* Not a table function, so do the normal thing */
2225  if (proc->proretset)
2226  appendStringInfoString(&rbuf, "SETOF ");
2227  appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
2228  }
2229 
2230  appendStringInfoString(buf, rbuf.data);
2231 }
2232 
2233 /*
2234  * Common code for pg_get_function_arguments and pg_get_function_result:
2235  * append the desired subset of arguments to buf. We print only TABLE
2236  * arguments when print_table_args is true, and all the others when it's false.
2237  * We print argument defaults only if print_defaults is true.
2238  * Function return value is the number of arguments printed.
2239  */
2240 static int
2242  bool print_table_args, bool print_defaults)
2243 {
2244  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
2245  int numargs;
2246  Oid *argtypes;
2247  char **argnames;
2248  char *argmodes;
2249  int insertorderbyat = -1;
2250  int argsprinted;
2251  int inputargno;
2252  int nlackdefaults;
2253  ListCell *nextargdefault = NULL;
2254  int i;
2255 
2256  numargs = get_func_arg_info(proctup,
2257  &argtypes, &argnames, &argmodes);
2258 
2259  nlackdefaults = numargs;
2260  if (print_defaults && proc->pronargdefaults > 0)
2261  {
2262  Datum proargdefaults;
2263  bool isnull;
2264 
2265  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
2267  &isnull);
2268  if (!isnull)
2269  {
2270  char *str;
2271  List *argdefaults;
2272 
2273  str = TextDatumGetCString(proargdefaults);
2274  argdefaults = (List *) stringToNode(str);
2275  Assert(IsA(argdefaults, List));
2276  pfree(str);
2277  nextargdefault = list_head(argdefaults);
2278  /* nlackdefaults counts only *input* arguments lacking defaults */
2279  nlackdefaults = proc->pronargs - list_length(argdefaults);
2280  }
2281  }
2282 
2283  /* Check for special treatment of ordered-set aggregates */
2284  if (proc->proisagg)
2285  {
2286  HeapTuple aggtup;
2287  Form_pg_aggregate agg;
2288 
2289  aggtup = SearchSysCache1(AGGFNOID,
2290  ObjectIdGetDatum(HeapTupleGetOid(proctup)));
2291  if (!HeapTupleIsValid(aggtup))
2292  elog(ERROR, "cache lookup failed for aggregate %u",
2293  HeapTupleGetOid(proctup));
2294  agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
2295  if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
2296  insertorderbyat = agg->aggnumdirectargs;
2297  ReleaseSysCache(aggtup);
2298  }
2299 
2300  argsprinted = 0;
2301  inputargno = 0;
2302  for (i = 0; i < numargs; i++)
2303  {
2304  Oid argtype = argtypes[i];
2305  char *argname = argnames ? argnames[i] : NULL;
2306  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
2307  const char *modename;
2308  bool isinput;
2309 
2310  switch (argmode)
2311  {
2312  case PROARGMODE_IN:
2313  modename = "";
2314  isinput = true;
2315  break;
2316  case PROARGMODE_INOUT:
2317  modename = "INOUT ";
2318  isinput = true;
2319  break;
2320  case PROARGMODE_OUT:
2321  modename = "OUT ";
2322  isinput = false;
2323  break;
2324  case PROARGMODE_VARIADIC:
2325  modename = "VARIADIC ";
2326  isinput = true;
2327  break;
2328  case PROARGMODE_TABLE:
2329  modename = "";
2330  isinput = false;
2331  break;
2332  default:
2333  elog(ERROR, "invalid parameter mode '%c'", argmode);
2334  modename = NULL; /* keep compiler quiet */
2335  isinput = false;
2336  break;
2337  }
2338  if (isinput)
2339  inputargno++; /* this is a 1-based counter */
2340 
2341  if (print_table_args != (argmode == PROARGMODE_TABLE))
2342  continue;
2343 
2344  if (argsprinted == insertorderbyat)
2345  {
2346  if (argsprinted)
2347  appendStringInfoChar(buf, ' ');
2348  appendStringInfoString(buf, "ORDER BY ");
2349  }
2350  else if (argsprinted)
2351  appendStringInfoString(buf, ", ");
2352 
2353  appendStringInfoString(buf, modename);
2354  if (argname && argname[0])
2355  appendStringInfo(buf, "%s ", quote_identifier(argname));
2356  appendStringInfoString(buf, format_type_be(argtype));
2357  if (print_defaults && isinput && inputargno > nlackdefaults)
2358  {
2359  Node *expr;
2360 
2361  Assert(nextargdefault != NULL);
2362  expr = (Node *) lfirst(nextargdefault);
2363  nextargdefault = lnext(nextargdefault);
2364 
2365  appendStringInfo(buf, " DEFAULT %s",
2366  deparse_expression(expr, NIL, false, false));
2367  }
2368  argsprinted++;
2369 
2370  /* nasty hack: print the last arg twice for variadic ordered-set agg */
2371  if (argsprinted == insertorderbyat && i == numargs - 1)
2372  {
2373  i--;
2374  /* aggs shouldn't have defaults anyway, but just to be sure ... */
2375  print_defaults = false;
2376  }
2377  }
2378 
2379  return argsprinted;
2380 }
2381 
2382 static bool
2383 is_input_argument(int nth, const char *argmodes)
2384 {
2385  return (!argmodes
2386  || argmodes[nth] == PROARGMODE_IN
2387  || argmodes[nth] == PROARGMODE_INOUT
2388  || argmodes[nth] == PROARGMODE_VARIADIC);
2389 }
2390 
2391 /*
2392  * Append used transformated types to specified buffer
2393  */
2394 static void
2396 {
2397  Oid *trftypes;
2398  int ntypes;
2399 
2400  ntypes = get_func_trftypes(proctup, &trftypes);
2401  if (ntypes > 0)
2402  {
2403  int i;
2404 
2405  appendStringInfoString(buf, "\n TRANSFORM ");
2406  for (i = 0; i < ntypes; i++)
2407  {
2408  if (i != 0)
2409  appendStringInfoString(buf, ", ");
2410  appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
2411  }
2412  }
2413 }
2414 
2415 /*
2416  * Get textual representation of a function argument's default value. The
2417  * second argument of this function is the argument number among all arguments
2418  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
2419  * how information_schema.sql uses it.
2420  */
2421 Datum
2423 {
2424  Oid funcid = PG_GETARG_OID(0);
2425  int32 nth_arg = PG_GETARG_INT32(1);
2426  HeapTuple proctup;
2427  Form_pg_proc proc;
2428  int numargs;
2429  Oid *argtypes;
2430  char **argnames;
2431  char *argmodes;
2432  int i;
2433  List *argdefaults;
2434  Node *node;
2435  char *str;
2436  int nth_inputarg;
2437  Datum proargdefaults;
2438  bool isnull;
2439  int nth_default;
2440 
2441  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2442  if (!HeapTupleIsValid(proctup))
2443  elog(ERROR, "cache lookup failed for function %u", funcid);
2444 
2445  numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
2446  if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
2447  {
2448  ReleaseSysCache(proctup);
2449  PG_RETURN_NULL();
2450  }
2451 
2452  nth_inputarg = 0;
2453  for (i = 0; i < nth_arg; i++)
2454  if (is_input_argument(i, argmodes))
2455  nth_inputarg++;
2456 
2457  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
2459  &isnull);
2460  if (isnull)
2461  {
2462  ReleaseSysCache(proctup);
2463  PG_RETURN_NULL();
2464  }
2465 
2466  str = TextDatumGetCString(proargdefaults);
2467  argdefaults = (List *) stringToNode(str);
2468  Assert(IsA(argdefaults, List));
2469  pfree(str);
2470 
2471  proc = (Form_pg_proc) GETSTRUCT(proctup);
2472 
2473  /*
2474  * Calculate index into proargdefaults: proargdefaults corresponds to the
2475  * last N input arguments, where N = pronargdefaults.
2476  */
2477  nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
2478 
2479  if (nth_default < 0 || nth_default >= list_length(argdefaults))
2480  {
2481  ReleaseSysCache(proctup);
2482  PG_RETURN_NULL();
2483  }
2484  node = list_nth(argdefaults, nth_default);
2485  str = deparse_expression(node, NIL, false, false);
2486 
2487  ReleaseSysCache(proctup);
2488 
2490 }
2491 
2492 
2493 /*
2494  * deparse_expression - General utility for deparsing expressions
2495  *
2496  * calls deparse_expression_pretty with all prettyPrinting disabled
2497  */
2498 char *
2499 deparse_expression(Node *expr, List *dpcontext,
2500  bool forceprefix, bool showimplicit)
2501 {
2502  return deparse_expression_pretty(expr, dpcontext, forceprefix,
2503  showimplicit, 0, 0);
2504 }
2505 
2506 /* ----------
2507  * deparse_expression_pretty - General utility for deparsing expressions
2508  *
2509  * expr is the node tree to be deparsed. It must be a transformed expression
2510  * tree (ie, not the raw output of gram.y).
2511  *
2512  * dpcontext is a list of deparse_namespace nodes representing the context
2513  * for interpreting Vars in the node tree. It can be NIL if no Vars are
2514  * expected.
2515  *
2516  * forceprefix is TRUE to force all Vars to be prefixed with their table names.
2517  *
2518  * showimplicit is TRUE to force all implicit casts to be shown explicitly.
2519  *
2520  * Tries to pretty up the output according to prettyFlags and startIndent.
2521  *
2522  * The result is a palloc'd string.
2523  * ----------
2524  */
2525 static char *
2527  bool forceprefix, bool showimplicit,
2528  int prettyFlags, int startIndent)
2529 {
2531  deparse_context context;
2532 
2533  initStringInfo(&buf);
2534  context.buf = &buf;
2535  context.namespaces = dpcontext;
2536  context.windowClause = NIL;
2537  context.windowTList = NIL;
2538  context.varprefix = forceprefix;
2539  context.prettyFlags = prettyFlags;
2540  context.wrapColumn = WRAP_COLUMN_DEFAULT;
2541  context.indentLevel = startIndent;
2542  context.special_exprkind = EXPR_KIND_NONE;
2543 
2544  get_rule_expr(expr, &context, showimplicit);
2545 
2546  return buf.data;
2547 }
2548 
2549 /* ----------
2550  * deparse_context_for - Build deparse context for a single relation
2551  *
2552  * Given the reference name (alias) and OID of a relation, build deparsing
2553  * context for an expression referencing only that relation (as varno 1,
2554  * varlevelsup 0). This is sufficient for many uses of deparse_expression.
2555  * ----------
2556  */
2557 List *
2558 deparse_context_for(const char *aliasname, Oid relid)
2559 {
2560  deparse_namespace *dpns;
2561  RangeTblEntry *rte;
2562 
2563  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2564 
2565  /* Build a minimal RTE for the rel */
2566  rte = makeNode(RangeTblEntry);
2567  rte->rtekind = RTE_RELATION;
2568  rte->relid = relid;
2569  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
2570  rte->alias = makeAlias(aliasname, NIL);
2571  rte->eref = rte->alias;
2572  rte->lateral = false;
2573  rte->inh = false;
2574  rte->inFromCl = true;
2575 
2576  /* Build one-element rtable */
2577  dpns->rtable = list_make1(rte);
2578  dpns->ctes = NIL;
2579  set_rtable_names(dpns, NIL, NULL);
2581 
2582  /* Return a one-deep namespace stack */
2583  return list_make1(dpns);
2584 }
2585 
2586 /*
2587  * deparse_context_for_plan_rtable - Build deparse context for a plan's rtable
2588  *
2589  * When deparsing an expression in a Plan tree, we use the plan's rangetable
2590  * to resolve names of simple Vars. The initialization of column names for
2591  * this is rather expensive if the rangetable is large, and it'll be the same
2592  * for every expression in the Plan tree; so we do it just once and re-use
2593  * the result of this function for each expression. (Note that the result
2594  * is not usable until set_deparse_context_planstate() is applied to it.)
2595  *
2596  * In addition to the plan's rangetable list, pass the per-RTE alias names
2597  * assigned by a previous call to select_rtable_names_for_explain.
2598  */
2599 List *
2601 {
2602  deparse_namespace *dpns;
2603 
2604  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2605 
2606  /* Initialize fields that stay the same across the whole plan tree */
2607  dpns->rtable = rtable;
2608  dpns->rtable_names = rtable_names;
2609  dpns->ctes = NIL;
2610 
2611  /*
2612  * Set up column name aliases. We will get rather bogus results for join
2613  * RTEs, but that doesn't matter because plan trees don't contain any join
2614  * alias Vars.
2615  */
2617 
2618  /* Return a one-deep namespace stack */
2619  return list_make1(dpns);
2620 }
2621 
2622 /*
2623  * set_deparse_context_planstate - Specify Plan node containing expression
2624  *
2625  * When deparsing an expression in a Plan tree, we might have to resolve
2626  * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
2627  * provide the parent PlanState node. Then OUTER_VAR and INNER_VAR references
2628  * can be resolved by drilling down into the left and right child plans.
2629  * Similarly, INDEX_VAR references can be resolved by reference to the
2630  * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
2631  * ForeignScan and CustomScan nodes. (Note that we don't currently support
2632  * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
2633  * for those, we can only deparse the indexqualorig fields, which won't
2634  * contain INDEX_VAR Vars.)
2635  *
2636  * Note: planstate really ought to be declared as "PlanState *", but we use
2637  * "Node *" to avoid having to include execnodes.h in ruleutils.h.
2638  *
2639  * The ancestors list is a list of the PlanState's parent PlanStates, the
2640  * most-closely-nested first. This is needed to resolve PARAM_EXEC Params.
2641  * Note we assume that all the PlanStates share the same rtable.
2642  *
2643  * Once this function has been called, deparse_expression() can be called on
2644  * subsidiary expression(s) of the specified PlanState node. To deparse
2645  * expressions of a different Plan node in the same Plan tree, re-call this
2646  * function to identify the new parent Plan node.
2647  *
2648  * The result is the same List passed in; this is a notational convenience.
2649  */
2650 List *
2652  Node *planstate, List *ancestors)
2653 {
2654  deparse_namespace *dpns;
2655 
2656  /* Should always have one-entry namespace list for Plan deparsing */
2657  Assert(list_length(dpcontext) == 1);
2658  dpns = (deparse_namespace *) linitial(dpcontext);
2659 
2660  /* Set our attention on the specific plan node passed in */
2661  set_deparse_planstate(dpns, (PlanState *) planstate);
2662  dpns->ancestors = ancestors;
2663 
2664  return dpcontext;
2665 }
2666 
2667 /*
2668  * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
2669  *
2670  * Determine the relation aliases we'll use during an EXPLAIN operation.
2671  * This is just a frontend to set_rtable_names. We have to expose the aliases
2672  * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
2673  */
2674 List *
2676 {
2677  deparse_namespace dpns;
2678 
2679  memset(&dpns, 0, sizeof(dpns));
2680  dpns.rtable = rtable;
2681  dpns.ctes = NIL;
2682  set_rtable_names(&dpns, NIL, rels_used);
2683  /* We needn't bother computing column aliases yet */
2684 
2685  return dpns.rtable_names;
2686 }
2687 
2688 /*
2689  * set_rtable_names: select RTE aliases to be used in printing a query
2690  *
2691  * We fill in dpns->rtable_names with a list of names that is one-for-one with
2692  * the already-filled dpns->rtable list. Each RTE name is unique among those
2693  * in the new namespace plus any ancestor namespaces listed in
2694  * parent_namespaces.
2695  *
2696  * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
2697  *
2698  * Note that this function is only concerned with relation names, not column
2699  * names.
2700  */
2701 static void
2702 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
2703  Bitmapset *rels_used)
2704 {
2705  HASHCTL hash_ctl;
2706  HTAB *names_hash;
2707  NameHashEntry *hentry;
2708  bool found;
2709  int rtindex;
2710  ListCell *lc;
2711 
2712  dpns->rtable_names = NIL;
2713  /* nothing more to do if empty rtable */
2714  if (dpns->rtable == NIL)
2715  return;
2716 
2717  /*
2718  * We use a hash table to hold known names, so that this process is O(N)
2719  * not O(N^2) for N names.
2720  */
2721  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
2722  hash_ctl.keysize = NAMEDATALEN;
2723  hash_ctl.entrysize = sizeof(NameHashEntry);
2724  hash_ctl.hcxt = CurrentMemoryContext;
2725  names_hash = hash_create("set_rtable_names names",
2726  list_length(dpns->rtable),
2727  &hash_ctl,
2729  /* Preload the hash table with names appearing in parent_namespaces */
2730  foreach(lc, parent_namespaces)
2731  {
2732  deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
2733  ListCell *lc2;
2734 
2735  foreach(lc2, olddpns->rtable_names)
2736  {
2737  char *oldname = (char *) lfirst(lc2);
2738 
2739  if (oldname == NULL)
2740  continue;
2741  hentry = (NameHashEntry *) hash_search(names_hash,
2742  oldname,
2743  HASH_ENTER,
2744  &found);
2745  /* we do not complain about duplicate names in parent namespaces */
2746  hentry->counter = 0;
2747  }
2748  }
2749 
2750  /* Now we can scan the rtable */
2751  rtindex = 1;
2752  foreach(lc, dpns->rtable)
2753  {
2754  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2755  char *refname;
2756 
2757  /* Just in case this takes an unreasonable amount of time ... */
2759 
2760  if (rels_used && !bms_is_member(rtindex, rels_used))
2761  {
2762  /* Ignore unreferenced RTE */
2763  refname = NULL;
2764  }
2765  else if (rte->alias)
2766  {
2767  /* If RTE has a user-defined alias, prefer that */
2768  refname = rte->alias->aliasname;
2769  }
2770  else if (rte->rtekind == RTE_RELATION)
2771  {
2772  /* Use the current actual name of the relation */
2773  refname = get_rel_name(rte->relid);
2774  }
2775  else if (rte->rtekind == RTE_JOIN)
2776  {
2777  /* Unnamed join has no refname */
2778  refname = NULL;
2779  }
2780  else
2781  {
2782  /* Otherwise use whatever the parser assigned */
2783  refname = rte->eref->aliasname;
2784  }
2785 
2786  /*
2787  * If the selected name isn't unique, append digits to make it so, and
2788  * make a new hash entry for it once we've got a unique name. For a
2789  * very long input name, we might have to truncate to stay within
2790  * NAMEDATALEN.
2791  */
2792  if (refname)
2793  {
2794  hentry = (NameHashEntry *) hash_search(names_hash,
2795  refname,
2796  HASH_ENTER,
2797  &found);
2798  if (found)
2799  {
2800  /* Name already in use, must choose a new one */
2801  int refnamelen = strlen(refname);
2802  char *modname = (char *) palloc(refnamelen + 16);
2803  NameHashEntry *hentry2;
2804 
2805  do
2806  {
2807  hentry->counter++;
2808  for (;;)
2809  {
2810  /*
2811  * We avoid using %.*s here because it can misbehave
2812  * if the data is not valid in what libc thinks is the
2813  * prevailing encoding.
2814  */
2815  memcpy(modname, refname, refnamelen);
2816  sprintf(modname + refnamelen, "_%d", hentry->counter);
2817  if (strlen(modname) < NAMEDATALEN)
2818  break;
2819  /* drop chars from refname to keep all the digits */
2820  refnamelen = pg_mbcliplen(refname, refnamelen,
2821  refnamelen - 1);
2822  }
2823  hentry2 = (NameHashEntry *) hash_search(names_hash,
2824  modname,
2825  HASH_ENTER,
2826  &found);
2827  } while (found);
2828  hentry2->counter = 0; /* init new hash entry */
2829  refname = modname;
2830  }
2831  else
2832  {
2833  /* Name not previously used, need only initialize hentry */
2834  hentry->counter = 0;
2835  }
2836  }
2837 
2838  dpns->rtable_names = lappend(dpns->rtable_names, refname);
2839  rtindex++;
2840  }
2841 
2842  hash_destroy(names_hash);
2843 }
2844 
2845 /*
2846  * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
2847  *
2848  * For convenience, this is defined to initialize the deparse_namespace struct
2849  * from scratch.
2850  */
2851 static void
2853  List *parent_namespaces)
2854 {
2855  ListCell *lc;
2856  ListCell *lc2;
2857 
2858  /* Initialize *dpns and fill rtable/ctes links */
2859  memset(dpns, 0, sizeof(deparse_namespace));
2860  dpns->rtable = query->rtable;
2861  dpns->ctes = query->cteList;
2862 
2863  /* Assign a unique relation alias to each RTE */
2864  set_rtable_names(dpns, parent_namespaces, NULL);
2865 
2866  /* Initialize dpns->rtable_columns to contain zeroed structs */
2867  dpns->rtable_columns = NIL;
2868  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
2869  dpns->rtable_columns = lappend(dpns->rtable_columns,
2870  palloc0(sizeof(deparse_columns)));
2871 
2872  /* If it's a utility query, it won't have a jointree */
2873  if (query->jointree)
2874  {
2875  /* Detect whether global uniqueness of USING names is needed */
2876  dpns->unique_using =
2877  has_dangerous_join_using(dpns, (Node *) query->jointree);
2878 
2879  /*
2880  * Select names for columns merged by USING, via a recursive pass over
2881  * the query jointree.
2882  */
2883  set_using_names(dpns, (Node *) query->jointree, NIL);
2884  }
2885 
2886  /*
2887  * Now assign remaining column aliases for each RTE. We do this in a
2888  * linear scan of the rtable, so as to process RTEs whether or not they
2889  * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
2890  * etc). JOIN RTEs must be processed after their children, but this is
2891  * okay because they appear later in the rtable list than their children
2892  * (cf Asserts in identify_join_columns()).
2893  */
2894  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
2895  {
2896  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2897  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
2898 
2899  if (rte->rtekind == RTE_JOIN)
2900  set_join_column_names(dpns, rte, colinfo);
2901  else
2902  set_relation_column_names(dpns, rte, colinfo);
2903  }
2904 }
2905 
2906 /*
2907  * set_simple_column_names: fill in column aliases for non-query situations
2908  *
2909  * This handles EXPLAIN and cases where we only have relation RTEs. Without
2910  * a join tree, we can't do anything smart about join RTEs, but we don't
2911  * need to (note that EXPLAIN should never see join alias Vars anyway).
2912  * If we do hit a join RTE we'll just process it like a non-table base RTE.
2913  */
2914 static void
2916 {
2917  ListCell *lc;
2918  ListCell *lc2;
2919 
2920  /* Initialize dpns->rtable_columns to contain zeroed structs */
2921  dpns->rtable_columns = NIL;
2922  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
2923  dpns->rtable_columns = lappend(dpns->rtable_columns,
2924  palloc0(sizeof(deparse_columns)));
2925 
2926  /* Assign unique column aliases within each RTE */
2927  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
2928  {
2929  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2930  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
2931 
2932  set_relation_column_names(dpns, rte, colinfo);
2933  }
2934 }
2935 
2936 /*
2937  * has_dangerous_join_using: search jointree for unnamed JOIN USING
2938  *
2939  * Merged columns of a JOIN USING may act differently from either of the input
2940  * columns, either because they are merged with COALESCE (in a FULL JOIN) or
2941  * because an implicit coercion of the underlying input column is required.
2942  * In such a case the column must be referenced as a column of the JOIN not as
2943  * a column of either input. And this is problematic if the join is unnamed
2944  * (alias-less): we cannot qualify the column's name with an RTE name, since
2945  * there is none. (Forcibly assigning an alias to the join is not a solution,
2946  * since that will prevent legal references to tables below the join.)
2947  * To ensure that every column in the query is unambiguously referenceable,
2948  * we must assign such merged columns names that are globally unique across
2949  * the whole query, aliasing other columns out of the way as necessary.
2950  *
2951  * Because the ensuing re-aliasing is fairly damaging to the readability of
2952  * the query, we don't do this unless we have to. So, we must pre-scan
2953  * the join tree to see if we have to, before starting set_using_names().
2954  */
2955 static bool
2957 {
2958  if (IsA(jtnode, RangeTblRef))
2959  {
2960  /* nothing to do here */
2961  }
2962  else if (IsA(jtnode, FromExpr))
2963  {
2964  FromExpr *f = (FromExpr *) jtnode;
2965  ListCell *lc;
2966 
2967  foreach(lc, f->fromlist)
2968  {
2969  if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
2970  return true;
2971  }
2972  }
2973  else if (IsA(jtnode, JoinExpr))
2974  {
2975  JoinExpr *j = (JoinExpr *) jtnode;
2976 
2977  /* Is it an unnamed JOIN with USING? */
2978  if (j->alias == NULL && j->usingClause)
2979  {
2980  /*
2981  * Yes, so check each join alias var to see if any of them are not
2982  * simple references to underlying columns. If so, we have a
2983  * dangerous situation and must pick unique aliases.
2984  */
2985  RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
2986  ListCell *lc;
2987 
2988  foreach(lc, jrte->joinaliasvars)
2989  {
2990  Var *aliasvar = (Var *) lfirst(lc);
2991 
2992  if (aliasvar != NULL && !IsA(aliasvar, Var))
2993  return true;
2994  }
2995  }
2996 
2997  /* Nope, but inspect children */
2998  if (has_dangerous_join_using(dpns, j->larg))
2999  return true;
3000  if (has_dangerous_join_using(dpns, j->rarg))
3001  return true;
3002  }
3003  else
3004  elog(ERROR, "unrecognized node type: %d",
3005  (int) nodeTag(jtnode));
3006  return false;
3007 }
3008 
3009 /*
3010  * set_using_names: select column aliases to be used for merged USING columns
3011  *
3012  * We do this during a recursive descent of the query jointree.
3013  * dpns->unique_using must already be set to determine the global strategy.
3014  *
3015  * Column alias info is saved in the dpns->rtable_columns list, which is
3016  * assumed to be filled with pre-zeroed deparse_columns structs.
3017  *
3018  * parentUsing is a list of all USING aliases assigned in parent joins of
3019  * the current jointree node. (The passed-in list must not be modified.)
3020  */
3021 static void
3022 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
3023 {
3024  if (IsA(jtnode, RangeTblRef))
3025  {
3026  /* nothing to do now */
3027  }
3028  else if (IsA(jtnode, FromExpr))
3029  {
3030  FromExpr *f = (FromExpr *) jtnode;
3031  ListCell *lc;
3032 
3033  foreach(lc, f->fromlist)
3034  set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
3035  }
3036  else if (IsA(jtnode, JoinExpr))
3037  {
3038  JoinExpr *j = (JoinExpr *) jtnode;
3039  RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
3040  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
3041  int *leftattnos;
3042  int *rightattnos;
3043  deparse_columns *leftcolinfo;
3044  deparse_columns *rightcolinfo;
3045  int i;
3046  ListCell *lc;
3047 
3048  /* Get info about the shape of the join */
3049  identify_join_columns(j, rte, colinfo);
3050  leftattnos = colinfo->leftattnos;
3051  rightattnos = colinfo->rightattnos;
3052 
3053  /* Look up the not-yet-filled-in child deparse_columns structs */
3054  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
3055  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
3056 
3057  /*
3058  * If this join is unnamed, then we cannot substitute new aliases at
3059  * this level, so any name requirements pushed down to here must be
3060  * pushed down again to the children.
3061  */
3062  if (rte->alias == NULL)
3063  {
3064  for (i = 0; i < colinfo->num_cols; i++)
3065  {
3066  char *colname = colinfo->colnames[i];
3067 
3068  if (colname == NULL)
3069  continue;
3070 
3071  /* Push down to left column, unless it's a system column */
3072  if (leftattnos[i] > 0)
3073  {
3074  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
3075  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
3076  }
3077 
3078  /* Same on the righthand side */
3079  if (rightattnos[i] > 0)
3080  {
3081  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
3082  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
3083  }
3084  }
3085  }
3086 
3087  /*
3088  * If there's a USING clause, select the USING column names and push
3089  * those names down to the children. We have two strategies:
3090  *
3091  * If dpns->unique_using is TRUE, we force all USING names to be
3092  * unique across the whole query level. In principle we'd only need
3093  * the names of dangerous USING columns to be globally unique, but to
3094  * safely assign all USING names in a single pass, we have to enforce
3095  * the same uniqueness rule for all of them. However, if a USING
3096  * column's name has been pushed down from the parent, we should use
3097  * it as-is rather than making a uniqueness adjustment. This is
3098  * necessary when we're at an unnamed join, and it creates no risk of
3099  * ambiguity. Also, if there's a user-written output alias for a
3100  * merged column, we prefer to use that rather than the input name;
3101  * this simplifies the logic and seems likely to lead to less aliasing
3102  * overall.
3103  *
3104  * If dpns->unique_using is FALSE, we only need USING names to be
3105  * unique within their own join RTE. We still need to honor
3106  * pushed-down names, though.
3107  *
3108  * Though significantly different in results, these two strategies are
3109  * implemented by the same code, with only the difference of whether
3110  * to put assigned names into dpns->using_names.
3111  */
3112  if (j->usingClause)
3113  {
3114  /* Copy the input parentUsing list so we don't modify it */
3115  parentUsing = list_copy(parentUsing);
3116 
3117  /* USING names must correspond to the first join output columns */
3119  i = 0;
3120  foreach(lc, j->usingClause)
3121  {
3122  char *colname = strVal(lfirst(lc));
3123 
3124  /* Assert it's a merged column */
3125  Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
3126 
3127  /* Adopt passed-down name if any, else select unique name */
3128  if (colinfo->colnames[i] != NULL)
3129  colname = colinfo->colnames[i];
3130  else
3131  {
3132  /* Prefer user-written output alias if any */
3133  if (rte->alias && i < list_length(rte->alias->colnames))
3134  colname = strVal(list_nth(rte->alias->colnames, i));
3135  /* Make it appropriately unique */
3136  colname = make_colname_unique(colname, dpns, colinfo);
3137  if (dpns->unique_using)
3138  dpns->using_names = lappend(dpns->using_names,
3139  colname);
3140  /* Save it as output column name, too */
3141  colinfo->colnames[i] = colname;
3142  }
3143 
3144  /* Remember selected names for use later */
3145  colinfo->usingNames = lappend(colinfo->usingNames, colname);
3146  parentUsing = lappend(parentUsing, colname);
3147 
3148  /* Push down to left column, unless it's a system column */
3149  if (leftattnos[i] > 0)
3150  {
3151  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
3152  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
3153  }
3154 
3155  /* Same on the righthand side */
3156  if (rightattnos[i] > 0)
3157  {
3158  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
3159  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
3160  }
3161 
3162  i++;
3163  }
3164  }
3165 
3166  /* Mark child deparse_columns structs with correct parentUsing info */
3167  leftcolinfo->parentUsing = parentUsing;
3168  rightcolinfo->parentUsing = parentUsing;
3169 
3170  /* Now recursively assign USING column names in children */
3171  set_using_names(dpns, j->larg, parentUsing);
3172  set_using_names(dpns, j->rarg, parentUsing);
3173  }
3174  else
3175  elog(ERROR, "unrecognized node type: %d",
3176  (int) nodeTag(jtnode));
3177 }
3178 
3179 /*
3180  * set_relation_column_names: select column aliases for a non-join RTE
3181  *
3182  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
3183  * If any colnames entries are already filled in, those override local
3184  * choices.
3185  */
3186 static void
3188  deparse_columns *colinfo)
3189 {
3190  int ncolumns;
3191  char **real_colnames;
3192  bool changed_any;
3193  int noldcolumns;
3194  int i;
3195  int j;
3196 
3197  /*
3198  * Extract the RTE's "real" column names. This is comparable to
3199  * get_rte_attribute_name, except that it's important to disregard dropped
3200  * columns. We put NULL into the array for a dropped column.
3201  */
3202  if (rte->rtekind == RTE_RELATION)
3203  {
3204  /* Relation --- look to the system catalogs for up-to-date info */
3205  Relation rel;
3206  TupleDesc tupdesc;
3207 
3208  rel = relation_open(rte->relid, AccessShareLock);
3209  tupdesc = RelationGetDescr(rel);
3210 
3211  ncolumns = tupdesc->natts;
3212  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
3213 
3214  for (i = 0; i < ncolumns; i++)
3215  {
3216  if (tupdesc->attrs[i]->attisdropped)
3217  real_colnames[i] = NULL;
3218  else
3219  real_colnames[i] = pstrdup(NameStr(tupdesc->attrs[i]->attname));
3220  }
3222  }
3223  else
3224  {
3225  /* Otherwise use the column names from eref */
3226  ListCell *lc;
3227 
3228  ncolumns = list_length(rte->eref->colnames);
3229  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
3230 
3231  i = 0;
3232  foreach(lc, rte->eref->colnames)
3233  {
3234  /*
3235  * If the column name shown in eref is an empty string, then it's
3236  * a column that was dropped at the time of parsing the query, so
3237  * treat it as dropped.
3238  */
3239  char *cname = strVal(lfirst(lc));
3240 
3241  if (cname[0] == '\0')
3242  cname = NULL;
3243  real_colnames[i] = cname;
3244  i++;
3245  }
3246  }
3247 
3248  /*
3249  * Ensure colinfo->colnames has a slot for each column. (It could be long
3250  * enough already, if we pushed down a name for the last column.) Note:
3251  * it's possible that there are now more columns than there were when the
3252  * query was parsed, ie colnames could be longer than rte->eref->colnames.
3253  * We must assign unique aliases to the new columns too, else there could
3254  * be unresolved conflicts when the view/rule is reloaded.
3255  */
3256  expand_colnames_array_to(colinfo, ncolumns);
3257  Assert(colinfo->num_cols == ncolumns);
3258 
3259  /*
3260  * Make sufficiently large new_colnames and is_new_col arrays, too.
3261  *
3262  * Note: because we leave colinfo->num_new_cols zero until after the loop,
3263  * colname_is_unique will not consult that array, which is fine because it
3264  * would only be duplicate effort.
3265  */
3266  colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
3267  colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
3268 
3269  /*
3270  * Scan the columns, select a unique alias for each one, and store it in
3271  * colinfo->colnames and colinfo->new_colnames. The former array has NULL
3272  * entries for dropped columns, the latter omits them. Also mark
3273  * new_colnames entries as to whether they are new since parse time; this
3274  * is the case for entries beyond the length of rte->eref->colnames.
3275  */
3276  noldcolumns = list_length(rte->eref->colnames);
3277  changed_any = false;
3278  j = 0;
3279  for (i = 0; i < ncolumns; i++)
3280  {
3281  char *real_colname = real_colnames[i];
3282  char *colname = colinfo->colnames[i];
3283 
3284  /* Skip dropped columns */
3285  if (real_colname == NULL)
3286  {
3287  Assert(colname == NULL); /* colnames[i] is already NULL */
3288  continue;
3289  }
3290 
3291  /* If alias already assigned, that's what to use */
3292  if (colname == NULL)
3293  {
3294  /* If user wrote an alias, prefer that over real column name */
3295  if (rte->alias && i < list_length(rte->alias->colnames))
3296  colname = strVal(list_nth(rte->alias->colnames, i));
3297  else
3298  colname = real_colname;
3299 
3300  /* Unique-ify and insert into colinfo */
3301  colname = make_colname_unique(colname, dpns, colinfo);
3302 
3303  colinfo->colnames[i] = colname;
3304  }
3305 
3306  /* Put names of non-dropped columns in new_colnames[] too */
3307  colinfo->new_colnames[j] = colname;
3308  /* And mark them as new or not */
3309  colinfo->is_new_col[j] = (i >= noldcolumns);
3310  j++;
3311 
3312  /* Remember if any assigned aliases differ from "real" name */
3313  if (!changed_any && strcmp(colname, real_colname) != 0)
3314  changed_any = true;
3315  }
3316 
3317  /*
3318  * Set correct length for new_colnames[] array. (Note: if columns have
3319  * been added, colinfo->num_cols includes them, which is not really quite
3320  * right but is harmless, since any new columns must be at the end where
3321  * they won't affect varattnos of pre-existing columns.)
3322  */
3323  colinfo->num_new_cols = j;
3324 
3325  /*
3326  * For a relation RTE, we need only print the alias column names if any
3327  * are different from the underlying "real" names. For a function RTE,
3328  * always emit a complete column alias list; this is to protect against
3329  * possible instability of the default column names (eg, from altering
3330  * parameter names). For other RTE types, print if we changed anything OR
3331  * if there were user-written column aliases (since the latter would be
3332  * part of the underlying "reality").
3333  */
3334  if (rte->rtekind == RTE_RELATION)
3335  colinfo->printaliases = changed_any;
3336  else if (rte->rtekind == RTE_FUNCTION)
3337  colinfo->printaliases = true;
3338  else if (rte->alias && rte->alias->colnames != NIL)
3339  colinfo->printaliases = true;
3340  else
3341  colinfo->printaliases = changed_any;
3342 }
3343 
3344 /*
3345  * set_join_column_names: select column aliases for a join RTE
3346  *
3347  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
3348  * If any colnames entries are already filled in, those override local
3349  * choices. Also, names for USING columns were already chosen by
3350  * set_using_names(). We further expect that column alias selection has been
3351  * completed for both input RTEs.
3352  */
3353 static void
3355  deparse_columns *colinfo)
3356 {
3357  deparse_columns *leftcolinfo;
3358  deparse_columns *rightcolinfo;
3359  bool changed_any;
3360  int noldcolumns;
3361  int nnewcolumns;
3362  Bitmapset *leftmerged = NULL;
3363  Bitmapset *rightmerged = NULL;
3364  int i;
3365  int j;
3366  int ic;
3367  int jc;
3368 
3369  /* Look up the previously-filled-in child deparse_columns structs */
3370  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
3371  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
3372 
3373  /*
3374  * Ensure colinfo->colnames has a slot for each column. (It could be long
3375  * enough already, if we pushed down a name for the last column.) Note:
3376  * it's possible that one or both inputs now have more columns than there
3377  * were when the query was parsed, but we'll deal with that below. We
3378  * only need entries in colnames for pre-existing columns.
3379  */
3380  noldcolumns = list_length(rte->eref->colnames);
3381  expand_colnames_array_to(colinfo, noldcolumns);
3382  Assert(colinfo->num_cols == noldcolumns);
3383 
3384  /*
3385  * Scan the join output columns, select an alias for each one, and store
3386  * it in colinfo->colnames. If there are USING columns, set_using_names()
3387  * already selected their names, so we can start the loop at the first
3388  * non-merged column.
3389  */
3390  changed_any = false;
3391  for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
3392  {
3393  char *colname = colinfo->colnames[i];
3394  char *real_colname;
3395 
3396  /* Ignore dropped column (only possible for non-merged column) */
3397  if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0)
3398  {
3399  Assert(colname == NULL);
3400  continue;
3401  }
3402 
3403  /* Get the child column name */
3404  if (colinfo->leftattnos[i] > 0)
3405  real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
3406  else if (colinfo->rightattnos[i] > 0)
3407  real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
3408  else
3409  {
3410  /* We're joining system columns --- use eref name */
3411  real_colname = strVal(list_nth(rte->eref->colnames, i));
3412  }
3413  Assert(real_colname != NULL);
3414 
3415  /* In an unnamed join, just report child column names as-is */
3416  if (rte->alias == NULL)
3417  {
3418  colinfo->colnames[i] = real_colname;
3419  continue;
3420  }
3421 
3422  /* If alias already assigned, that's what to use */
3423  if (colname == NULL)
3424  {
3425  /* If user wrote an alias, prefer that over real column name */
3426  if (rte->alias && i < list_length(rte->alias->colnames))
3427  colname = strVal(list_nth(rte->alias->colnames, i));
3428  else
3429  colname = real_colname;
3430 
3431  /* Unique-ify and insert into colinfo */
3432  colname = make_colname_unique(colname, dpns, colinfo);
3433 
3434  colinfo->colnames[i] = colname;
3435  }
3436 
3437  /* Remember if any assigned aliases differ from "real" name */
3438  if (!changed_any && strcmp(colname, real_colname) != 0)
3439  changed_any = true;
3440  }
3441 
3442  /*
3443  * Calculate number of columns the join would have if it were re-parsed
3444  * now, and create storage for the new_colnames and is_new_col arrays.
3445  *
3446  * Note: colname_is_unique will be consulting new_colnames[] during the
3447  * loops below, so its not-yet-filled entries must be zeroes.
3448  */
3449  nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
3450  list_length(colinfo->usingNames);
3451  colinfo->num_new_cols = nnewcolumns;
3452  colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
3453  colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
3454 
3455  /*
3456  * Generating the new_colnames array is a bit tricky since any new columns
3457  * added since parse time must be inserted in the right places. This code
3458  * must match the parser, which will order a join's columns as merged
3459  * columns first (in USING-clause order), then non-merged columns from the
3460  * left input (in attnum order), then non-merged columns from the right
3461  * input (ditto). If one of the inputs is itself a join, its columns will
3462  * be ordered according to the same rule, which means newly-added columns
3463  * might not be at the end. We can figure out what's what by consulting
3464  * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
3465  *
3466  * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
3467  * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
3468  * meanings for the current child RTE.
3469  */
3470 
3471  /* Handle merged columns; they are first and can't be new */
3472  i = j = 0;
3473  while (i < noldcolumns &&
3474  colinfo->leftattnos[i] != 0 &&
3475  colinfo->rightattnos[i] != 0)
3476  {
3477  /* column name is already determined and known unique */
3478  colinfo->new_colnames[j] = colinfo->colnames[i];
3479  colinfo->is_new_col[j] = false;
3480 
3481  /* build bitmapsets of child attnums of merged columns */
3482  if (colinfo->leftattnos[i] > 0)
3483  leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
3484  if (colinfo->rightattnos[i] > 0)
3485  rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
3486 
3487  i++, j++;
3488  }
3489 
3490  /* Handle non-merged left-child columns */
3491  ic = 0;
3492  for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
3493  {
3494  char *child_colname = leftcolinfo->new_colnames[jc];
3495 
3496  if (!leftcolinfo->is_new_col[jc])
3497  {
3498  /* Advance ic to next non-dropped old column of left child */
3499  while (ic < leftcolinfo->num_cols &&
3500  leftcolinfo->colnames[ic] == NULL)
3501  ic++;
3502  Assert(ic < leftcolinfo->num_cols);
3503  ic++;
3504  /* If it is a merged column, we already processed it */
3505  if (bms_is_member(ic, leftmerged))
3506  continue;
3507  /* Else, advance i to the corresponding existing join column */
3508  while (i < colinfo->num_cols &&
3509  colinfo->colnames[i] == NULL)
3510  i++;
3511  Assert(i < colinfo->num_cols);
3512  Assert(ic == colinfo->leftattnos[i]);
3513  /* Use the already-assigned name of this column */
3514  colinfo->new_colnames[j] = colinfo->colnames[i];
3515  i++;
3516  }
3517  else
3518  {
3519  /*
3520  * Unique-ify the new child column name and assign, unless we're
3521  * in an unnamed join, in which case just copy
3522  */
3523  if (rte->alias != NULL)
3524  {
3525  colinfo->new_colnames[j] =
3526  make_colname_unique(child_colname, dpns, colinfo);
3527  if (!changed_any &&
3528  strcmp(colinfo->new_colnames[j], child_colname) != 0)
3529  changed_any = true;
3530  }
3531  else
3532  colinfo->new_colnames[j] = child_colname;
3533  }
3534 
3535  colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
3536  j++;
3537  }
3538 
3539  /* Handle non-merged right-child columns in exactly the same way */
3540  ic = 0;
3541  for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
3542  {
3543  char *child_colname = rightcolinfo->new_colnames[jc];
3544 
3545  if (!rightcolinfo->is_new_col[jc])
3546  {
3547  /* Advance ic to next non-dropped old column of right child */
3548  while (ic < rightcolinfo->num_cols &&
3549  rightcolinfo->colnames[ic] == NULL)
3550  ic++;
3551  Assert(ic < rightcolinfo->num_cols);
3552  ic++;
3553  /* If it is a merged column, we already processed it */
3554  if (bms_is_member(ic, rightmerged))
3555  continue;
3556  /* Else, advance i to the corresponding existing join column */
3557  while (i < colinfo->num_cols &&
3558  colinfo->colnames[i] == NULL)
3559  i++;
3560  Assert(i < colinfo->num_cols);
3561  Assert(ic == colinfo->rightattnos[i]);
3562  /* Use the already-assigned name of this column */
3563  colinfo->new_colnames[j] = colinfo->colnames[i];
3564  i++;
3565  }
3566  else
3567  {
3568  /*
3569  * Unique-ify the new child column name and assign, unless we're
3570  * in an unnamed join, in which case just copy
3571  */
3572  if (rte->alias != NULL)
3573  {
3574  colinfo->new_colnames[j] =
3575  make_colname_unique(child_colname, dpns, colinfo);
3576  if (!changed_any &&
3577  strcmp(colinfo->new_colnames[j], child_colname) != 0)
3578  changed_any = true;
3579  }
3580  else
3581  colinfo->new_colnames[j] = child_colname;
3582  }
3583 
3584  colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
3585  j++;
3586  }
3587 
3588  /* Assert we processed the right number of columns */
3589 #ifdef USE_ASSERT_CHECKING
3590  while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
3591  i++;
3592  Assert(i == colinfo->num_cols);
3593  Assert(j == nnewcolumns);
3594 #endif
3595 
3596  /*
3597  * For a named join, print column aliases if we changed any from the child
3598  * names. Unnamed joins cannot print aliases.
3599  */
3600  if (rte->alias != NULL)
3601  colinfo->printaliases = changed_any;
3602  else
3603  colinfo->printaliases = false;
3604 }
3605 
3606 /*
3607  * colname_is_unique: is colname distinct from already-chosen column names?
3608  *
3609  * dpns is query-wide info, colinfo is for the column's RTE
3610  */
3611 static bool
3613  deparse_columns *colinfo)
3614 {
3615  int i;
3616  ListCell *lc;
3617 
3618  /* Check against already-assigned column aliases within RTE */
3619  for (i = 0; i < colinfo->num_cols; i++)
3620  {
3621  char *oldname = colinfo->colnames[i];
3622 
3623  if (oldname && strcmp(oldname, colname) == 0)
3624  return false;
3625  }
3626 
3627  /*
3628  * If we're building a new_colnames array, check that too (this will be
3629  * partially but not completely redundant with the previous checks)
3630  */
3631  for (i = 0; i < colinfo->num_new_cols; i++)
3632  {
3633  char *oldname = colinfo->new_colnames[i];
3634 
3635  if (oldname && strcmp(oldname, colname) == 0)
3636  return false;
3637  }
3638 
3639  /* Also check against USING-column names that must be globally unique */
3640  foreach(lc, dpns->using_names)
3641  {
3642  char *oldname = (char *) lfirst(lc);
3643 
3644  if (strcmp(oldname, colname) == 0)
3645  return false;
3646  }
3647 
3648  /* Also check against names already assigned for parent-join USING cols */
3649  foreach(lc, colinfo->parentUsing)
3650  {
3651  char *oldname = (char *) lfirst(lc);
3652 
3653  if (strcmp(oldname, colname) == 0)
3654  return false;
3655  }
3656 
3657  return true;
3658 }
3659 
3660 /*
3661  * make_colname_unique: modify colname if necessary to make it unique
3662  *
3663  * dpns is query-wide info, colinfo is for the column's RTE
3664  */
3665 static char *
3667  deparse_columns *colinfo)
3668 {
3669  /*
3670  * If the selected name isn't unique, append digits to make it so. For a
3671  * very long input name, we might have to truncate to stay within
3672  * NAMEDATALEN.
3673  */
3674  if (!colname_is_unique(colname, dpns, colinfo))
3675  {
3676  int colnamelen = strlen(colname);
3677  char *modname = (char *) palloc(colnamelen + 16);
3678  int i = 0;
3679 
3680  do
3681  {
3682  i++;
3683  for (;;)
3684  {
3685  /*
3686  * We avoid using %.*s here because it can misbehave if the
3687  * data is not valid in what libc thinks is the prevailing
3688  * encoding.
3689  */
3690  memcpy(modname, colname, colnamelen);
3691  sprintf(modname + colnamelen, "_%d", i);
3692  if (strlen(modname) < NAMEDATALEN)
3693  break;
3694  /* drop chars from colname to keep all the digits */
3695  colnamelen = pg_mbcliplen(colname, colnamelen,
3696  colnamelen - 1);
3697  }
3698  } while (!colname_is_unique(modname, dpns, colinfo));
3699  colname = modname;
3700  }
3701  return colname;
3702 }
3703 
3704 /*
3705  * expand_colnames_array_to: make colinfo->colnames at least n items long
3706  *
3707  * Any added array entries are initialized to zero.
3708  */
3709 static void
3711 {
3712  if (n > colinfo->num_cols)
3713  {
3714  if (colinfo->colnames == NULL)
3715  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
3716  else
3717  {
3718  colinfo->colnames = (char **) repalloc(colinfo->colnames,
3719  n * sizeof(char *));
3720  memset(colinfo->colnames + colinfo->num_cols, 0,
3721  (n - colinfo->num_cols) * sizeof(char *));
3722  }
3723  colinfo->num_cols = n;
3724  }
3725 }
3726 
3727 /*
3728  * identify_join_columns: figure out where columns of a join come from
3729  *
3730  * Fills the join-specific fields of the colinfo struct, except for
3731  * usingNames which is filled later.
3732  */
3733 static void
3735  deparse_columns *colinfo)
3736 {
3737  int numjoincols;
3738  int i;
3739  ListCell *lc;
3740 
3741  /* Extract left/right child RT indexes */
3742  if (IsA(j->larg, RangeTblRef))
3743  colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
3744  else if (IsA(j->larg, JoinExpr))
3745  colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
3746  else
3747  elog(ERROR, "unrecognized node type in jointree: %d",
3748  (int) nodeTag(j->larg));
3749  if (IsA(j->rarg, RangeTblRef))
3750  colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
3751  else if (IsA(j->rarg, JoinExpr))
3752  colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
3753  else
3754  elog(ERROR, "unrecognized node type in jointree: %d",
3755  (int) nodeTag(j->rarg));
3756 
3757  /* Assert children will be processed earlier than join in second pass */
3758  Assert(colinfo->leftrti < j->rtindex);
3759  Assert(colinfo->rightrti < j->rtindex);
3760 
3761  /* Initialize result arrays with zeroes */
3762  numjoincols = list_length(jrte->joinaliasvars);
3763  Assert(numjoincols == list_length(jrte->eref->colnames));
3764  colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
3765  colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
3766 
3767  /* Scan the joinaliasvars list to identify simple column references */
3768  i = 0;
3769  foreach(lc, jrte->joinaliasvars)
3770  {
3771  Var *aliasvar = (Var *) lfirst(lc);
3772 
3773  /* get rid of any implicit coercion above the Var */
3774  aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
3775 
3776  if (aliasvar == NULL)
3777  {
3778  /* It's a dropped column; nothing to do here */
3779  }
3780  else if (IsA(aliasvar, Var))
3781  {
3782  Assert(aliasvar->varlevelsup == 0);
3783  Assert(aliasvar->varattno != 0);
3784  if (aliasvar->varno == colinfo->leftrti)
3785  colinfo->leftattnos[i] = aliasvar->varattno;
3786  else if (aliasvar->varno == colinfo->rightrti)
3787  colinfo->rightattnos[i] = aliasvar->varattno;
3788  else
3789  elog(ERROR, "unexpected varno %d in JOIN RTE",
3790  aliasvar->varno);
3791  }
3792  else if (IsA(aliasvar, CoalesceExpr))
3793  {
3794  /*
3795  * It's a merged column in FULL JOIN USING. Ignore it for now and
3796  * let the code below identify the merged columns.
3797  */
3798  }
3799  else
3800  elog(ERROR, "unrecognized node type in join alias vars: %d",
3801  (int) nodeTag(aliasvar));
3802 
3803  i++;
3804  }
3805 
3806  /*
3807  * If there's a USING clause, deconstruct the join quals to identify the
3808  * merged columns. This is a tad painful but if we cannot rely on the
3809  * column names, there is no other representation of which columns were
3810  * joined by USING. (Unless the join type is FULL, we can't tell from the
3811  * joinaliasvars list which columns are merged.) Note: we assume that the
3812  * merged columns are the first output column(s) of the join.
3813  */
3814  if (j->usingClause)
3815  {
3816  List *leftvars = NIL;
3817  List *rightvars = NIL;
3818  ListCell *lc2;
3819 
3820  /* Extract left- and right-side Vars from the qual expression */
3821  flatten_join_using_qual(j->quals, &leftvars, &rightvars);
3822  Assert(list_length(leftvars) == list_length(j->usingClause));
3823  Assert(list_length(rightvars) == list_length(j->usingClause));
3824 
3825  /* Mark the output columns accordingly */
3826  i = 0;
3827  forboth(lc, leftvars, lc2, rightvars)
3828  {
3829  Var *leftvar = (Var *) lfirst(lc);
3830  Var *rightvar = (Var *) lfirst(lc2);
3831 
3832  Assert(leftvar->varlevelsup == 0);
3833  Assert(leftvar->varattno != 0);
3834  if (leftvar->varno != colinfo->leftrti)
3835  elog(ERROR, "unexpected varno %d in JOIN USING qual",
3836  leftvar->varno);
3837  colinfo->leftattnos[i] = leftvar->varattno;
3838 
3839  Assert(rightvar->varlevelsup == 0);
3840  Assert(rightvar->varattno != 0);
3841  if (rightvar->varno != colinfo->rightrti)
3842  elog(ERROR, "unexpected varno %d in JOIN USING qual",
3843  rightvar->varno);
3844  colinfo->rightattnos[i] = rightvar->varattno;
3845 
3846  i++;
3847  }
3848  }
3849 }
3850 
3851 /*
3852  * flatten_join_using_qual: extract Vars being joined from a JOIN/USING qual
3853  *
3854  * We assume that transformJoinUsingClause won't have produced anything except
3855  * AND nodes, equality operator nodes, and possibly implicit coercions, and
3856  * that the AND node inputs match left-to-right with the original USING list.
3857  *
3858  * Caller must initialize the result lists to NIL.
3859  */
3860 static void
3861 flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
3862 {
3863  if (IsA(qual, BoolExpr))
3864  {
3865  /* Handle AND nodes by recursion */
3866  BoolExpr *b = (BoolExpr *) qual;
3867  ListCell *lc;
3868 
3869  Assert(b->boolop == AND_EXPR);
3870  foreach(lc, b->args)
3871  {
3873  leftvars, rightvars);
3874  }
3875  }
3876  else if (IsA(qual, OpExpr))
3877  {
3878  /* Otherwise we should have an equality operator */
3879  OpExpr *op = (OpExpr *) qual;
3880  Var *var;
3881 
3882  if (list_length(op->args) != 2)
3883  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
3884  /* Arguments should be Vars with perhaps implicit coercions */
3885  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
3886  if (!IsA(var, Var))
3887  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
3888  (int) nodeTag(var));
3889  *leftvars = lappend(*leftvars, var);
3890  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
3891  if (!IsA(var, Var))
3892  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
3893  (int) nodeTag(var));
3894  *rightvars = lappend(*rightvars, var);
3895  }
3896  else
3897  {
3898  /* Perhaps we have an implicit coercion to boolean? */
3899  Node *q = strip_implicit_coercions(qual);
3900 
3901  if (q != qual)
3902  flatten_join_using_qual(q, leftvars, rightvars);
3903  else
3904  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
3905  (int) nodeTag(qual));
3906  }
3907 }
3908 
3909 /*
3910  * get_rtable_name: convenience function to get a previously assigned RTE alias
3911  *
3912  * The RTE must belong to the topmost namespace level in "context".
3913  */
3914 static char *
3915 get_rtable_name(int rtindex, deparse_context *context)
3916 {
3918 
3919  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
3920  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
3921 }
3922 
3923 /*
3924  * set_deparse_planstate: set up deparse_namespace to parse subexpressions
3925  * of a given PlanState node
3926  *
3927  * This sets the planstate, outer_planstate, inner_planstate, outer_tlist,
3928  * inner_tlist, and index_tlist fields. Caller is responsible for adjusting
3929  * the ancestors list if necessary. Note that the rtable and ctes fields do
3930  * not need to change when shifting attention to different plan nodes in a
3931  * single plan tree.
3932  */
3933 static void
3935 {
3936  dpns->planstate = ps;
3937 
3938  /*
3939  * We special-case Append and MergeAppend to pretend that the first child
3940  * plan is the OUTER referent; we have to interpret OUTER Vars in their
3941  * tlists according to one of the children, and the first one is the most
3942  * natural choice. Likewise special-case ModifyTable to pretend that the
3943  * first child plan is the OUTER referent; this is to support RETURNING
3944  * lists containing references to non-target relations.
3945  */
3946  if (IsA(ps, AppendState))
3947  dpns->outer_planstate = ((AppendState *) ps)->appendplans[0];
3948  else if (IsA(ps, MergeAppendState))
3949  dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0];
3950  else if (IsA(ps, ModifyTableState))
3951  dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0];
3952  else
3953  dpns->outer_planstate = outerPlanState(ps);
3954 
3955  if (dpns->outer_planstate)
3956  dpns->outer_tlist = dpns->outer_planstate->plan->targetlist;
3957  else
3958  dpns->outer_tlist = NIL;
3959 
3960  /*
3961  * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3962  * use OUTER because that could someday conflict with the normal meaning.)
3963  * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3964  * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
3965  * excluded expression's tlist. (Similar to the SubqueryScan we don't want
3966  * to reuse OUTER, it's used for RETURNING in some modify table cases,
3967  * although not INSERT .. CONFLICT).
3968  */
3969  if (IsA(ps, SubqueryScanState))
3970  dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan;
3971  else if (IsA(ps, CteScanState))
3972  dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate;
3973  else if (IsA(ps, ModifyTableState))
3974  dpns->inner_planstate = ps;
3975  else
3976  dpns->inner_planstate = innerPlanState(ps);
3977 
3978  if (IsA(ps, ModifyTableState))
3979  dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist;
3980  else if (dpns->inner_planstate)
3981  dpns->inner_tlist = dpns->inner_planstate->plan->targetlist;
3982  else
3983  dpns->inner_tlist = NIL;
3984 
3985  /* Set up referent for INDEX_VAR Vars, if needed */
3986  if (IsA(ps->plan, IndexOnlyScan))
3987  dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist;
3988  else if (IsA(ps->plan, ForeignScan))
3989  dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist;
3990  else if (IsA(ps->plan, CustomScan))
3991  dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist;
3992  else
3993  dpns->index_tlist = NIL;
3994 }
3995 
3996 /*
3997  * push_child_plan: temporarily transfer deparsing attention to a child plan
3998  *
3999  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
4000  * deparse context in case the referenced expression itself uses
4001  * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
4002  * affecting levelsup issues (although in a Plan tree there really shouldn't
4003  * be any).
4004  *
4005  * Caller must provide a local deparse_namespace variable to save the
4006  * previous state for pop_child_plan.
4007  */
4008 static void
4010  deparse_namespace *save_dpns)
4011 {
4012  /* Save state for restoration later */
4013  *save_dpns = *dpns;
4014 
4015  /* Link current plan node into ancestors list */
4016  dpns->ancestors = lcons(dpns->planstate, dpns->ancestors);
4017 
4018  /* Set attention on selected child */
4019  set_deparse_planstate(dpns, ps);
4020 }
4021 
4022 /*
4023  * pop_child_plan: undo the effects of push_child_plan
4024  */
4025 static void
4027 {
4028  List *ancestors;
4029 
4030  /* Get rid of ancestors list cell added by push_child_plan */
4031  ancestors = list_delete_first(dpns->ancestors);
4032 
4033  /* Restore fields changed by push_child_plan */
4034  *dpns = *save_dpns;
4035 
4036  /* Make sure dpns->ancestors is right (may be unnecessary) */
4037  dpns->ancestors = ancestors;
4038 }
4039 
4040 /*
4041  * push_ancestor_plan: temporarily transfer deparsing attention to an
4042  * ancestor plan
4043  *
4044  * When expanding a Param reference, we must adjust the deparse context
4045  * to match the plan node that contains the expression being printed;
4046  * otherwise we'd fail if that expression itself contains a Param or
4047  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
4048  *
4049  * The target ancestor is conveniently identified by the ListCell holding it
4050  * in dpns->ancestors.
4051  *
4052  * Caller must provide a local deparse_namespace variable to save the
4053  * previous state for pop_ancestor_plan.
4054  */
4055 static void
4057  deparse_namespace *save_dpns)
4058 {
4059  PlanState *ps = (PlanState *) lfirst(ancestor_cell);
4060  List *ancestors;
4061 
4062  /* Save state for restoration later */
4063  *save_dpns = *dpns;
4064 
4065  /* Build a new ancestor list with just this node's ancestors */
4066  ancestors = NIL;
4067  while ((ancestor_cell = lnext(ancestor_cell)) != NULL)
4068  ancestors = lappend(ancestors, lfirst(ancestor_cell));
4069  dpns->ancestors = ancestors;
4070 
4071  /* Set attention on selected ancestor */
4072  set_deparse_planstate(dpns, ps);
4073 }
4074 
4075 /*
4076  * pop_ancestor_plan: undo the effects of push_ancestor_plan
4077  */
4078 static void
4080 {
4081  /* Free the ancestor list made in push_ancestor_plan */
4082  list_free(dpns->ancestors);
4083 
4084  /* Restore fields changed by push_ancestor_plan */
4085  *dpns = *save_dpns;
4086 }
4087 
4088 
4089 /* ----------
4090  * make_ruledef - reconstruct the CREATE RULE command
4091  * for a given pg_rewrite tuple
4092  * ----------
4093  */
4094 static void
4096  int prettyFlags)
4097 {
4098  char *rulename;
4099  char ev_type;
4100  Oid ev_class;
4101  bool is_instead;
4102  char *ev_qual;
4103  char *ev_action;
4104  List *actions = NIL;
4105  int fno;
4106  Datum dat;
4107  bool isnull;
4108 
4109  /*
4110  * Get the attribute values from the rules tuple
4111  */
4112  fno = SPI_fnumber(rulettc, "rulename");
4113  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4114  Assert(!isnull);
4115  rulename = NameStr(*(DatumGetName(dat)));
4116 
4117  fno = SPI_fnumber(rulettc, "ev_type");
4118  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4119  Assert(!isnull);
4120  ev_type = DatumGetChar(dat);
4121 
4122  fno = SPI_fnumber(rulettc, "ev_class");
4123  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4124  Assert(!isnull);
4125  ev_class = DatumGetObjectId(dat);
4126 
4127  fno = SPI_fnumber(rulettc, "is_instead");
4128  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4129  Assert(!isnull);
4130  is_instead = DatumGetBool(dat);
4131 
4132  /* these could be nulls */
4133  fno = SPI_fnumber(rulettc, "ev_qual");
4134  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
4135 
4136  fno = SPI_fnumber(rulettc, "ev_action");
4137  ev_action = SPI_getvalue(ruletup, rulettc, fno);
4138  if (ev_action != NULL)
4139  actions = (List *) stringToNode(ev_action);
4140 
4141  /*
4142  * Build the rules definition text
4143  */
4144  appendStringInfo(buf, "CREATE RULE %s AS",
4145  quote_identifier(rulename));
4146 
4147  if (prettyFlags & PRETTYFLAG_INDENT)
4148  appendStringInfoString(buf, "\n ON ");
4149  else
4150  appendStringInfoString(buf, " ON ");
4151 
4152  /* The event the rule is fired for */
4153  switch (ev_type)
4154  {
4155  case '1':
4156  appendStringInfoString(buf, "SELECT");
4157  break;
4158 
4159  case '2':
4160  appendStringInfoString(buf, "UPDATE");
4161  break;
4162 
4163  case '3':
4164  appendStringInfoString(buf, "INSERT");
4165  break;
4166 
4167  case '4':
4168  appendStringInfoString(buf, "DELETE");
4169  break;
4170 
4171  default:
4172  ereport(ERROR,
4173  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4174  errmsg("rule \"%s\" has unsupported event type %d",
4175  rulename, ev_type)));
4176  break;
4177  }
4178 
4179  /* The relation the rule is fired on */
4180  appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
4181 
4182  /* If the rule has an event qualification, add it */
4183  if (ev_qual == NULL)
4184  ev_qual = "";
4185  if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
4186  {
4187  Node *qual;
4188  Query *query;
4189  deparse_context context;
4190  deparse_namespace dpns;
4191 
4192  if (prettyFlags & PRETTYFLAG_INDENT)
4193  appendStringInfoString(buf, "\n ");
4194  appendStringInfoString(buf, " WHERE ");
4195 
4196  qual = stringToNode(ev_qual);
4197 
4198  /*
4199  * We need to make a context for recognizing any Vars in the qual
4200  * (which can only be references to OLD and NEW). Use the rtable of
4201  * the first query in the action list for this purpose.
4202  */
4203  query = (Query *) linitial(actions);
4204 
4205  /*
4206  * If the action is INSERT...SELECT, OLD/NEW have been pushed down
4207  * into the SELECT, and that's what we need to look at. (Ugly kluge
4208  * ... try to fix this when we redesign querytrees.)
4209  */
4210  query = getInsertSelectQuery(query, NULL);
4211 
4212  /* Must acquire locks right away; see notes in get_query_def() */
4213  AcquireRewriteLocks(query, false, false);
4214 
4215  context.buf = buf;
4216  context.namespaces = list_make1(&dpns);
4217  context.windowClause = NIL;
4218  context.windowTList = NIL;
4219  context.varprefix = (list_length(query->rtable) != 1);
4220  context.prettyFlags = prettyFlags;
4221  context.wrapColumn = WRAP_COLUMN_DEFAULT;
4222  context.indentLevel = PRETTYINDENT_STD;
4223  context.special_exprkind = EXPR_KIND_NONE;
4224 
4225  set_deparse_for_query(&dpns, query, NIL);
4226 
4227  get_rule_expr(qual, &context, false);
4228  }
4229 
4230  appendStringInfoString(buf, " DO ");
4231 
4232  /* The INSTEAD keyword (if so) */
4233  if (is_instead)
4234  appendStringInfoString(buf, "INSTEAD ");
4235 
4236  /* Finally the rules actions */
4237  if (list_length(actions) > 1)
4238  {
4239  ListCell *action;
4240  Query *query;
4241 
4242  appendStringInfoChar(buf, '(');
4243  foreach(action, actions)
4244  {
4245  query = (Query *) lfirst(action);
4246  get_query_def(query, buf, NIL, NULL,
4247  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
4248  if (prettyFlags)
4249  appendStringInfoString(buf, ";\n");
4250  else
4251  appendStringInfoString(buf, "; ");
4252  }
4253  appendStringInfoString(buf, ");");
4254  }
4255  else if (list_length(actions) == 0)
4256  {
4257  appendStringInfoString(buf, "NOTHING;");
4258  }
4259  else
4260  {
4261  Query *query;
4262 
4263  query = (Query *) linitial(actions);
4264  get_query_def(query, buf, NIL, NULL,
4265  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
4266  appendStringInfoChar(buf, ';');
4267  }
4268 }
4269 
4270 
4271 /* ----------
4272  * make_viewdef - reconstruct the SELECT part of a
4273  * view rewrite rule
4274  * ----------
4275  */
4276 static void
4278  int prettyFlags, int wrapColumn)
4279 {
4280  Query *query;
4281  char ev_type;
4282  Oid ev_class;
4283  bool is_instead;
4284  char *ev_qual;
4285  char *ev_action;
4286  List *actions = NIL;
4287  Relation ev_relation;
4288  int fno;
4289  bool isnull;
4290 
4291  /*
4292  * Get the attribute values from the rules tuple
4293  */
4294  fno = SPI_fnumber(rulettc, "ev_type");
4295  ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4296 
4297  fno = SPI_fnumber(rulettc, "ev_class");
4298  ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4299 
4300  fno = SPI_fnumber(rulettc, "is_instead");
4301  is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4302 
4303  fno = SPI_fnumber(rulettc, "ev_qual");
4304  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
4305 
4306  fno = SPI_fnumber(rulettc, "ev_action");
4307  ev_action = SPI_getvalue(ruletup, rulettc, fno);
4308  if (ev_action != NULL)
4309  actions = (List *) stringToNode(ev_action);
4310 
4311  if (list_length(actions) != 1)
4312  {
4313  appendStringInfoString(buf, "Not a view");
4314  return;
4315  }
4316 
4317  query = (Query *) linitial(actions);
4318 
4319  if (ev_type != '1' || !is_instead ||
4320  strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
4321  {
4322  appendStringInfoString(buf, "Not a view");
4323  return;
4324  }
4325 
4326  ev_relation = heap_open(ev_class, AccessShareLock);
4327 
4328  get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
4329  prettyFlags, wrapColumn, 0);
4330  appendStringInfoChar(buf, ';');
4331 
4332  heap_close(ev_relation, AccessShareLock);
4333 }
4334 
4335 
4336 /* ----------
4337  * get_query_def - Parse back one query parsetree
4338  *
4339  * If resultDesc is not NULL, then it is the output tuple descriptor for
4340  * the view represented by a SELECT query.
4341  * ----------
4342  */
4343 static void
4344 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
4345  TupleDesc resultDesc,
4346  int prettyFlags, int wrapColumn, int startIndent)
4347 {
4348  deparse_context context;
4349  deparse_namespace dpns;
4350 
4351  /* Guard against excessively long or deeply-nested queries */
4354 
4355  /*
4356  * Before we begin to examine the query, acquire locks on referenced
4357  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4358  * consistent results. Note we assume it's OK to scribble on the passed
4359  * querytree!
4360  *
4361  * We are only deparsing the query (we are not about to execute it), so we
4362  * only need AccessShareLock on the relations it mentions.
4363  */
4364  AcquireRewriteLocks(query, false, false);
4365 
4366  context.buf = buf;
4367  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4368  context.windowClause = NIL;
4369  context.windowTList = NIL;
4370  context.varprefix = (parentnamespace != NIL ||
4371  list_length(query->rtable) != 1);
4372  context.prettyFlags = prettyFlags;
4373  context.wrapColumn = wrapColumn;
4374  context.indentLevel = startIndent;
4375  context.special_exprkind = EXPR_KIND_NONE;
4376 
4377  set_deparse_for_query(&dpns, query, parentnamespace);
4378 
4379  switch (query->commandType)
4380  {
4381  case CMD_SELECT:
4382  get_select_query_def(query, &context, resultDesc);
4383  break;
4384 
4385  case CMD_UPDATE:
4386  get_update_query_def(query, &context);
4387  break;
4388 
4389  case CMD_INSERT:
4390  get_insert_query_def(query, &context);
4391  break;
4392 
4393  case CMD_DELETE:
4394  get_delete_query_def(query, &context);
4395  break;
4396 
4397  case CMD_NOTHING:
4398  appendStringInfoString(buf, "NOTHING");
4399  break;
4400 
4401  case CMD_UTILITY:
4402  get_utility_query_def(query, &context);
4403  break;
4404 
4405  default:
4406  elog(ERROR, "unrecognized query command type: %d",
4407  query->commandType);
4408  break;
4409  }
4410 }
4411 
4412 /* ----------
4413  * get_values_def - Parse back a VALUES list
4414  * ----------
4415  */
4416 static void
4417 get_values_def(List *values_lists, deparse_context *context)
4418 {
4419  StringInfo buf = context->buf;
4420  bool first_list = true;
4421  ListCell *vtl;
4422 
4423  appendStringInfoString(buf, "VALUES ");
4424 
4425  foreach(vtl, values_lists)
4426  {
4427  List *sublist = (List *) lfirst(vtl);
4428  bool first_col = true;
4429  ListCell *lc;
4430 
4431  if (first_list)
4432  first_list = false;
4433  else
4434  appendStringInfoString(buf, ", ");
4435 
4436  appendStringInfoChar(buf, '(');
4437  foreach(lc, sublist)
4438  {
4439  Node *col = (Node *) lfirst(lc);
4440 
4441  if (first_col)
4442  first_col = false;
4443  else
4444  appendStringInfoChar(buf, ',');
4445 
4446  /*
4447  * Strip any top-level nodes representing indirection assignments,
4448  * then print the result. Whole-row Vars need special treatment.
4449  */
4450  get_rule_expr_toplevel(processIndirection(col, context, false),
4451  context, false);
4452  }
4453  appendStringInfoChar(buf, ')');
4454  }
4455 }
4456 
4457 /* ----------
4458  * get_with_clause - Parse back a WITH clause
4459  * ----------
4460  */
4461 static void
4463 {
4464  StringInfo buf = context->buf;
4465  const char *sep;
4466  ListCell *l;
4467 
4468  if (query->cteList == NIL)
4469  return;
4470 
4471  if (PRETTY_INDENT(context))
4472  {
4473  context->indentLevel += PRETTYINDENT_STD;
4474  appendStringInfoChar(buf, ' ');
4475  }
4476 
4477  if (query->hasRecursive)
4478  sep = "WITH RECURSIVE ";
4479  else
4480  sep = "WITH ";
4481  foreach(l, query->cteList)
4482  {
4483  CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
4484 
4485  appendStringInfoString(buf, sep);
4487  if (cte->aliascolnames)
4488  {
4489  bool first = true;
4490  ListCell *col;
4491 
4492  appendStringInfoChar(buf, '(');
4493  foreach(col, cte->aliascolnames)
4494  {
4495  if (first)
4496  first = false;
4497  else
4498  appendStringInfoString(buf, ", ");
4500  quote_identifier(strVal(lfirst(col))));
4501  }
4502  appendStringInfoChar(buf, ')');
4503  }
4504  appendStringInfoString(buf, " AS (");
4505  if (PRETTY_INDENT(context))
4506  appendContextKeyword(context, "", 0, 0, 0);
4507  get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
4508  context->prettyFlags, context->wrapColumn,
4509  context->indentLevel);
4510  if (PRETTY_INDENT(context))
4511  appendContextKeyword(context, "", 0, 0, 0);
4512  appendStringInfoChar(buf, ')');
4513  sep = ", ";
4514  }
4515 
4516  if (PRETTY_INDENT(context))
4517  {
4518  context->indentLevel -= PRETTYINDENT_STD;
4519  appendContextKeyword(context, "", 0, 0, 0);
4520  }
4521  else
4522  appendStringInfoChar(buf, ' ');
4523 }
4524 
4525 /* ----------
4526  * get_select_query_def - Parse back a SELECT parsetree
4527  * ----------
4528  */
4529 static void
4531  TupleDesc resultDesc)
4532 {
4533  StringInfo buf = context->buf;
4534  List *save_windowclause;
4535  List *save_windowtlist;
4536  bool force_colno;
4537  ListCell *l;
4538 
4539  /* Insert the WITH clause if given */
4540  get_with_clause(query, context);
4541 
4542  /* Set up context for possible window functions */
4543  save_windowclause = context->windowClause;
4544  context->windowClause = query->windowClause;
4545  save_windowtlist = context->windowTList;
4546  context->windowTList = query->targetList;
4547 
4548  /*
4549  * If the Query node has a setOperations tree, then it's the top level of
4550  * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
4551  * fields are interesting in the top query itself.
4552  */
4553  if (query->setOperations)
4554  {
4555  get_setop_query(query->setOperations, query, context, resultDesc);
4556  /* ORDER BY clauses must be simple in this case */
4557  force_colno = true;
4558  }
4559  else
4560  {
4561  get_basic_select_query(query, context, resultDesc);
4562  force_colno = false;
4563  }
4564 
4565  /* Add the ORDER BY clause if given */
4566  if (query->sortClause != NIL)
4567  {
4568  appendContextKeyword(context, " ORDER BY ",
4570  get_rule_orderby(query->sortClause, query->targetList,
4571  force_colno, context);
4572  }
4573 
4574  /* Add the LIMIT clause if given */
4575  if (query->limitOffset != NULL)
4576  {
4577  appendContextKeyword(context, " OFFSET ",
4579  get_rule_expr(query->limitOffset, context, false);
4580  }
4581  if (query->limitCount != NULL)
4582  {
4583  appendContextKeyword(context, " LIMIT ",
4585  if (IsA(query->limitCount, Const) &&
4586  ((Const *) query->limitCount)->constisnull)
4587  appendStringInfoString(buf, "ALL");
4588  else
4589  get_rule_expr(query->limitCount, context, false);
4590  }
4591 
4592  /* Add FOR [KEY] UPDATE/SHARE clauses if present */
4593  if (query->hasForUpdate)
4594  {
4595  foreach(l, query->rowMarks)
4596  {
4597  RowMarkClause *rc = (RowMarkClause *) lfirst(l);
4598 
4599  /* don't print implicit clauses */
4600  if (rc->pushedDown)
4601  continue;
4602 
4603  switch (rc->strength)
4604  {
4605  case LCS_NONE:
4606  /* we intentionally throw an error for LCS_NONE */
4607  elog(ERROR, "unrecognized LockClauseStrength %d",
4608  (int) rc->strength);
4609  break;
4610  case LCS_FORKEYSHARE:
4611  appendContextKeyword(context, " FOR KEY SHARE",
4613  break;
4614  case LCS_FORSHARE:
4615  appendContextKeyword(context, " FOR SHARE",
4617  break;
4618  case LCS_FORNOKEYUPDATE:
4619  appendContextKeyword(context, " FOR NO KEY UPDATE",
4621  break;
4622  case LCS_FORUPDATE:
4623  appendContextKeyword(context, " FOR UPDATE",
4625  break;
4626  }
4627 
4628  appendStringInfo(buf, " OF %s",
4630  context)));
4631  if (rc->waitPolicy == LockWaitError)
4632  appendStringInfoString(buf, " NOWAIT");
4633  else if (rc->waitPolicy == LockWaitSkip)
4634  appendStringInfoString(buf, " SKIP LOCKED");
4635  }
4636  }
4637 
4638  context->windowClause = save_windowclause;
4639  context->windowTList = save_windowtlist;
4640 }
4641 
4642 /*
4643  * Detect whether query looks like SELECT ... FROM VALUES();
4644  * if so, return the VALUES RTE. Otherwise return NULL.
4645  */
4646 static RangeTblEntry *
4648 {
4649  RangeTblEntry *result = NULL;
4650  ListCell *lc;
4651 
4652  /*
4653  * We want to return TRUE even if the Query also contains OLD or NEW rule
4654  * RTEs. So the idea is to scan the rtable and see if there is only one
4655  * inFromCl RTE that is a VALUES RTE.
4656  */
4657  foreach(lc, query->rtable)
4658  {
4659  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4660 
4661  if (rte->rtekind == RTE_VALUES && rte->inFromCl)
4662  {
4663  if (result)
4664  return NULL; /* multiple VALUES (probably not possible) */
4665  result = rte;
4666  }
4667  else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
4668  continue; /* ignore rule entries */
4669  else
4670  return NULL; /* something else -> not simple VALUES */
4671  }
4672 
4673  /*
4674  * We don't need to check the targetlist in any great detail, because
4675  * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
4676  * appear inside auto-generated sub-queries with very restricted
4677  * structure. However, DefineView might have modified the tlist by
4678  * injecting new column aliases; so compare tlist resnames against the
4679  * RTE's names to detect that.
4680  */
4681  if (result)
4682  {
4683  ListCell *lcn;
4684 
4685  if (list_length(query->targetList) != list_length(result->eref->colnames))
4686  return NULL; /* this probably cannot happen */
4687  forboth(lc, query->targetList, lcn, result->eref->colnames)
4688  {
4689  TargetEntry *tle = (TargetEntry *) lfirst(lc);
4690  char *cname = strVal(lfirst(lcn));
4691 
4692  if (tle->resjunk)
4693  return NULL; /* this probably cannot happen */
4694  if (tle->resname == NULL || strcmp(tle->resname, cname) != 0)
4695  return NULL; /* column name has been changed */
4696  }
4697  }
4698 
4699  return result;
4700 }
4701 
4702 static void
4704  TupleDesc resultDesc)
4705 {
4706  StringInfo buf = context->buf;
4707  RangeTblEntry *values_rte;
4708  char *sep;
4709  ListCell *l;
4710 
4711  if (PRETTY_INDENT(context))
4712  {
4713  context->indentLevel += PRETTYINDENT_STD;
4714  appendStringInfoChar(buf, ' ');
4715  }
4716 
4717  /*
4718  * If the query looks like SELECT * FROM (VALUES ...), then print just the
4719  * VALUES part. This reverses what transformValuesClause() did at parse
4720  * time.
4721  */
4722  values_rte = get_simple_values_rte(query);
4723  if (values_rte)
4724  {
4725  get_values_def(values_rte->values_lists, context);
4726  return;
4727  }
4728 
4729  /*
4730  * Build up the query string - first we say SELECT
4731  */
4732  appendStringInfoString(buf, "SELECT");
4733 
4734  /* Add the DISTINCT clause if given */
4735  if (query->distinctClause != NIL)
4736  {
4737  if (query->hasDistinctOn)
4738  {
4739  appendStringInfoString(buf, " DISTINCT ON (");
4740  sep = "";
4741  foreach(l, query->distinctClause)
4742  {
4743  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
4744 
4745  appendStringInfoString(buf, sep);
4747  false, context);
4748  sep = ", ";
4749  }
4750  appendStringInfoChar(buf, ')');
4751  }
4752  else
4753  appendStringInfoString(buf, " DISTINCT");
4754  }
4755 
4756  /* Then we tell what to select (the targetlist) */
4757  get_target_list(query->targetList, context, resultDesc);
4758 
4759  /* Add the FROM clause if needed */
4760  get_from_clause(query, " FROM ", context);
4761 
4762  /* Add the WHERE clause if given */
4763  if (query->jointree->quals != NULL)
4764  {
4765  appendContextKeyword(context, " WHERE ",
4767  get_rule_expr(query->jointree->quals, context, false);
4768  }
4769 
4770  /* Add the GROUP BY clause if given */
4771  if (query->groupClause != NULL || query->groupingSets != NULL)
4772  {
4773  ParseExprKind save_exprkind;
4774 
4775  appendContextKeyword(context, " GROUP BY ",
4777 
4778  save_exprkind = context->special_exprkind;
4780 
4781  if (query->groupingSets == NIL)
4782  {
4783  sep = "";
4784  foreach(l, query->groupClause)
4785  {
4786  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
4787 
4788  appendStringInfoString(buf, sep);
4790  false, context);
4791  sep = ", ";
4792  }
4793  }
4794  else
4795  {
4796  sep = "";
4797  foreach(l, query->groupingSets)
4798  {
4799  GroupingSet *grp = lfirst(l);
4800 
4801  appendStringInfoString(buf, sep);
4802  get_rule_groupingset(grp, query->targetList, true, context);
4803  sep = ", ";
4804  }
4805  }
4806 
4807  context->special_exprkind = save_exprkind;
4808  }
4809 
4810  /* Add the HAVING clause if given */
4811  if (query->havingQual != NULL)
4812  {
4813  appendContextKeyword(context, " HAVING ",
4815  get_rule_expr(query->havingQual, context, false);
4816  }
4817 
4818  /* Add the WINDOW clause if needed */
4819  if (query->windowClause != NIL)
4820  get_rule_windowclause(query, context);
4821 }
4822 
4823 /* ----------
4824  * get_target_list - Parse back a SELECT target list
4825  *
4826  * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
4827  * ----------
4828  */
4829 static void
4830 get_target_list(List *targetList, deparse_context *context,
4831  TupleDesc resultDesc)
4832 {
4833  StringInfo buf = context->buf;
4834  StringInfoData targetbuf;
4835  bool last_was_multiline = false;
4836  char *sep;
4837  int colno;
4838  ListCell *l;
4839 
4840  /* we use targetbuf to hold each TLE's text temporarily */
4841  initStringInfo(&targetbuf);
4842 
4843  sep = " ";
4844  colno = 0;
4845  foreach(l, targetList)
4846  {
4847  TargetEntry *tle = (TargetEntry *) lfirst(l);
4848  char *colname;
4849  char *attname;
4850 
4851  if (tle->resjunk)
4852  continue; /* ignore junk entries */
4853 
4854  appendStringInfoString(buf, sep);
4855  sep = ", ";
4856  colno++;
4857 
4858  /*
4859  * Put the new field text into targetbuf so we can decide after we've
4860  * got it whether or not it needs to go on a new line.
4861  */
4862  resetStringInfo(&targetbuf);
4863  context->buf = &targetbuf;
4864 
4865  /*
4866  * We special-case Var nodes rather than using get_rule_expr. This is
4867  * needed because get_rule_expr will display a whole-row Var as
4868  * "foo.*", which is the preferred notation in most contexts, but at
4869  * the top level of a SELECT list it's not right (the parser will
4870  * expand that notation into multiple columns, yielding behavior
4871  * different from a whole-row Var). We need to call get_variable
4872  * directly so that we can tell it to do the right thing, and so that
4873  * we can get the attribute name which is the default AS label.
4874  */
4875  if (tle->expr && (IsA(tle->expr, Var)))
4876  {
4877  attname = get_variable((Var *) tle->expr, 0, true, context);
4878  }
4879  else
4880  {
4881  get_rule_expr((Node *) tle->expr, context, true);
4882  /* We'll show the AS name unless it's this: */
4883  attname = "?column?";
4884  }
4885 
4886  /*
4887  * Figure out what the result column should be called. In the context
4888  * of a view, use the view's tuple descriptor (so as to pick up the
4889  * effects of any column RENAME that's been done on the view).
4890  * Otherwise, just use what we can find in the TLE.
4891  */
4892  if (resultDesc && colno <= resultDesc->natts)
4893  colname = NameStr(resultDesc->attrs[colno - 1]->attname);
4894  else
4895  colname = tle->resname;
4896 
4897  /* Show AS unless the column's name is correct as-is */
4898  if (colname) /* resname could be NULL */
4899  {
4900  if (attname == NULL || strcmp(attname, colname) != 0)
4901  appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
4902  }
4903 
4904  /* Restore context's output buffer */
4905  context->buf = buf;
4906 
4907  /* Consider line-wrapping if enabled */
4908  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
4909  {
4910  int leading_nl_pos;
4911 
4912  /* Does the new field start with a new line? */
4913  if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
4914  leading_nl_pos = 0;
4915  else
4916  leading_nl_pos = -1;
4917 
4918  /* If so, we shouldn't add anything */
4919  if (leading_nl_pos >= 0)
4920  {
4921  /* instead, remove any trailing spaces currently in buf */
4923  }
4924  else
4925  {
4926  char *trailing_nl;
4927 
4928  /* Locate the start of the current line in the output buffer */
4929  trailing_nl = strrchr(buf->data, '\n');
4930  if (trailing_nl == NULL)
4931  trailing_nl = buf->data;
4932  else
4933  trailing_nl++;
4934 
4935  /*
4936  * Add a newline, plus some indentation, if the new field is
4937  * not the first and either the new field would cause an
4938  * overflow or the last field used more than one line.
4939  */
4940  if (colno > 1 &&
4941  ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
4942  last_was_multiline))
4943  appendContextKeyword(context, "", -PRETTYINDENT_STD,
4945  }
4946 
4947  /* Remember this field's multiline status for next iteration */
4948  last_was_multiline =
4949  (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
4950  }
4951 
4952  /* Add the new field */
4953  appendStringInfoString(buf, targetbuf.data);
4954  }
4955 
4956  /* clean up */
4957  pfree(targetbuf.data);
4958 }
4959 
4960 static void
4961 get_setop_query(Node *setOp, Query *query, deparse_context *context,
4962  TupleDesc resultDesc)
4963 {
4964  StringInfo buf = context->buf;
4965  bool need_paren;
4966 
4967  /* Guard against excessively long or deeply-nested queries */
4970 
4971  if (IsA(setOp, RangeTblRef))
4972  {
4973  RangeTblRef *rtr = (RangeTblRef *) setOp;
4974  RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
4975  Query *subquery = rte->subquery;
4976 
4977  Assert(subquery != NULL);
4978  Assert(subquery->setOperations == NULL);
4979  /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
4980  need_paren = (subquery->cteList ||
4981  subquery->sortClause ||
4982  subquery->rowMarks ||
4983  subquery->limitOffset ||
4984  subquery->limitCount);
4985  if (need_paren)
4986  appendStringInfoChar(buf, '(');
4987  get_query_def(subquery, buf, context->namespaces, resultDesc,
4988  context->prettyFlags, context->wrapColumn,
4989  context->indentLevel);
4990  if (need_paren)
4991  appendStringInfoChar(buf, ')');
4992  }
4993  else if (IsA(setOp, SetOperationStmt))
4994  {
4995  SetOperationStmt *op = (SetOperationStmt *) setOp;
4996  int subindent;
4997 
4998  /*
4999  * We force parens when nesting two SetOperationStmts, except when the
5000  * lefthand input is another setop of the same kind. Syntactically,
5001  * we could omit parens in rather more cases, but it seems best to use
5002  * parens to flag cases where the setop operator changes. If we use
5003  * parens, we also increase the indentation level for the child query.
5004  *
5005  * There are some cases in which parens are needed around a leaf query
5006  * too, but those are more easily handled at the next level down (see
5007  * code above).
5008  */
5009  if (IsA(op->larg, SetOperationStmt))
5010  {
5011  SetOperationStmt *lop = (SetOperationStmt *) op->larg;
5012 
5013  if (op->op == lop->op && op->all == lop->all)
5014  need_paren = false;
5015  else
5016  need_paren = true;
5017  }
5018  else
5019  need_paren = false;
5020 
5021  if (need_paren)
5022  {
5023  appendStringInfoChar(buf, '(');
5024  subindent = PRETTYINDENT_STD;
5025  appendContextKeyword(context, "", subindent, 0, 0);
5026  }
5027  else
5028  subindent = 0;
5029 
5030  get_setop_query(op->larg, query, context, resultDesc);
5031 
5032  if (need_paren)
5033  appendContextKeyword(context, ") ", -subindent, 0, 0);
5034  else if (PRETTY_INDENT(context))
5035  appendContextKeyword(context, "", -subindent, 0, 0);
5036  else
5037  appendStringInfoChar(buf, ' ');
5038 
5039  switch (op->op)
5040  {
5041  case SETOP_UNION:
5042  appendStringInfoString(buf, "UNION ");
5043  break;
5044  case SETOP_INTERSECT:
5045  appendStringInfoString(buf, "INTERSECT ");
5046  break;
5047  case SETOP_EXCEPT:
5048  appendStringInfoString(buf, "EXCEPT ");
5049  break;
5050  default:
5051  elog(ERROR, "unrecognized set op: %d",
5052  (int) op->op);
5053  }
5054  if (op->all)
5055  appendStringInfoString(buf, "ALL ");
5056 
5057  /* Always parenthesize if RHS is another setop */
5058  need_paren = IsA(op->rarg, SetOperationStmt);
5059 
5060  /*
5061  * The indentation code here is deliberately a bit different from that
5062  * for the lefthand input, because we want the line breaks in
5063  * different places.
5064  */
5065  if (need_paren)
5066  {
5067  appendStringInfoChar(buf, '(');
5068  subindent = PRETTYINDENT_STD;
5069  }
5070  else
5071  subindent = 0;
5072  appendContextKeyword(context, "", subindent, 0, 0);
5073 
5074  get_setop_query(op->rarg, query, context, resultDesc);
5075 
5076  if (PRETTY_INDENT(context))
5077  context->indentLevel -= subindent;
5078  if (need_paren)
5079  appendContextKeyword(context, ")", 0, 0, 0);
5080  }
5081  else
5082  {
5083  elog(ERROR, "unrecognized node type: %d",
5084  (int) nodeTag(setOp));
5085  }
5086 }
5087 
5088 /*
5089  * Display a sort/group clause.
5090  *
5091  * Also returns the expression tree, so caller need not find it again.
5092  */
5093 static Node *
5094 get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
5095  deparse_context *context)
5096 {
5097  StringInfo buf = context->buf;
5098  TargetEntry *tle;
5099  Node *expr;
5100 
5101  tle = get_sortgroupref_tle(ref, tlist);
5102  expr = (Node *) tle->expr;
5103 
5104  /*
5105  * Use column-number form if requested by caller. Otherwise, if
5106  * expression is a constant, force it to be dumped with an explicit cast
5107  * as decoration --- this is because a simple integer constant is
5108  * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
5109  * dump it without any decoration. If it's anything more complex than a
5110  * simple Var, then force extra parens around it, to ensure it can't be
5111  * misinterpreted as a cube() or rollup() construct.
5112  */
5113  if (force_colno)
5114  {
5115  Assert(!tle->resjunk);
5116  appendStringInfo(buf, "%d", tle->resno);
5117  }
5118  else if (expr && IsA(expr, Const))
5119  get_const_expr((Const *) expr, context, 1);
5120  else if (!expr || IsA(expr, Var))
5121  get_rule_expr(expr, context, true);
5122  else
5123  {
5124  /*
5125  * We must force parens for function-like expressions even if
5126  * PRETTY_PAREN is off, since those are the ones in danger of
5127  * misparsing. For other expressions we need to force them only if
5128  * PRETTY_PAREN is on, since otherwise the expression will output them
5129  * itself. (We can't skip the parens.)
5130  */
5131  bool need_paren = (PRETTY_PAREN(context)
5132  || IsA(expr, FuncExpr)
5133  ||IsA(expr, Aggref)
5134  ||IsA(expr, WindowFunc));
5135 
5136  if (need_paren)
5137  appendStringInfoString(context->buf, "(");
5138  get_rule_expr(expr, context, true);
5139  if (need_paren)
5140  appendStringInfoString(context->buf, ")");
5141  }
5142 
5143  return expr;
5144 }
5145 
5146 /*
5147  * Display a GroupingSet
5148  */
5149 static void
5151  bool omit_parens, deparse_context *context)
5152 {
5153  ListCell *l;
5154  StringInfo buf = context->buf;
5155  bool omit_child_parens = true;
5156  char *sep = "";
5157 
5158  switch (gset->kind)
5159  {
5160  case GROUPING_SET_EMPTY:
5161  appendStringInfoString(buf, "()");
5162  return;
5163 
5164  case GROUPING_SET_SIMPLE:
5165  {
5166  if (!omit_parens || list_length(gset->content) != 1)
5167  appendStringInfoString(buf, "(");
5168 
5169  foreach(l, gset->content)
5170  {
5171  Index ref = lfirst_int(l);
5172 
5173  appendStringInfoString(buf, sep);
5174  get_rule_sortgroupclause(ref, targetlist,
5175  false, context);
5176  sep = ", ";
5177  }
5178 
5179  if (!omit_parens || list_length(gset->content) != 1)
5180  appendStringInfoString(buf, ")");
5181  }
5182  return;
5183 
5184  case GROUPING_SET_ROLLUP:
5185  appendStringInfoString(buf, "ROLLUP(");
5186  break;
5187  case GROUPING_SET_CUBE:
5188  appendStringInfoString(buf, "CUBE(");
5189  break;
5190  case GROUPING_SET_SETS:
5191  appendStringInfoString(buf, "GROUPING SETS (");
5192  omit_child_parens = false;
5193  break;
5194  }
5195 
5196  foreach(l, gset->content)
5197  {
5198  appendStringInfoString(buf, sep);
5199  get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context);
5200  sep = ", ";
5201  }
5202 
5203  appendStringInfoString(buf, ")");
5204 }
5205 
5206 /*
5207  * Display an ORDER BY list.
5208  */
5209 static void
5210 get_rule_orderby(List *orderList, List *targetList,
5211  bool force_colno, deparse_context *context)
5212 {
5213  StringInfo buf = context->buf;
5214  const char *sep;
5215  ListCell *l;
5216 
5217  sep = "";
5218  foreach(l, orderList)
5219  {
5220  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5221  Node *sortexpr;
5222  Oid sortcoltype;
5223  TypeCacheEntry *typentry;
5224 
5225  appendStringInfoString(buf, sep);
5226  sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList,
5227  force_colno, context);
5228  sortcoltype = exprType(sortexpr);
5229  /* See whether operator is default < or > for datatype */
5230  typentry = lookup_type_cache(sortcoltype,
5232  if (srt->sortop == typentry->lt_opr)
5233  {
5234  /* ASC is default, so emit nothing for it */
5235  if (srt->nulls_first)
5236  appendStringInfoString(buf, " NULLS FIRST");
5237  }
5238  else if (srt->sortop == typentry->gt_opr)
5239  {
5240  appendStringInfoString(buf, " DESC");
5241  /* DESC defaults to NULLS FIRST */
5242  if (!srt->nulls_first)
5243  appendStringInfoString(buf, " NULLS LAST");
5244  }
5245  else
5246  {
5247  appendStringInfo(buf, " USING %s",
5249  sortcoltype,
5250  sortcoltype));
5251  /* be specific to eliminate ambiguity */
5252  if (srt->nulls_first)
5253  appendStringInfoString(buf, " NULLS FIRST");
5254  else
5255  appendStringInfoString(buf, " NULLS LAST");
5256  }
5257  sep = ", ";
5258  }
5259 }
5260 
5261 /*
5262  * Display a WINDOW clause.
5263  *
5264  * Note that the windowClause list might contain only anonymous window
5265  * specifications, in which case we should print nothing here.
5266  */
5267 static void
5269 {
5270  StringInfo buf = context->buf;
5271  const char *sep;
5272  ListCell *l;
5273 
5274  sep = NULL;
5275  foreach(l, query->windowClause)
5276  {
5277  WindowClause *wc = (WindowClause *) lfirst(l);
5278 
5279  if (wc->name == NULL)
5280  continue; /* ignore anonymous windows */
5281 
5282  if (sep == NULL)
5283  appendContextKeyword(context, " WINDOW ",
5285  else
5286  appendStringInfoString(buf, sep);
5287 
5288  appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
5289 
5290  get_rule_windowspec(wc, query->targetList, context);
5291 
5292  sep = ", ";
5293  }
5294 }
5295 
5296 /*
5297  * Display a window definition
5298  */
5299 static void
5301  deparse_context *context)
5302 {
5303  StringInfo buf = context->buf;
5304  bool needspace = false;
5305  const char *sep;
5306  ListCell *l;
5307 
5308  appendStringInfoChar(buf, '(');
5309  if (wc->refname)
5310  {
5312  needspace = true;
5313  }
5314  /* partition clauses are always inherited, so only print if no refname */
5315  if (wc->partitionClause && !wc->refname)
5316  {
5317  if (needspace)
5318  appendStringInfoChar(buf, ' ');
5319  appendStringInfoString(buf, "PARTITION BY ");
5320  sep = "";
5321  foreach(l, wc->partitionClause)
5322  {
5323  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5324 
5325  appendStringInfoString(buf, sep);
5326  get_rule_sortgroupclause(grp->tleSortGroupRef, targetList,
5327  false, context);
5328  sep = ", ";
5329  }
5330  needspace = true;
5331  }
5332  /* print ordering clause only if not inherited */
5333  if (wc->orderClause && !wc->copiedOrder)
5334  {
5335  if (needspace)
5336  appendStringInfoChar(buf, ' ');
5337  appendStringInfoString(buf, "ORDER BY ");
5338  get_rule_orderby(wc->orderClause, targetList, false, context);
5339  needspace = true;
5340  }
5341  /* framing clause is never inherited, so print unless it's default */
5343  {
5344  if (needspace)
5345  appendStringInfoChar(buf, ' ');
5346  if (wc->frameOptions & FRAMEOPTION_RANGE)
5347  appendStringInfoString(buf, "RANGE ");
5348  else if (wc->frameOptions & FRAMEOPTION_ROWS)
5349  appendStringInfoString(buf, "ROWS ");
5350  else
5351  Assert(false);
5353  appendStringInfoString(buf, "BETWEEN ");
5355  appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
5357  appendStringInfoString(buf, "CURRENT ROW ");
5358  else if (wc->frameOptions & FRAMEOPTION_START_VALUE)
5359  {
5360  get_rule_expr(wc->startOffset, context, false);
5362  appendStringInfoString(buf, " PRECEDING ");
5364  appendStringInfoString(buf, " FOLLOWING ");
5365  else
5366  Assert(false);
5367  }
5368  else
5369  Assert(false);
5371  {
5372  appendStringInfoString(buf, "AND ");
5374  appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
5376  appendStringInfoString(buf, "CURRENT ROW ");
5377  else if (wc->frameOptions & FRAMEOPTION_END_VALUE)
5378  {
5379  get_rule_expr(wc->endOffset, context, false);
5381  appendStringInfoString(buf, " PRECEDING ");
5383  appendStringInfoString(buf, " FOLLOWING ");
5384  else
5385  Assert(false);
5386  }
5387  else
5388  Assert(false);
5389  }
5390  /* we will now have a trailing space; remove it */
5391  buf->len--;
5392  }
5393  appendStringInfoChar(buf, ')');
5394 }
5395 
5396 /* ----------
5397  * get_insert_query_def - Parse back an INSERT parsetree
5398  * ----------
5399  */
5400 static void
5402 {
5403  StringInfo buf = context->buf;
5404  RangeTblEntry *select_rte = NULL;
5405  RangeTblEntry *values_rte = NULL;
5406  RangeTblEntry *rte;
5407  char *sep;
5408  ListCell *values_cell;
5409  ListCell *l;
5410  List *strippedexprs;
5411 
5412  /* Insert the WITH clause if given */
5413  get_with_clause(query, context);
5414 
5415  /*
5416  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5417  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5418  */
5419  foreach(l, query->rtable)
5420  {
5421  rte = (RangeTblEntry *) lfirst(l);
5422 
5423  if (rte->rtekind == RTE_SUBQUERY)
5424  {
5425  if (select_rte)
5426  elog(ERROR, "too many subquery RTEs in INSERT");
5427  select_rte = rte;
5428  }
5429 
5430  if (rte->rtekind == RTE_VALUES)
5431  {
5432  if (values_rte)
5433  elog(ERROR, "too many values RTEs in INSERT");
5434  values_rte = rte;
5435  }
5436  }
5437  if (select_rte && values_rte)
5438  elog(ERROR, "both subquery and values RTEs in INSERT");
5439 
5440  /*
5441  * Start the query with INSERT INTO relname
5442  */
5443  rte = rt_fetch(query->resultRelation, query->rtable);
5444  Assert(rte->rtekind == RTE_RELATION);
5445 
5446  if (PRETTY_INDENT(context))
5447  {
5448  context->indentLevel += PRETTYINDENT_STD;
5449  appendStringInfoChar(buf, ' ');
5450  }
5451  appendStringInfo(buf, "INSERT INTO %s ",
5453  /* INSERT requires AS keyword for target alias */
5454  if (rte->alias != NULL)
5455  appendStringInfo(buf, "AS %s ",
5457 
5458  /*
5459  * Add the insert-column-names list. To handle indirection properly, we
5460  * need to look for indirection nodes in the top targetlist (if it's
5461  * INSERT ... SELECT or INSERT ... single VALUES), or in the first
5462  * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
5463  * assume that all the expression lists will have similar indirection in
5464  * the latter case.
5465  */
5466  if (values_rte)
5467  values_cell = list_head((List *) linitial(values_rte->values_lists));
5468  else
5469  values_cell = NULL;
5470  strippedexprs = NIL;
5471  sep = "";
5472  if (query->targetList)
5473  appendStringInfoChar(buf, '(');
5474  foreach(l, query->targetList)
5475  {
5476  TargetEntry *tle = (TargetEntry *) lfirst(l);
5477 
5478  if (tle->resjunk)
5479  continue; /* ignore junk entries */
5480 
5481  appendStringInfoString(buf, sep);
5482  sep = ", ";
5483 
5484  /*
5485  * Put out name of target column; look in the catalogs, not at
5486  * tle->resname, since resname will fail to track RENAME.
5487  */
5490  tle->resno)));
5491 
5492  /*
5493  * Print any indirection needed (subfields or subscripts), and strip
5494  * off the top-level nodes representing the indirection assignments.
5495  */
5496  if (values_cell)
5497  {
5498  /* we discard the stripped expression in this case */
5499  processIndirection((Node *) lfirst(values_cell), context, true);
5500  values_cell = lnext(values_cell);
5501  }
5502  else
5503  {
5504  /* we keep a list of the stripped expressions in this case */
5505  strippedexprs = lappend(strippedexprs,
5506  processIndirection((Node *) tle->expr,
5507  context, true));
5508  }
5509  }
5510  if (query->targetList)
5511  appendStringInfoString(buf, ") ");
5512 
5513  if (select_rte)
5514  {
5515  /* Add the SELECT */
5516  get_query_def(select_rte->subquery, buf, NIL, NULL,
5517  context->prettyFlags, context->wrapColumn,
5518  context->indentLevel);
5519  }
5520  else if (values_rte)
5521  {
5522  /* Add the multi-VALUES expression lists */
5523  get_values_def(values_rte->values_lists, context);
5524  }
5525  else if (strippedexprs)
5526  {
5527  /* Add the single-VALUES expression list */
5528  appendContextKeyword(context, "VALUES (",
5530  get_rule_expr((Node *) strippedexprs, context, false);
5531  appendStringInfoChar(buf, ')');
5532  }
5533  else
5534  {
5535  /* No expressions, so it must be DEFAULT VALUES */
5536  appendStringInfoString(buf, "DEFAULT VALUES");
5537  }
5538 
5539  /* Add ON CONFLICT if present */
5540  if (query->onConflict)
5541  {
5542  OnConflictExpr *confl = query->onConflict;
5543 
5544  appendStringInfoString(buf, " ON CONFLICT");
5545 
5546  if (confl->arbiterElems)
5547  {
5548  /* Add the single-VALUES expression list */
5549  appendStringInfoChar(buf, '(');
5550  get_rule_expr((Node *) confl->arbiterElems, context, false);
5551  appendStringInfoChar(buf, ')');
5552 
5553  /* Add a WHERE clause (for partial indexes) if given */
5554  if (confl->arbiterWhere != NULL)
5555  {
5556  bool save_varprefix;
5557 
5558  /*
5559  * Force non-prefixing of Vars, since parser assumes that they
5560  * belong to target relation. WHERE clause does not use
5561  * InferenceElem, so this is separately required.
5562  */
5563  save_varprefix = context->varprefix;
5564  context->varprefix = false;
5565 
5566  appendContextKeyword(context, " WHERE ",
5568  get_rule_expr(confl->arbiterWhere, context, false);
5569 
5570  context->varprefix = save_varprefix;
5571  }
5572  }
5573  else if (confl->constraint != InvalidOid)
5574  {
5575  char *constraint = get_constraint_name(confl->constraint);
5576 
5577  appendStringInfo(buf, " ON CONSTRAINT %s",
5578  quote_qualified_identifier(NULL, constraint));
5579  }
5580 
5581  if (confl->action == ONCONFLICT_NOTHING)
5582  {
5583  appendStringInfoString(buf, " DO NOTHING");
5584  }
5585  else
5586  {
5587  appendStringInfoString(buf, " DO UPDATE SET ");
5588  /* Deparse targetlist */
5590  context, rte);
5591 
5592  /* Add a WHERE clause if given */
5593  if (confl->onConflictWhere != NULL)
5594  {
5595  appendContextKeyword(context, " WHERE ",
5597  get_rule_expr(confl->onConflictWhere, context, false);
5598  }
5599  }
5600  }
5601 
5602  /* Add RETURNING if present */
5603  if (query->returningList)
5604  {
5605  appendContextKeyword(context, " RETURNING",
5607  get_target_list(query->returningList, context, NULL);
5608  }
5609 }
5610 
5611 
5612 /* ----------
5613  * get_update_query_def - Parse back an UPDATE parsetree
5614  * ----------
5615  */
5616 static void
5618 {
5619  StringInfo buf = context->buf;
5620  RangeTblEntry *rte;
5621 
5622  /* Insert the WITH clause if given */
5623  get_with_clause(query, context);
5624 
5625  /*
5626  * Start the query with UPDATE relname SET
5627  */
5628  rte = rt_fetch(query->resultRelation, query->rtable);
5629  Assert(rte->rtekind == RTE_RELATION);
5630  if (PRETTY_INDENT(context))
5631  {
5632  appendStringInfoChar(buf, ' ');
5633  context->indentLevel += PRETTYINDENT_STD;
5634  }
5635  appendStringInfo(buf, "UPDATE %s%s",
5636  only_marker(rte),
5638  if (rte->alias != NULL)
5639  appendStringInfo(buf, " %s",
5641  appendStringInfoString(buf, " SET ");
5642 
5643  /* Deparse targetlist */
5644  get_update_query_targetlist_def(query, query->targetList, context, rte);
5645 
5646  /* Add the FROM clause if needed */
5647  get_from_clause(query, " FROM ", context);
5648 
5649  /* Add a WHERE clause if given */
5650  if (query->jointree->quals != NULL)
5651  {
5652  appendContextKeyword(context, " WHERE ",
5654  get_rule_expr(query->jointree->quals, context, false);
5655  }
5656 
5657  /* Add RETURNING if present */
5658  if (query->returningList)
5659  {
5660  appendContextKeyword(context, " RETURNING",
5662  get_target_list(query->returningList, context, NULL);
5663  }
5664 }
5665 
5666 
5667 /* ----------
5668  * get_update_query_targetlist_def - Parse back an UPDATE targetlist
5669  * ----------
5670  */
5671 static void
5673  deparse_context *context, RangeTblEntry *rte)
5674 {
5675  StringInfo buf = context->buf;
5676  ListCell *l;
5677  ListCell *next_ma_cell;
5678  int remaining_ma_columns;
5679  const char *sep;
5680  SubLink *cur_ma_sublink;
5681  List *ma_sublinks;
5682 
5683  /*
5684  * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks
5685  * into a list. We expect them to appear, in ID order, in resjunk tlist
5686  * entries.
5687  */
5688  ma_sublinks = NIL;
5689  if (query->hasSubLinks) /* else there can't be any */
5690  {
5691  foreach(l, targetList)
5692  {
5693  TargetEntry *tle = (TargetEntry *) lfirst(l);
5694 
5695  if (tle->resjunk && IsA(tle->expr, SubLink))
5696  {
5697  SubLink *sl = (SubLink *) tle->expr;
5698 
5699  if (sl->subLinkType == MULTIEXPR_SUBLINK)
5700  {
5701  ma_sublinks = lappend(ma_sublinks, sl);
5702  Assert(sl->subLinkId == list_length(ma_sublinks));
5703  }
5704  }
5705  }
5706  }
5707  next_ma_cell = list_head(ma_sublinks);
5708  cur_ma_sublink = NULL;
5709  remaining_ma_columns = 0;
5710 
5711  /* Add the comma separated list of 'attname = value' */
5712  sep = "";
5713  foreach(l, targetList)
5714  {
5715  TargetEntry *tle = (TargetEntry *) lfirst(l);
5716  Node *expr;
5717 
5718  if (tle->resjunk)
5719  continue; /* ignore junk entries */
5720 
5721  /* Emit separator (OK whether we're in multiassignment or not) */
5722  appendStringInfoString(buf, sep);
5723  sep = ", ";
5724 
5725  /*
5726  * Check to see if we're starting a multiassignment group: if so,
5727  * output a left paren.
5728  */
5729  if (next_ma_cell != NULL && cur_ma_sublink == NULL)
5730  {
5731  /*
5732  * We must dig down into the expr to see if it's a PARAM_MULTIEXPR
5733  * Param. That could be buried under FieldStores and ArrayRefs
5734  * (cf processIndirection()), and underneath those there could be
5735  * an implicit type coercion.
5736  */
5737  expr = (Node *) tle->expr;
5738  while (expr)
5739  {
5740  if (IsA(expr, FieldStore))
5741  {
5742  FieldStore *fstore = (FieldStore *) expr;
5743 
5744  expr = (Node *) linitial(fstore->newvals);
5745  }
5746  else if (IsA(expr, ArrayRef))
5747  {
5748  ArrayRef *aref = (ArrayRef *) expr;
5749 
5750  if (aref->refassgnexpr == NULL)
5751  break;
5752  expr = (Node *) aref->refassgnexpr;
5753  }
5754  else
5755  break;
5756  }
5757  expr = strip_implicit_coercions(expr);
5758 
5759  if (expr && IsA(expr, Param) &&
5760  ((Param *) expr)->paramkind == PARAM_MULTIEXPR)
5761  {
5762  cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
5763  next_ma_cell = lnext(next_ma_cell);
5764  remaining_ma_columns = count_nonjunk_tlist_entries(
5765  ((Query *) cur_ma_sublink->subselect)->targetList);
5766  Assert(((Param *) expr)->paramid ==
5767  ((cur_ma_sublink->subLinkId << 16) | 1));
5768  appendStringInfoChar(buf, '(');
5769  }
5770  }
5771 
5772  /*
5773  * Put out name of target column; look in the catalogs, not at
5774  * tle->resname, since resname will fail to track RENAME.
5775  */
5778  tle->resno)));
5779 
5780  /*
5781  * Print any indirection needed (subfields or subscripts), and strip
5782  * off the top-level nodes representing the indirection assignments.
5783  */
5784  expr = processIndirection((Node *) tle->expr, context, true);
5785 
5786  /*
5787  * If we're in a multiassignment, skip printing anything more, unless
5788  * this is the last column; in which case, what we print should be the
5789  * sublink, not the Param.
5790  */
5791  if (cur_ma_sublink != NULL)
5792  {
5793  if (--remaining_ma_columns > 0)
5794  continue; /* not the last column of multiassignment */
5795  appendStringInfoChar(buf, ')');
5796  expr = (Node *) cur_ma_sublink;
5797  cur_ma_sublink = NULL;
5798  }
5799 
5800  appendStringInfoString(buf, " = ");
5801 
5802  get_rule_expr(expr, context, false);
5803  }
5804 }
5805 
5806 
5807 /* ----------
5808  * get_delete_query_def - Parse back a DELETE parsetree
5809  * ----------
5810  */
5811 static void
5813 {
5814  StringInfo buf = context->buf;
5815  RangeTblEntry *rte;
5816 
5817  /* Insert the WITH clause if given */
5818  get_with_clause(query, context);
5819 
5820  /*
5821  * Start the query with DELETE FROM relname
5822  */
5823  rte = rt_fetch(query->resultRelation, query->rtable);
5824  Assert(rte->rtekind == RTE_RELATION);
5825  if (PRETTY_INDENT(context))
5826  {
5827  appendStringInfoChar(buf, ' ');
5828  context->indentLevel += PRETTYINDENT_STD;
5829  }
5830  appendStringInfo(buf, "DELETE FROM %s%s",
5831  only_marker(rte),
5833  if (rte->alias != NULL)
5834  appendStringInfo(buf, " %s",
5836 
5837  /* Add the USING clause if given */
5838  get_from_clause(query, " USING ", context);
5839 
5840  /* Add a WHERE clause if given */
5841  if (query->jointree->quals != NULL)
5842  {
5843  appendContextKeyword(context, " WHERE ",
5845  get_rule_expr(query->jointree->quals, context, false);
5846  }
5847 
5848  /* Add RETURNING if present */
5849  if (query->returningList)
5850  {
5851  appendContextKeyword(context, " RETURNING",
5853  get_target_list(query->returningList, context, NULL);
5854  }
5855 }
5856 
5857 
5858 /* ----------
5859  * get_utility_query_def - Parse back a UTILITY parsetree
5860  * ----------
5861  */
5862 static void
5864 {
5865  StringInfo buf = context->buf;
5866 
5867  if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
5868  {
5869  NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
5870 
5871  appendContextKeyword(context, "",
5872  0, PRETTYINDENT_STD, 1);
5873  appendStringInfo(buf, "NOTIFY %s",
5875  if (stmt->payload)
5876  {
5877  appendStringInfoString(buf, ", ");
5878  simple_quote_literal(buf, stmt->payload);
5879  }
5880  }
5881  else
5882  {
5883  /* Currently only NOTIFY utility commands can appear in rules */
5884  elog(ERROR, "unexpected utility statement type");
5885  }
5886 }
5887 
5888 /*
5889  * Display a Var appropriately.
5890  *
5891  * In some cases (currently only when recursing into an unnamed join)
5892  * the Var's varlevelsup has to be interpreted with respect to a context
5893  * above the current one; levelsup indicates the offset.
5894  *
5895  * If istoplevel is TRUE, the Var is at the top level of a SELECT's
5896  * targetlist, which means we need special treatment of whole-row Vars.
5897  * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a
5898  * dirty hack to prevent "tab.*" from being expanded into multiple columns.
5899  * (The parser will strip the useless coercion, so no inefficiency is added in
5900  * dump and reload.) We used to print just "tab" in such cases, but that is
5901  * ambiguous and will yield the wrong result if "tab" is also a plain column
5902  * name in the query.
5903  *
5904  * Returns the attname of the Var, or NULL if the Var has no attname (because
5905  * it is a whole-row Var or a subplan output reference).
5906  */
5907 static char *
5908 get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
5909 {
5910  StringInfo buf = context->buf;
5911  RangeTblEntry *rte;
5912  AttrNumber attnum;
5913  int netlevelsup;
5914  deparse_namespace *dpns;
5915  deparse_columns *colinfo;
5916  char *refname;
5917  char *attname;
5918 
5919  /* Find appropriate nesting depth */
5920  netlevelsup = var->varlevelsup + levelsup;
5921  if (netlevelsup >= list_length(context->namespaces))
5922  elog(ERROR, "bogus varlevelsup: %d offset %d",
5923  var->varlevelsup, levelsup);
5924  dpns = (deparse_namespace *) list_nth(context->namespaces,
5925  netlevelsup);
5926 
5927  /*
5928  * Try to find the relevant RTE in this rtable. In a plan tree, it's
5929  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
5930  * down into the subplans, or INDEX_VAR, which is resolved similarly. Also
5931  * find the aliases previously assigned for this RTE.
5932  */
5933  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
5934  {
5935  rte = rt_fetch(var->varno, dpns->rtable);
5936  refname = (char *) list_nth(dpns->rtable_names, var->varno - 1);
5937  colinfo = deparse_columns_fetch(var->varno, dpns);
5938  attnum = var->varattno;
5939  }
5940  else
5941  {
5942  resolve_special_varno((Node *) var, context, NULL,
5944  return NULL;
5945  }
5946 
5947  /*
5948  * The planner will sometimes emit Vars referencing resjunk elements of a
5949  * subquery's target list (this is currently only possible if it chooses
5950  * to generate a "physical tlist" for a SubqueryScan or CteScan node).
5951  * Although we prefer to print subquery-referencing Vars using the
5952  * subquery's alias, that's not possible for resjunk items since they have
5953  * no alias. So in that case, drill down to the subplan and print the
5954  * contents of the referenced tlist item. This works because in a plan
5955  * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
5956  * we'll have set dpns->inner_planstate to reference the child plan node.
5957  */
5958  if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
5959  attnum > list_length(rte->eref->colnames) &&
5960  dpns->inner_planstate)
5961  {
5962  TargetEntry *tle;
5963  deparse_namespace save_dpns;
5964 
5965  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
5966  if (!tle)
5967  elog(ERROR, "bogus varattno for subquery var: %d", var->varattno);
5968 
5969  Assert(netlevelsup == 0);
5970  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
5971 
5972  /*
5973  * Force parentheses because our caller probably assumed a Var is a
5974  * simple expression.
5975  */
5976  if (!IsA(tle->expr, Var))
5977  appendStringInfoChar(buf, '(');
5978  get_rule_expr((Node *) tle->expr, context, true);
5979  if (!IsA(tle->expr, Var))
5980  appendStringInfoChar(buf, ')');
5981 
5982  pop_child_plan(dpns, &save_dpns);
5983  return NULL;
5984  }
5985 
5986  /*
5987  * If it's an unnamed join, look at the expansion of the alias variable.
5988  * If it's a simple reference to one of the input vars, then recursively
5989  * print the name of that var instead. When it's not a simple reference,
5990  * we have to just print the unqualified join column name. (This can only
5991  * happen with "dangerous" merged columns in a JOIN USING; we took pains
5992  * previously to make the unqualified column name unique in such cases.)
5993  *
5994  * This wouldn't work in decompiling plan trees, because we don't store
5995  * joinaliasvars lists after planning; but a plan tree should never
5996  * contain a join alias variable.
5997  */
5998  if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
5999  {
6000  if (rte->joinaliasvars == NIL)
6001  elog(ERROR, "cannot decompile join alias var in plan tree");
6002  if (attnum > 0)
6003  {
6004  Var *aliasvar;
6005 
6006  aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
6007  /* we intentionally don't strip implicit coercions here */
6008  if (aliasvar && IsA(aliasvar, Var))
6009  {
6010  return get_variable(aliasvar, var->varlevelsup + levelsup,
6011  istoplevel, context);
6012  }
6013  }
6014 
6015  /*
6016  * Unnamed join has no refname. (Note: since it's unnamed, there is
6017  * no way the user could have referenced it to create a whole-row Var
6018  * for it. So we don't have to cover that case below.)
6019  */
6020  Assert(refname == NULL);
6021  }
6022 
6023  if (attnum == InvalidAttrNumber)
6024  attname = NULL;
6025  else if (attnum > 0)
6026  {
6027  /* Get column name to use from the colinfo struct */
6028  Assert(attnum <= colinfo->num_cols);
6029  attname = colinfo->colnames[attnum - 1];
6030  Assert(attname != NULL);
6031  }
6032  else
6033  {
6034  /* System column - name is fixed, get it from the catalog */
6035  attname = get_rte_attribute_name(rte, attnum);
6036  }
6037 
6038  if (refname && (context->varprefix || attname == NULL))
6039  {
6041  appendStringInfoChar(buf, '.');
6042  }
6043  if (attname)
6045  else
6046  {
6047  appendStringInfoChar(buf, '*');
6048  if (istoplevel)
6049  appendStringInfo(buf, "::%s",
6051  var->vartypmod));
6052  }
6053 
6054  return attname;
6055 }
6056 
6057 /*
6058  * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR. This
6059  * routine is actually a callback for get_special_varno, which handles finding
6060  * the correct TargetEntry. We get the expression contained in that
6061  * TargetEntry and just need to deparse it, a job we can throw back on
6062  * get_rule_expr.
6063  */
6064 static void
6065 get_special_variable(Node *node, deparse_context *context, void *private)
6066 {
6067  StringInfo buf = context->buf;
6068 
6069  /*
6070  * Force parentheses because our caller probably assumed a Var is a simple
6071  * expression.
6072  */
6073  if (!IsA(node, Var))
6074  appendStringInfoChar(buf, '(');
6075  get_rule_expr(node, context, true);
6076  if (!IsA(node, Var))
6077  appendStringInfoChar(buf, ')');
6078 }
6079 
6080 /*
6081  * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR,
6082  * INDEX_VAR) until we find a real Var or some kind of non-Var node; then,
6083  * invoke the callback provided.
6084  */
6085 static void
6086 resolve_special_varno(Node *node, deparse_context *context, void *private,
6087  void (*callback) (Node *, deparse_context *, void *))
6088 {
6089  Var *var;
6090  deparse_namespace *dpns;
6091 
6092  /* If it's not a Var, invoke the callback. */
6093  if (!IsA(node, Var))
6094  {
6095  callback(node, context, private);
6096  return;
6097  }
6098 
6099  /* Find appropriate nesting depth */
6100  var = (Var *) node;
6101  dpns = (deparse_namespace *) list_nth(context->namespaces,
6102  var->varlevelsup);
6103 
6104  /*
6105  * It's a special RTE, so recurse.
6106  */
6107  if (var->varno == OUTER_VAR && dpns->outer_tlist)
6108  {
6109  TargetEntry *tle;
6110  deparse_namespace save_dpns;
6111 
6112  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6113  if (!tle)
6114  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6115 
6116  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6117  resolve_special_varno((Node *) tle->expr, context, private, callback);
6118  pop_child_plan(dpns, &save_dpns);
6119  return;
6120  }
6121  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6122  {
6123  TargetEntry *tle;
6124  deparse_namespace save_dpns;
6125 
6126  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6127  if (!tle)
6128  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6129 
6130  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6131  resolve_special_varno((Node *) tle->expr, context, private, callback);
6132  pop_child_plan(dpns, &save_dpns);
6133  return;
6134  }
6135  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6136  {
6137  TargetEntry *tle;
6138 
6139  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6140  if (!tle)
6141  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6142 
6143  resolve_special_varno((Node *) tle->expr, context, private, callback);
6144  return;
6145  }
6146  else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
6147  elog(ERROR, "bogus varno: %d", var->varno);
6148 
6149  /* Not special. Just invoke the callback. */
6150  callback(node, context, private);
6151 }
6152 
6153 /*
6154  * Get the name of a field of an expression of composite type. The
6155  * expression is usually a Var, but we handle other cases too.
6156  *
6157  * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
6158  *
6159  * This is fairly straightforward when the expression has a named composite
6160  * type; we need only look up the type in the catalogs. However, the type
6161  * could also be RECORD. Since no actual table or view column is allowed to
6162  * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
6163  * or to a subquery output. We drill down to find the ultimate defining
6164  * expression and attempt to infer the field name from it. We ereport if we
6165  * can't determine the name.
6166  *
6167  * Similarly, a PARAM of type RECORD has to refer to some expression of
6168  * a determinable composite type.
6169  */
6170 static const char *
6171 get_name_for_var_field(Var *var, int fieldno,
6172  int levelsup, deparse_context *context)
6173 {
6174  RangeTblEntry *rte;
6175  AttrNumber attnum;
6176  int netlevelsup;
6177  deparse_namespace *dpns;
6179  Node *expr;
6180 
6181  /*
6182  * If it's a RowExpr that was expanded from a whole-row Var, use the
6183  * column names attached to it.
6184  */
6185  if (IsA(var, RowExpr))
6186  {
6187  RowExpr *r = (RowExpr *) var;
6188 
6189  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6190  return strVal(list_nth(r->colnames, fieldno - 1));
6191  }
6192 
6193  /*
6194  * If it's a Param of type RECORD, try to find what the Param refers to.
6195  */
6196  if (IsA(var, Param))
6197  {
6198  Param *param = (Param *) var;
6199  ListCell *ancestor_cell;
6200 
6201  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6202  if (expr)
6203  {
6204  /* Found a match, so recurse to decipher the field name */
6205  deparse_namespace save_dpns;
6206  const char *result;
6207 
6208  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6209  result = get_name_for_var_field((Var *) expr, fieldno,
6210  0, context);
6211  pop_ancestor_plan(dpns, &save_dpns);
6212  return result;
6213  }
6214  }
6215 
6216  /*
6217  * If it's a Var of type RECORD, we have to find what the Var refers to;
6218  * if not, we can use get_expr_result_type. If that fails, we try
6219  * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
6220  * an acceptable message.
6221  */
6222  if (!IsA(var, Var) ||
6223  var->vartype != RECORDOID)
6224  {
6225  if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6226  tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
6227  exprTypmod((Node *) var));
6228  Assert(tupleDesc);
6229  /* Got the tupdesc, so we can extract the field name */
6230  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6231  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6232  }
6233 
6234  /* Find appropriate nesting depth */
6235  netlevelsup = var->varlevelsup + levelsup;
6236  if (netlevelsup >= list_length(context->namespaces))
6237  elog(ERROR, "bogus varlevelsup: %d offset %d",
6238  var->varlevelsup, levelsup);
6239  dpns = (deparse_namespace *) list_nth(context->namespaces,
6240  netlevelsup);
6241 
6242  /*
6243  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6244  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6245  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6246  */
6247  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6248  {
6249  rte = rt_fetch(var->varno, dpns->rtable);
6250  attnum = var->varattno;
6251  }
6252  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6253  {
6254  TargetEntry *tle;
6255  deparse_namespace save_dpns;
6256  const char *result;
6257 
6258  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6259  if (!tle)
6260  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6261 
6262  Assert(netlevelsup == 0);
6263  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6264 
6265  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6266  levelsup, context);
6267 
6268  pop_child_plan(dpns, &save_dpns);
6269  return result;
6270  }
6271  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6272  {
6273  TargetEntry *tle;
6274  deparse_namespace save_dpns;
6275  const char *result;
6276 
6277  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6278  if (!tle)
6279  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6280 
6281  Assert(netlevelsup == 0);
6282  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6283 
6284  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6285  levelsup, context);
6286 
6287  pop_child_plan(dpns, &save_dpns);
6288  return result;
6289  }
6290  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6291  {
6292  TargetEntry *tle;
6293  const char *result;
6294 
6295  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6296  if (!tle)
6297  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6298 
6299  Assert(netlevelsup == 0);
6300 
6301  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6302  levelsup, context);
6303 
6304  return result;
6305  }
6306  else
6307  {
6308  elog(ERROR, "bogus varno: %d", var->varno);
6309  return NULL; /* keep compiler quiet */
6310  }
6311 
6312  if (attnum == InvalidAttrNumber)
6313  {
6314  /* Var is whole-row reference to RTE, so select the right field */
6315  return get_rte_attribute_name(rte, fieldno);
6316  }
6317 
6318  /*
6319  * This part has essentially the same logic as the parser's
6320  * expandRecordVariable() function, but we are dealing with a different
6321  * representation of the input context, and we only need one field name
6322  * not a TupleDesc. Also, we need special cases for finding subquery and
6323  * CTE subplans when deparsing Plan trees.
6324  */
6325  expr = (Node *) var; /* default if we can't drill down */
6326 
6327  switch (rte->rtekind)
6328  {
6329  case RTE_RELATION:
6330  case RTE_VALUES:
6331 
6332  /*
6333  * This case should not occur: a column of a table or values list
6334  * shouldn't have type RECORD. Fall through and fail (most
6335  * likely) at the bottom.
6336  */
6337  break;
6338  case RTE_SUBQUERY:
6339  /* Subselect-in-FROM: examine sub-select's output expr */
6340  {
6341  if (rte->subquery)
6342  {
6344  attnum);
6345 
6346  if (ste == NULL || ste->resjunk)
6347  elog(ERROR, "subquery %s does not have attribute %d",
6348  rte->eref->aliasname, attnum);
6349  expr = (Node *) ste->expr;
6350  if (IsA(expr, Var))
6351  {
6352  /*
6353  * Recurse into the sub-select to see what its Var
6354  * refers to. We have to build an additional level of
6355  * namespace to keep in step with varlevelsup in the
6356  * subselect.
6357  */
6358  deparse_namespace mydpns;
6359  const char *result;
6360 
6361  set_deparse_for_query(&mydpns, rte->subquery,
6362  context->namespaces);
6363 
6364  context->namespaces = lcons(&mydpns,
6365  context->namespaces);
6366 
6367  result = get_name_for_var_field((Var *) expr, fieldno,
6368  0, context);
6369 
6370  context->namespaces =
6371  list_delete_first(context->namespaces);
6372 
6373  return result;
6374  }
6375  /* else fall through to inspect the expression */
6376  }
6377  else
6378  {
6379  /*
6380  * We're deparsing a Plan tree so we don't have complete
6381  * RTE entries (in particular, rte->subquery is NULL). But
6382  * the only place we'd see a Var directly referencing a
6383  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6384  * look into the child plan's tlist instead.
6385  */
6386  TargetEntry *tle;
6387  deparse_namespace save_dpns;
6388  const char *result;
6389 
6390  if (!dpns->inner_planstate)
6391  elog(ERROR, "failed to find plan for subquery %s",
6392  rte->eref->aliasname);
6393  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6394  if (!tle)
6395  elog(ERROR, "bogus varattno for subquery var: %d",
6396  attnum);
6397  Assert(netlevelsup == 0);
6398  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6399 
6400  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6401  levelsup, context);
6402 
6403  pop_child_plan(dpns, &save_dpns);
6404  return result;
6405  }
6406  }
6407  break;
6408  case RTE_JOIN:
6409  /* Join RTE --- recursively inspect the alias variable */
6410  if (rte->joinaliasvars == NIL)
6411  elog(ERROR, "cannot decompile join alias var in plan tree");
6412  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
6413  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
6414  Assert(expr != NULL);
6415  /* we intentionally don't strip implicit coercions here */
6416  if (IsA(expr, Var))
6417  return get_name_for_var_field((Var *) expr, fieldno,
6418  var->varlevelsup + levelsup,
6419  context);
6420  /* else fall through to inspect the expression */
6421  break;
6422  case RTE_FUNCTION:
6423 
6424  /*
6425  * We couldn't get here unless a function is declared with one of
6426  * its result columns as RECORD, which is not allowed.
6427  */
6428  break;
6429  case RTE_CTE:
6430  /* CTE reference: examine subquery's output expr */
6431  {
6432  CommonTableExpr *cte = NULL;
6433  Index ctelevelsup;
6434  ListCell *lc;
6435 
6436  /*
6437  * Try to find the referenced CTE using the namespace stack.
6438  */
6439  ctelevelsup = rte->ctelevelsup + netlevelsup;
6440  if (ctelevelsup >= list_length(context->namespaces))
6441  lc = NULL;
6442  else
6443  {
6444  deparse_namespace *ctedpns;
6445 
6446  ctedpns = (deparse_namespace *)
6447  list_nth(context->namespaces, ctelevelsup);
6448  foreach(lc, ctedpns->ctes)
6449  {
6450  cte = (CommonTableExpr *) lfirst(lc);
6451  if (strcmp(cte->ctename, rte->ctename) == 0)
6452  break;
6453  }
6454  }
6455  if (lc != NULL)
6456  {
6457  Query *ctequery = (Query *) cte->ctequery;
6459  attnum);
6460 
6461  if (ste == NULL || ste->resjunk)
6462  elog(ERROR, "subquery %s does not have attribute %d",
6463  rte->eref->aliasname, attnum);
6464  expr = (Node *) ste->expr;
6465  if (IsA(expr, Var))
6466  {
6467  /*
6468  * Recurse into the CTE to see what its Var refers to.
6469  * We have to build an additional level of namespace
6470  * to keep in step with varlevelsup in the CTE.
6471  * Furthermore it could be an outer CTE, so we may
6472  * have to delete some levels of namespace.
6473  */
6474  List *save_nslist = context->namespaces;
6475  List *new_nslist;
6476  deparse_namespace mydpns;
6477  const char *result;
6478 
6479  set_deparse_for_query(&mydpns, ctequery,
6480  context->namespaces);
6481 
6482  new_nslist = list_copy_tail(context->namespaces,
6483  ctelevelsup);
6484  context->namespaces = lcons(&mydpns, new_nslist);
6485 
6486  result = get_name_for_var_field((Var *) expr, fieldno,
6487  0, context);
6488 
6489  context->namespaces = save_nslist;
6490 
6491  return result;
6492  }
6493  /* else fall through to inspect the expression */
6494  }
6495  else
6496  {
6497  /*
6498  * We're deparsing a Plan tree so we don't have a CTE
6499  * list. But the only place we'd see a Var directly
6500  * referencing a CTE RTE is in a CteScan plan node, and we
6501  * can look into the subplan's tlist instead.
6502  */
6503  TargetEntry *tle;
6504  deparse_namespace save_dpns;
6505  const char *result;
6506 
6507  if (!dpns->inner_planstate)
6508  elog(ERROR, "failed to find plan for CTE %s",
6509  rte->eref->aliasname);
6510  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6511  if (!tle)
6512  elog(ERROR, "bogus varattno for subquery var: %d",
6513  attnum);
6514  Assert(netlevelsup == 0);
6515  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6516 
6517  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6518  levelsup, context);
6519 
6520  pop_child_plan(dpns, &save_dpns);
6521  return result;
6522  }
6523  }
6524  break;
6525  }
6526 
6527  /*
6528  * We now have an expression we can't expand any more, so see if
6529  * get_expr_result_type() can do anything with it. If not, pass to
6530  * lookup_rowtype_tupdesc() which will probably fail, but will give an
6531  * appropriate error message while failing.
6532  */
6533  if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6534  tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
6535  exprTypmod(expr));
6536  Assert(tupleDesc);
6537  /* Got the tupdesc, so we can extract the field name */
6538  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6539  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6540 }
6541 
6542 /*
6543  * Try to find the referenced expression for a PARAM_EXEC Param that might
6544  * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
6545  *
6546  * If successful, return the expression and set *dpns_p and *ancestor_cell_p
6547  * appropriately for calling push_ancestor_plan(). If no referent can be
6548  * found, return NULL.
6549  */
6550 static Node *
6552  deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
6553 {
6554  /* Initialize output parameters to prevent compiler warnings */
6555  *dpns_p = NULL;
6556  *ancestor_cell_p = NULL;
6557 
6558  /*
6559  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
6560  * SubPlan argument. This will necessarily be in some ancestor of the
6561  * current expression's PlanState.
6562  */
6563  if (param->paramkind == PARAM_EXEC)
6564  {
6565  deparse_namespace *dpns;
6566  PlanState *child_ps;
6567  bool in_same_plan_level;
6568  ListCell *lc;
6569 
6570  dpns = (deparse_namespace *) linitial(context->namespaces);
6571  child_ps = dpns->planstate;
6572  in_same_plan_level = true;
6573 
6574  foreach(lc, dpns->ancestors)
6575  {
6576  PlanState *ps = (PlanState *) lfirst(lc);
6577  ListCell *lc2;
6578 
6579  /*
6580  * NestLoops transmit params to their inner child only; also, once
6581  * we've crawled up out of a subplan, this couldn't possibly be
6582  * the right match.
6583  */
6584  if (IsA(ps, NestLoopState) &&
6585  child_ps == innerPlanState(ps) &&
6586  in_same_plan_level)
6587  {
6588  NestLoop *nl = (NestLoop *) ps->plan;
6589 
6590  foreach(lc2, nl->nestParams)
6591  {
6592  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
6593 
6594  if (nlp->paramno == param->paramid)
6595  {
6596  /* Found a match, so return it */
6597  *dpns_p = dpns;
6598  *ancestor_cell_p = lc;
6599  return (Node *) nlp->paramval;
6600  }
6601  }
6602  }
6603 
6604  /*
6605  * Check to see if we're crawling up from a subplan.
6606  */
6607  foreach(lc2, ps->subPlan)
6608  {
6609  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6610  SubPlan *subplan = (SubPlan *) sstate->xprstate.expr;
6611  ListCell *lc3;
6612  ListCell *lc4;
6613 
6614  if (child_ps != sstate->planstate)
6615  continue;
6616 
6617  /* Matched subplan, so check its arguments */
6618  forboth(lc3, subplan->parParam, lc4, subplan->args)
6619  {
6620  int paramid = lfirst_int(lc3);
6621  Node *arg = (Node *) lfirst(lc4);
6622 
6623  if (paramid == param->paramid)
6624  {
6625  /* Found a match, so return it */
6626  *dpns_p = dpns;
6627  *ancestor_cell_p = lc;
6628  return arg;
6629  }
6630  }
6631 
6632  /* Keep looking, but we are emerging from a subplan. */
6633  in_same_plan_level = false;
6634  break;
6635  }
6636 
6637  /*
6638  * Likewise check to see if we're emerging from an initplan.
6639  * Initplans never have any parParams, so no need to search that
6640  * list, but we need to know if we should reset
6641  * in_same_plan_level.
6642  */
6643  foreach(lc2, ps->initPlan)
6644  {
6645  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6646 
6647  if (child_ps != sstate->planstate)
6648  continue;
6649 
6650  /* No parameters to be had here. */
6651  Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL);
6652 
6653  /* Keep looking, but we are emerging from an initplan. */
6654  in_same_plan_level = false;
6655  break;
6656  }
6657 
6658  /* No luck, crawl up to next ancestor */
6659  child_ps = ps;
6660  }
6661  }
6662 
6663  /* No referent found */
6664  return NULL;
6665 }
6666 
6667 /*
6668  * Display a Param appropriately.
6669  */
6670 static void
6672 {
6673  Node *expr;
6674  deparse_namespace *dpns;
6675  ListCell *ancestor_cell;
6676 
6677  /*
6678  * If it's a PARAM_EXEC parameter, try to locate the expression from which
6679  * the parameter was computed. Note that failing to find a referent isn't
6680  * an error, since the Param might well be a subplan output rather than an
6681  * input.
6682  */
6683  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6684  if (expr)
6685  {
6686  /* Found a match, so print it */
6687  deparse_namespace save_dpns;
6688  bool save_varprefix;
6689  bool need_paren;
6690 
6691  /* Switch attention to the ancestor plan node */
6692  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6693 
6694  /*
6695  * Force prefixing of Vars, since they won't belong to the relation
6696  * being scanned in the original plan node.
6697  */
6698  save_varprefix = context->varprefix;
6699  context->varprefix = true;
6700 
6701  /*
6702  * A Param's expansion is typically a Var, Aggref, or upper-level
6703  * Param, which wouldn't need extra parentheses. Otherwise, insert
6704  * parens to ensure the expression looks atomic.
6705  */
6706  need_paren = !(IsA(expr, Var) ||
6707  IsA(expr, Aggref) ||
6708  IsA(expr, Param));
6709  if (need_paren)
6710  appendStringInfoChar(context->buf, '(');
6711 
6712  get_rule_expr(expr, context, false);
6713 
6714  if (need_paren)
6715  appendStringInfoChar(context->buf, ')');
6716 
6717  context->varprefix = save_varprefix;
6718 
6719  pop_ancestor_plan(dpns, &save_dpns);
6720 
6721  return;
6722  }
6723 
6724  /*
6725  * Not PARAM_EXEC, or couldn't find referent: just print $N.
6726  */
6727  appendStringInfo(context->buf, "$%d", param->paramid);
6728 }
6729 
6730 /*
6731  * get_simple_binary_op_name
6732  *
6733  * helper function for isSimpleNode
6734  * will return single char binary operator name, or NULL if it's not
6735  */
6736 static const char *
6738 {
6739  List *args = expr->args;
6740 
6741  if (list_length(args) == 2)
6742  {
6743  /* binary operator */
6744  Node *arg1 = (Node *) linitial(args);
6745  Node *arg2 = (Node *) lsecond(args);
6746  const char *op;
6747 
6748  op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
6749  if (strlen(op) == 1)
6750  return op;
6751  }
6752  return NULL;
6753 }
6754 
6755 
6756 /*
6757  * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
6758  *
6759  * true : simple in the context of parent node's type
6760  * false : not simple
6761  */
6762 static bool
6763 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
6764 {
6765  if (!node)
6766  return false;
6767 
6768  switch (nodeTag(node))
6769  {
6770  case T_Var:
6771  case T_Const:
6772  case T_Param:
6773  case T_CoerceToDomainValue:
6774  case T_SetToDefault:
6775  case T_CurrentOfExpr:
6776  /* single words: always simple */
6777  return true;
6778 
6779  case T_ArrayRef:
6780  case T_ArrayExpr:
6781  case T_RowExpr:
6782  case T_CoalesceExpr:
6783  case T_MinMaxExpr:
6784  case T_XmlExpr:
6785  case T_NullIfExpr:
6786  case T_Aggref:
6787  case T_WindowFunc:
6788  case T_FuncExpr:
6789  /* function-like: name(..) or name[..] */
6790  return true;
6791 
6792  /* CASE keywords act as parentheses */
6793  case T_CaseExpr:
6794  return true;
6795 
6796  case T_FieldSelect:
6797 
6798  /*
6799  * appears simple since . has top precedence, unless parent is
6800  * T_FieldSelect itself!
6801  */
6802  return (IsA(parentNode, FieldSelect) ? false : true);
6803 
6804  case T_FieldStore:
6805 
6806  /*
6807  * treat like FieldSelect (probably doesn't matter)
6808  */
6809  return (IsA(parentNode, FieldStore) ? false : true);
6810 
6811  case T_CoerceToDomain:
6812  /* maybe simple, check args */
6813  return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
6814  node, prettyFlags);
6815  case T_RelabelType:
6816  return isSimpleNode((Node *) ((RelabelType *) node)->arg,
6817  node, prettyFlags);
6818  case T_CoerceViaIO:
6819  return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
6820  node, prettyFlags);
6821  case T_ArrayCoerceExpr:
6822  return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
6823  node, prettyFlags);
6824  case T_ConvertRowtypeExpr:
6825  return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
6826  node, prettyFlags);
6827 
6828  case T_OpExpr:
6829  {
6830  /* depends on parent node type; needs further checking */
6831  if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
6832  {
6833  const char *op;
6834  const char *parentOp;
6835  bool is_lopriop;
6836  bool is_hipriop;
6837  bool is_lopriparent;
6838  bool is_hipriparent;
6839 
6840  op = get_simple_binary_op_name((OpExpr *) node);
6841  if (!op)
6842  return false;
6843 
6844  /* We know only the basic operators + - and * / % */
6845  is_lopriop = (strchr("+-", *op) != NULL);
6846  is_hipriop = (strchr("*/%", *op) != NULL);
6847  if (!(is_lopriop || is_hipriop))
6848  return false;
6849 
6850  parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
6851  if (!parentOp)
6852  return false;
6853 
6854  is_lopriparent = (strchr("+-", *parentOp) != NULL);
6855  is_hipriparent = (strchr("*/%", *parentOp) != NULL);
6856  if (!(is_lopriparent || is_hipriparent))
6857  return false;
6858 
6859  if (is_hipriop && is_lopriparent)
6860  return true; /* op binds tighter than parent */
6861 
6862  if (is_lopriop && is_hipriparent)
6863  return false;
6864 
6865  /*
6866  * Operators are same priority --- can skip parens only if
6867  * we have (a - b) - c, not a - (b - c).
6868  */
6869  if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
6870  return true;
6871 
6872  return false;
6873  }
6874  /* else do the same stuff as for T_SubLink et al. */
6875  /* FALL THROUGH */
6876  }
6877 
6878  case T_SubLink:
6879  case T_NullTest:
6880  case T_BooleanTest:
6881  case T_DistinctExpr:
6882  switch (nodeTag(parentNode))
6883  {
6884  case T_FuncExpr:
6885  {
6886  /* special handling for casts */
6887  CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
6888 
6889  if (type == COERCE_EXPLICIT_CAST ||
6890  type == COERCE_IMPLICIT_CAST)
6891  return false;
6892  return true; /* own parentheses */
6893  }
6894  case T_BoolExpr: /* lower precedence */
6895  case T_ArrayRef: /* other separators */
6896  case T_ArrayExpr: /* other separators */
6897  case T_RowExpr: /* other separators */
6898  case T_CoalesceExpr: /* own parentheses */
6899  case T_MinMaxExpr: /* own parentheses */
6900  case T_XmlExpr: /* own parentheses */
6901  case T_NullIfExpr: /* other separators */
6902  case T_Aggref: /* own parentheses */
6903  case T_WindowFunc: /* own parentheses */
6904  case T_CaseExpr: /* other separators */
6905  return true;
6906  default:
6907  return false;
6908  }
6909 
6910  case T_BoolExpr:
6911  switch (nodeTag(parentNode))
6912  {
6913  case T_BoolExpr:
6914  if (prettyFlags & PRETTYFLAG_PAREN)
6915  {
6916  BoolExprType type;
6917  BoolExprType parentType;
6918 
6919  type = ((BoolExpr *) node)->boolop;
6920  parentType = ((BoolExpr *) parentNode)->boolop;
6921  switch (type)
6922  {
6923  case NOT_EXPR:
6924  case AND_EXPR:
6925  if (parentType == AND_EXPR || parentType == OR_EXPR)
6926  return true;
6927  break;
6928  case OR_EXPR:
6929  if (parentType == OR_EXPR)
6930  return true;
6931  break;
6932  }
6933  }
6934  return false;
6935  case T_FuncExpr:
6936  {
6937  /* special handling for casts */
6938  CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
6939 
6940  if (type == COERCE_EXPLICIT_CAST ||
6941  type == COERCE_IMPLICIT_CAST)
6942  return false;
6943  return true; /* own parentheses */
6944  }
6945  case T_ArrayRef: /* other separators */
6946  case T_ArrayExpr: /* other separators */
6947  case T_RowExpr: /* other separators */
6948  case T_CoalesceExpr: /* own parentheses */
6949  case T_MinMaxExpr: /* own parentheses */
6950  case T_XmlExpr: /* own parentheses */
6951  case T_NullIfExpr: /* other separators */
6952  case T_Aggref: /* own parentheses */
6953  case T_WindowFunc: /* own parentheses */
6954  case T_CaseExpr: /* other separators */
6955  return true;
6956  default:
6957  return false;
6958  }
6959 
6960  default:
6961  break;
6962  }
6963  /* those we don't know: in dubio complexo */
6964  return false;
6965 }
6966 
6967 
6968 /*
6969  * appendContextKeyword - append a keyword to buffer
6970  *
6971  * If prettyPrint is enabled, perform a line break, and adjust indentation.
6972  * Otherwise, just append the keyword.
6973  */
6974 static void
6975 appendContextKeyword(deparse_context *context, const char *str,
6976  int indentBefore, int indentAfter, int indentPlus)
6977 {
6978  StringInfo buf = context->buf;
6979 
6980  if (PRETTY_INDENT(context))
6981  {
6982  int indentAmount;
6983 
6984  context->indentLevel += indentBefore;
6985 
6986  /* remove any trailing spaces currently in the buffer ... */
6988  /* ... then add a newline and some spaces */
6989  appendStringInfoChar(buf, '\n');
6990 
6991  if (context->indentLevel < PRETTYINDENT_LIMIT)
6992  indentAmount = Max(context->indentLevel, 0) + indentPlus;
6993  else
6994  {
6995  /*
6996  * If we're indented more than PRETTYINDENT_LIMIT characters, try
6997  * to conserve horizontal space by reducing the per-level
6998  * indentation. For best results the scale factor here should
6999  * divide all the indent amounts that get added to indentLevel
7000  * (PRETTYINDENT_STD, etc). It's important that the indentation
7001  * not grow unboundedly, else deeply-nested trees use O(N^2)
7002  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7003  */
7004  indentAmount = PRETTYINDENT_LIMIT +
7005  (context->indentLevel - PRETTYINDENT_LIMIT) /
7006  (PRETTYINDENT_STD / 2);
7007  indentAmount %= PRETTYINDENT_LIMIT;
7008  /* scale/wrap logic affects indentLevel, but not indentPlus */
7009  indentAmount += indentPlus;
7010  }
7011  appendStringInfoSpaces(buf, indentAmount);
7012 
7013  appendStringInfoString(buf, str);
7014 
7015  context->indentLevel += indentAfter;
7016  if (context->indentLevel < 0)
7017  context->indentLevel = 0;
7018  }
7019  else
7020  appendStringInfoString(buf, str);
7021 }
7022 
7023 /*
7024  * removeStringInfoSpaces - delete trailing spaces from a buffer.
7025  *
7026  * Possibly this should move to stringinfo.c at some point.
7027  */
7028 static void
7030 {
7031  while (str->len > 0 && str->data[str->len - 1] == ' ')
7032  str->data[--(str->len)] = '\0';
7033 }
7034 
7035 
7036 /*
7037  * get_rule_expr_paren - deparse expr using get_rule_expr,
7038  * embracing the string with parentheses if necessary for prettyPrint.
7039  *
7040  * Never embrace if prettyFlags=0, because it's done in the calling node.
7041  *
7042  * Any node that does *not* embrace its argument node by sql syntax (with
7043  * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
7044  * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
7045  * added.
7046  */
7047 static void
7049  bool showimplicit, Node *parentNode)
7050 {
7051  bool need_paren;
7052 
7053  need_paren = PRETTY_PAREN(context) &&
7054  !isSimpleNode(node, parentNode, context->prettyFlags);
7055 
7056  if (need_paren)
7057  appendStringInfoChar(context->buf, '(');
7058 
7059  get_rule_expr(node, context, showimplicit);
7060 
7061  if (need_paren)
7062  appendStringInfoChar(context->buf, ')');
7063 }
7064 
7065 
7066 /* ----------
7067  * get_rule_expr - Parse back an expression
7068  *
7069  * Note: showimplicit determines whether we display any implicit cast that
7070  * is present at the top of the expression tree. It is a passed argument,
7071  * not a field of the context struct, because we change the value as we
7072  * recurse down into the expression. In general we suppress implicit casts
7073  * when the result type is known with certainty (eg, the arguments of an
7074  * OR must be boolean). We display implicit casts for arguments of functions
7075  * and operators, since this is needed to be certain that the same function
7076  * or operator will be chosen when the expression is re-parsed.
7077  * ----------
7078  */
7079 static void
7081  bool showimplicit)
7082 {
7083  StringInfo buf = context->buf;
7084 
7085  if (node == NULL)
7086  return;
7087 
7088  /* Guard against excessively long or deeply-nested queries */
7091 
7092  /*
7093  * Each level of get_rule_expr must emit an indivisible term
7094  * (parenthesized if necessary) to ensure result is reparsed into the same
7095  * expression tree. The only exception is that when the input is a List,
7096  * we emit the component items comma-separated with no surrounding
7097  * decoration; this is convenient for most callers.
7098  */
7099  switch (nodeTag(node))
7100  {
7101  case T_Var:
7102  (void) get_variable((Var *) node, 0, false, context);
7103  break;
7104 
7105  case T_Const:
7106  get_const_expr((Const *) node, context, 0);
7107  break;
7108 
7109  case T_Param:
7110  get_parameter((Param *) node, context);
7111  break;
7112 
7113  case T_Aggref:
7114  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7115  break;
7116 
7117  case T_GroupingFunc:
7118  {
7119  GroupingFunc *gexpr = (GroupingFunc *) node;
7120 
7121  appendStringInfoString(buf, "GROUPING(");
7122  get_rule_expr((Node *) gexpr->args, context, true);
7123  appendStringInfoChar(buf, ')');
7124  }
7125  break;
7126 
7127  case T_WindowFunc:
7128  get_windowfunc_expr((WindowFunc *) node, context);
7129  break;
7130 
7131  case T_ArrayRef:
7132  {
7133  ArrayRef *aref = (ArrayRef *) node;
7134  bool need_parens;
7135 
7136  /*
7137  * If the argument is a CaseTestExpr, we must be inside a
7138  * FieldStore, ie, we are assigning to an element of an array
7139  * within a composite column. Since we already punted on
7140  * displaying the FieldStore's target information, just punt
7141  * here too, and display only the assignment source
7142  * expression.
7143  */
7144  if (IsA(aref->refexpr, CaseTestExpr))
7145  {
7146  Assert(aref->refassgnexpr);
7147  get_rule_expr((Node *) aref->refassgnexpr,
7148  context, showimplicit);
7149  break;
7150  }
7151 
7152  /*
7153  * Parenthesize the argument unless it's a simple Var or a
7154  * FieldSelect. (In particular, if it's another ArrayRef, we
7155  * *must* parenthesize to avoid confusion.)
7156  */
7157  need_parens = !IsA(aref->refexpr, Var) &&
7158  !IsA(aref->refexpr, FieldSelect);
7159  if (need_parens)
7160  appendStringInfoChar(buf, '(');
7161  get_rule_expr((Node *) aref->refexpr, context, showimplicit);
7162  if (need_parens)
7163  appendStringInfoChar(buf, ')');
7164 
7165  /*
7166  * If there's a refassgnexpr, we want to print the node in the
7167  * format "array[subscripts] := refassgnexpr". This is not
7168  * legal SQL, so decompilation of INSERT or UPDATE statements
7169  * should always use processIndirection as part of the
7170  * statement-level syntax. We should only see this when
7171  * EXPLAIN tries to print the targetlist of a plan resulting
7172  * from such a statement.
7173  */
7174  if (aref->refassgnexpr)
7175  {
7176  Node *refassgnexpr;
7177 
7178  /*
7179  * Use processIndirection to print this node's subscripts
7180  * as well as any additional field selections or
7181  * subscripting in immediate descendants. It returns the
7182  * RHS expr that is actually being "assigned".
7183  */
7184  refassgnexpr = processIndirection(node, context, true);
7185  appendStringInfoString(buf, " := ");
7186  get_rule_expr(refassgnexpr, context, showimplicit);
7187  }
7188  else
7189  {
7190  /* Just an ordinary array fetch, so print subscripts */
7191  printSubscripts(aref, context);
7192  }
7193  }
7194  break;
7195 
7196  case T_FuncExpr:
7197  get_func_expr((FuncExpr *) node, context, showimplicit);
7198  break;
7199 
7200  case T_NamedArgExpr:
7201  {
7202  NamedArgExpr *na = (NamedArgExpr *) node;
7203 
7204  appendStringInfo(buf, "%s => ", quote_identifier(na->name));
7205  get_rule_expr((Node *) na->arg, context, showimplicit);
7206  }
7207  break;
7208 
7209  case T_OpExpr:
7210  get_oper_expr((OpExpr *) node, context);
7211  break;
7212 
7213  case T_DistinctExpr:
7214  {
7215  DistinctExpr *expr = (DistinctExpr *) node;
7216  List *args = expr->args;
7217  Node *arg1 = (Node *) linitial(args);
7218  Node *arg2 = (Node *) lsecond(args);
7219 
7220  if (!PRETTY_PAREN(context))
7221  appendStringInfoChar(buf, '(');
7222  get_rule_expr_paren(arg1, context, true, node);
7223  appendStringInfoString(buf, " IS DISTINCT FROM ");
7224  get_rule_expr_paren(arg2, context, true, node);
7225  if (!PRETTY_PAREN(context))
7226  appendStringInfoChar(buf, ')');
7227  }
7228  break;
7229 
7230  case T_NullIfExpr:
7231  {
7232  NullIfExpr *nullifexpr = (NullIfExpr *) node;
7233 
7234  appendStringInfoString(buf, "NULLIF(");
7235  get_rule_expr((Node *) nullifexpr->args, context, true);
7236  appendStringInfoChar(buf, ')');
7237  }
7238  break;
7239 
7240  case T_ScalarArrayOpExpr:
7241  {
7242  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
7243  List *args = expr->args;
7244  Node *arg1 = (Node *) linitial(args);
7245  Node *arg2 = (Node *) lsecond(args);
7246 
7247  if (!PRETTY_PAREN(context))
7248  appendStringInfoChar(buf, '(');
7249  get_rule_expr_paren(arg1, context, true, node);
7250  appendStringInfo(buf, " %s %s (",
7252  exprType(arg1),
7254  expr->useOr ? "ANY" : "ALL");
7255  get_rule_expr_paren(arg2, context, true, node);
7256 
7257  /*
7258  * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
7259  * a bare sub-SELECT. Since we're here, the sub-SELECT must
7260  * be meant as a scalar sub-SELECT yielding an array value to
7261  * be used in ScalarArrayOpExpr; but the grammar will
7262  * preferentially interpret such a construct as an ANY/ALL
7263  * SubLink. To prevent misparsing the output that way, insert
7264  * a dummy coercion (which will be stripped by parse analysis,
7265  * so no inefficiency is added in dump and reload). This is
7266  * indeed most likely what the user wrote to get the construct
7267  * accepted in the first place.
7268  */
7269  if (IsA(arg2, SubLink) &&
7270  ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
7271  appendStringInfo(buf, "::%s",
7273  exprTypmod(arg2)));
7274  appendStringInfoChar(buf, ')');
7275  if (!PRETTY_PAREN(context))
7276  appendStringInfoChar(buf, ')');
7277  }
7278  break;
7279 
7280  case T_BoolExpr:
7281  {
7282  BoolExpr *expr = (BoolExpr *) node;
7283  Node *first_arg = linitial(expr->args);
7284  ListCell *arg = lnext(list_head(expr->args));
7285 
7286  switch (expr->boolop)
7287  {
7288  case AND_EXPR:
7289  if (!PRETTY_PAREN(context))
7290  appendStringInfoChar(buf, '(');
7291  get_rule_expr_paren(first_arg, context,
7292  false, node);
7293  while (arg)
7294  {
7295  appendStringInfoString(buf, " AND ");
7296  get_rule_expr_paren((Node *) lfirst(arg), context,
7297  false, node);
7298  arg = lnext(arg);
7299  }
7300  if (!PRETTY_PAREN(context))
7301  appendStringInfoChar(buf, ')');
7302  break;
7303 
7304  case OR_EXPR:
7305  if (!PRETTY_PAREN(context))
7306  appendStringInfoChar(buf, '(');
7307  get_rule_expr_paren(first_arg, context,
7308  false, node);
7309  while (arg)
7310  {
7311  appendStringInfoString(buf, " OR ");
7312  get_rule_expr_paren((Node *) lfirst(arg), context,
7313  false, node);
7314  arg = lnext(arg);
7315  }
7316  if (!PRETTY_PAREN(context))
7317  appendStringInfoChar(buf, ')');
7318  break;
7319 
7320  case NOT_EXPR:
7321  if (!PRETTY_PAREN(context))
7322  appendStringInfoChar(buf, '(');
7323  appendStringInfoString(buf, "NOT ");
7324  get_rule_expr_paren(first_arg, context,
7325  false, node);
7326  if (!PRETTY_PAREN(context))
7327  appendStringInfoChar(buf, ')');
7328  break;
7329 
7330  default:
7331  elog(ERROR, "unrecognized boolop: %d",
7332  (int) expr->boolop);
7333  }
7334  }
7335  break;
7336 
7337  case T_SubLink:
7338  get_sublink_expr((SubLink *) node, context);
7339  break;
7340 
7341  case T_SubPlan:
7342  {
7343  SubPlan *subplan = (SubPlan *) node;
7344 
7345  /*
7346  * We cannot see an already-planned subplan in rule deparsing,
7347  * only while EXPLAINing a query plan. We don't try to
7348  * reconstruct the original SQL, just reference the subplan
7349  * that appears elsewhere in EXPLAIN's result.
7350  */
7351  if (subplan->useHashTable)
7352  appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
7353  else
7354  appendStringInfo(buf, "(%s)", subplan->plan_name);
7355  }
7356  break;
7357 
7358  case T_AlternativeSubPlan:
7359  {
7360  AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
7361  ListCell *lc;
7362 
7363  /* As above, this can only happen during EXPLAIN */
7364  appendStringInfoString(buf, "(alternatives: ");
7365  foreach(lc, asplan->subplans)
7366  {
7367  SubPlan *splan = (SubPlan *) lfirst(lc);
7368 
7369  Assert(IsA(splan, SubPlan));
7370  if (splan->useHashTable)
7371  appendStringInfo(buf, "hashed %s", splan->plan_name);
7372  else
7373  appendStringInfoString(buf, splan->plan_name);
7374  if (lnext(lc))
7375  appendStringInfoString(buf, " or ");
7376  }
7377  appendStringInfoChar(buf, ')');
7378  }
7379  break;
7380 
7381  case T_FieldSelect:
7382  {
7383  FieldSelect *fselect = (FieldSelect *) node;
7384  Node *arg = (Node *) fselect->arg;
7385  int fno = fselect->fieldnum;
7386  const char *fieldname;
7387  bool need_parens;
7388 
7389  /*
7390  * Parenthesize the argument unless it's an ArrayRef or
7391  * another FieldSelect. Note in particular that it would be
7392  * WRONG to not parenthesize a Var argument; simplicity is not
7393  * the issue here, having the right number of names is.
7394  */
7395  need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
7396  if (need_parens)
7397  appendStringInfoChar(buf, '(');
7398  get_rule_expr(arg, context, true);
7399  if (need_parens)
7400  appendStringInfoChar(buf, ')');
7401 
7402  /*
7403  * Get and print the field name.
7404  */
7405  fieldname = get_name_for_var_field((Var *) arg, fno,
7406  0, context);
7407  appendStringInfo(buf, ".%s", quote_identifier(fieldname));
7408  }
7409  break;
7410 
7411  case T_FieldStore:
7412  {
7413  FieldStore *fstore = (FieldStore *) node;
7414  bool need_parens;
7415 
7416  /*
7417  * There is no good way to represent a FieldStore as real SQL,
7418  * so decompilation of INSERT or UPDATE statements should
7419  * always use processIndirection as part of the
7420  * statement-level syntax. We should only get here when
7421  * EXPLAIN tries to print the targetlist of a plan resulting
7422  * from such a statement. The plan case is even harder than
7423  * ordinary rules would be, because the planner tries to
7424  * collapse multiple assignments to the same field or subfield
7425  * into one FieldStore; so we can see a list of target fields
7426  * not just one, and the arguments could be FieldStores
7427  * themselves. We don't bother to try to print the target
7428  * field names; we just print the source arguments, with a
7429  * ROW() around them if there's more than one. This isn't
7430  * terribly complete, but it's probably good enough for
7431  * EXPLAIN's purposes; especially since anything more would be
7432  * either hopelessly confusing or an even poorer
7433  * representation of what the plan is actually doing.
7434  */
7435  need_parens = (list_length(fstore->newvals) != 1);
7436  if (need_parens)
7437  appendStringInfoString(buf, "ROW(");
7438  get_rule_expr((Node *) fstore->newvals, context, showimplicit);
7439  if (need_parens)
7440  appendStringInfoChar(buf, ')');
7441  }
7442  break;
7443 
7444  case T_RelabelType:
7445  {
7446  RelabelType *relabel = (RelabelType *) node;
7447  Node *arg = (Node *) relabel->arg;
7448 
7449  if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
7450  !showimplicit)
7451  {
7452  /* don't show the implicit cast */
7453  get_rule_expr_paren(arg, context, false, node);
7454  }
7455  else
7456  {
7457  get_coercion_expr(arg, context,
7458  relabel->resulttype,
7459  relabel->resulttypmod,
7460  node);
7461  }
7462  }
7463  break;
7464 
7465  case T_CoerceViaIO:
7466  {
7467  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
7468  Node *arg = (Node *) iocoerce->arg;
7469 
7470  if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
7471  !showimplicit)
7472  {
7473  /* don't show the implicit cast */
7474  get_rule_expr_paren(arg, context, false, node);
7475  }
7476  else
7477  {
7478  get_coercion_expr(arg, context,
7479  iocoerce->resulttype,
7480  -1,
7481  node);
7482  }
7483  }
7484  break;
7485 
7486  case T_ArrayCoerceExpr:
7487  {
7488  ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
7489  Node *arg = (Node *) acoerce->arg;
7490 
7491  if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
7492  !showimplicit)
7493  {
7494  /* don't show the implicit cast */
7495  get_rule_expr_paren(arg, context, false, node);
7496  }
7497  else
7498  {
7499  get_coercion_expr(arg, context,
7500  acoerce->resulttype,
7501  acoerce->resulttypmod,
7502  node);
7503  }
7504  }
7505  break;
7506 
7507  case T_ConvertRowtypeExpr:
7508  {
7510  Node *arg = (Node *) convert->arg;
7511 
7512  if (convert->convertformat == COERCE_IMPLICIT_CAST &&
7513  !showimplicit)
7514  {
7515  /* don't show the implicit cast */
7516  get_rule_expr_paren(arg, context, false, node);
7517  }
7518  else
7519  {
7520  get_coercion_expr(arg, context,
7521  convert->resulttype, -1,
7522  node);
7523  }
7524  }
7525  break;
7526 
7527  case T_CollateExpr:
7528  {
7529  CollateExpr *collate = (CollateExpr *) node;
7530  Node *arg = (Node *) collate->arg;
7531 
7532  if (!PRETTY_PAREN(context))
7533  appendStringInfoChar(buf, '(');
7534  get_rule_expr_paren(arg, context, showimplicit, node);
7535  appendStringInfo(buf, " COLLATE %s",
7536  generate_collation_name(collate->collOid));
7537  if (!PRETTY_PAREN(context))
7538  appendStringInfoChar(buf, ')');
7539  }
7540  break;
7541 
7542  case T_CaseExpr:
7543  {
7544  CaseExpr *caseexpr = (CaseExpr *) node;
7545  ListCell *temp;
7546 
7547  appendContextKeyword(context, "CASE",
7548  0, PRETTYINDENT_VAR, 0);
7549  if (caseexpr->arg)
7550  {
7551  appendStringInfoChar(buf, ' ');
7552  get_rule_expr((Node *) caseexpr->arg, context, true);
7553  }
7554  foreach(temp, caseexpr->args)
7555  {
7556  CaseWhen *when = (CaseWhen *) lfirst(temp);
7557  Node *w = (Node *) when->expr;
7558 
7559  if (caseexpr->arg)
7560  {
7561  /*
7562  * The parser should have produced WHEN clauses of the
7563  * form "CaseTestExpr = RHS", possibly with an
7564  * implicit coercion inserted above the CaseTestExpr.
7565  * For accurate decompilation of rules it's essential
7566  * that we show just the RHS. However in an
7567  * expression that's been through the optimizer, the
7568  * WHEN clause could be almost anything (since the
7569  * equality operator could have been expanded into an
7570  * inline function). If we don't recognize the form
7571  * of the WHEN clause, just punt and display it as-is.
7572  */
7573  if (IsA(w, OpExpr))
7574  {
7575  List *args = ((OpExpr *) w)->args;
7576 
7577  if (list_length(args) == 2 &&
7579  CaseTestExpr))
7580  w = (Node *) lsecond(args);
7581  }
7582  }
7583 
7584  if (!PRETTY_INDENT(context))
7585  appendStringInfoChar(buf, ' ');
7586  appendContextKeyword(context, "WHEN ",
7587  0, 0, 0);
7588  get_rule_expr(w, context, false);
7589  appendStringInfoString(buf, " THEN ");
7590  get_rule_expr((Node *) when->result, context, true);
7591  }
7592  if (!PRETTY_INDENT(context))
7593  appendStringInfoChar(buf, ' ');
7594  appendContextKeyword(context, "ELSE ",
7595  0, 0, 0);
7596  get_rule_expr((Node *) caseexpr->defresult, context, true);
7597  if (!PRETTY_INDENT(context))
7598  appendStringInfoChar(buf, ' ');
7599  appendContextKeyword(context, "END",
7600  -PRETTYINDENT_VAR, 0, 0);
7601  }
7602  break;
7603 
7604  case T_CaseTestExpr:
7605  {
7606  /*
7607  * Normally we should never get here, since for expressions
7608  * that can contain this node type we attempt to avoid
7609  * recursing to it. But in an optimized expression we might
7610  * be unable to avoid that (see comments for CaseExpr). If we
7611  * do see one, print it as CASE_TEST_EXPR.
7612  */
7613  appendStringInfoString(buf, "CASE_TEST_EXPR");
7614  }
7615  break;
7616 
7617  case T_ArrayExpr:
7618  {
7619  ArrayExpr *arrayexpr = (ArrayExpr *) node;
7620 
7621  appendStringInfoString(buf, "ARRAY[");
7622  get_rule_expr((Node *) arrayexpr->elements, context, true);
7623  appendStringInfoChar(buf, ']');
7624 
7625  /*
7626  * If the array isn't empty, we assume its elements are
7627  * coerced to the desired type. If it's empty, though, we
7628  * need an explicit coercion to the array type.
7629  */
7630  if (arrayexpr->elements == NIL)
7631  appendStringInfo(buf, "::%s",
7632  format_type_with_typemod(arrayexpr->array_typeid, -1));
7633  }
7634  break;
7635 
7636  case T_RowExpr:
7637  {
7638  RowExpr *rowexpr = (RowExpr *) node;
7639  TupleDesc tupdesc = NULL;
7640  ListCell *arg;
7641  int i;
7642  char *sep;
7643 
7644  /*
7645  * If it's a named type and not RECORD, we may have to skip
7646  * dropped columns and/or claim there are NULLs for added
7647  * columns.
7648  */
7649  if (rowexpr->row_typeid != RECORDOID)
7650  {
7651  tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
7652  Assert(list_length(rowexpr->args) <= tupdesc->natts);
7653  }
7654 
7655  /*
7656  * SQL99 allows "ROW" to be omitted when there is more than
7657  * one column, but for simplicity we always print it.
7658  */
7659  appendStringInfoString(buf, "ROW(");
7660  sep = "";
7661  i = 0;
7662  foreach(arg, rowexpr->args)
7663  {
7664  Node *e = (Node *) lfirst(arg);
7665 
7666  if (tupdesc == NULL ||
7667  !tupdesc->attrs[i]->attisdropped)
7668  {
7669  appendStringInfoString(buf, sep);
7670  /* Whole-row Vars need special treatment here */
7671  get_rule_expr_toplevel(e, context, true);
7672  sep = ", ";
7673  }
7674  i++;
7675  }
7676  if (tupdesc != NULL)
7677  {
7678  while (i < tupdesc->natts)
7679  {
7680  if (!tupdesc->attrs[i]->attisdropped)
7681  {
7682  appendStringInfoString(buf, sep);
7683  appendStringInfoString(buf, "NULL");
7684  sep = ", ";
7685  }
7686  i++;
7687  }
7688 
7689  ReleaseTupleDesc(tupdesc);
7690  }
7691  appendStringInfoChar(buf, ')');
7692  if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
7693  appendStringInfo(buf, "::%s",
7694  format_type_with_typemod(rowexpr->row_typeid, -1));
7695  }
7696  break;
7697 
7698  case T_RowCompareExpr:
7699  {
7700  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
7701  ListCell *arg;
7702  char *sep;
7703 
7704  /*
7705  * SQL99 allows "ROW" to be omitted when there is more than
7706  * one column, but for simplicity we always print it.
7707  */
7708  appendStringInfoString(buf, "(ROW(");
7709  sep = "";
7710  foreach(arg, rcexpr->largs)
7711  {
7712  Node *e = (Node *) lfirst(arg);
7713 
7714  appendStringInfoString(buf, sep);
7715  get_rule_expr(e, context, true);
7716  sep = ", ";
7717  }
7718 
7719  /*
7720  * We assume that the name of the first-column operator will
7721  * do for all the rest too. This is definitely open to
7722  * failure, eg if some but not all operators were renamed
7723  * since the construct was parsed, but there seems no way to
7724  * be perfect.
7725  */
7726  appendStringInfo(buf, ") %s ROW(",
7728  exprType(linitial(rcexpr->largs)),
7729  exprType(linitial(rcexpr->rargs))));
7730  sep = "";
7731  foreach(arg, rcexpr->rargs)
7732  {
7733  Node *e = (Node *) lfirst(arg);
7734 
7735  appendStringInfoString(buf, sep);
7736  get_rule_expr(e, context, true);
7737  sep = ", ";
7738  }
7739  appendStringInfoString(buf, "))");
7740  }
7741  break;
7742 
7743  case T_CoalesceExpr:
7744  {
7745  CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
7746 
7747  appendStringInfoString(buf, "COALESCE(");
7748  get_rule_expr((Node *) coalesceexpr->args, context, true);
7749  appendStringInfoChar(buf, ')');
7750  }
7751  break;
7752 
7753  case T_MinMaxExpr:
7754  {
7755  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
7756 
7757  switch (minmaxexpr->op)
7758  {
7759  case IS_GREATEST:
7760  appendStringInfoString(buf, "GREATEST(");
7761  break;
7762  case IS_LEAST:
7763  appendStringInfoString(buf, "LEAST(");
7764  break;
7765  }
7766  get_rule_expr((Node *) minmaxexpr->args, context, true);
7767  appendStringInfoChar(buf, ')');
7768  }
7769  break;
7770 
7771  case T_XmlExpr:
7772  {
7773  XmlExpr *xexpr = (XmlExpr *) node;
7774  bool needcomma = false;
7775  ListCell *arg;
7776  ListCell *narg;
7777  Const *con;
7778 
7779  switch (xexpr->op)
7780  {
7781  case IS_XMLCONCAT:
7782  appendStringInfoString(buf, "XMLCONCAT(");
7783  break;
7784  case IS_XMLELEMENT:
7785  appendStringInfoString(buf, "XMLELEMENT(");
7786  break;
7787  case IS_XMLFOREST:
7788  appendStringInfoString(buf, "XMLFOREST(");
7789  break;
7790  case IS_XMLPARSE:
7791  appendStringInfoString(buf, "XMLPARSE(");
7792  break;
7793  case IS_XMLPI:
7794  appendStringInfoString(buf, "XMLPI(");
7795  break;
7796  case IS_XMLROOT:
7797  appendStringInfoString(buf, "XMLROOT(");
7798  break;
7799  case IS_XMLSERIALIZE:
7800  appendStringInfoString(buf, "XMLSERIALIZE(");
7801  break;
7802  case IS_DOCUMENT:
7803  break;
7804  }
7805  if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
7806  {
7807  if (xexpr->xmloption == XMLOPTION_DOCUMENT)
7808  appendStringInfoString(buf, "DOCUMENT ");
7809  else
7810  appendStringInfoString(buf, "CONTENT ");
7811  }
7812  if (xexpr->name)
7813  {
7814  appendStringInfo(buf, "NAME %s",
7816  needcomma = true;
7817  }
7818  if (xexpr->named_args)
7819  {
7820  if (xexpr->op != IS_XMLFOREST)
7821  {
7822  if (needcomma)
7823  appendStringInfoString(buf, ", ");
7824  appendStringInfoString(buf, "XMLATTRIBUTES(");
7825  needcomma = false;
7826  }
7827  forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
7828  {
7829  Node *e = (Node *) lfirst(arg);
7830  char *argname = strVal(lfirst(narg));
7831 
7832  if (needcomma)
7833  appendStringInfoString(buf, ", ");
7834  get_rule_expr((Node *) e, context, true);
7835  appendStringInfo(buf, " AS %s",
7837  needcomma = true;
7838  }
7839  if (xexpr->op != IS_XMLFOREST)
7840  appendStringInfoChar(buf, ')');
7841  }
7842  if (xexpr->args)
7843  {
7844  if (needcomma)
7845  appendStringInfoString(buf, ", ");
7846  switch (xexpr->op)
7847  {
7848  case IS_XMLCONCAT:
7849  case IS_XMLELEMENT:
7850  case IS_XMLFOREST:
7851  case IS_XMLPI:
7852  case IS_XMLSERIALIZE:
7853  /* no extra decoration needed */
7854  get_rule_expr((Node *) xexpr->args, context, true);
7855  break;
7856  case IS_XMLPARSE:
7857  Assert(list_length(xexpr->args) == 2);
7858 
7859  get_rule_expr((Node *) linitial(xexpr->args),
7860  context, true);
7861 
7862  con = (Const *) lsecond(xexpr->args);
7863  Assert(IsA(con, Const));
7864  Assert(!con->constisnull);
7865  if (DatumGetBool(con->constvalue))
7867  " PRESERVE WHITESPACE");
7868  else
7870  " STRIP WHITESPACE");
7871  break;
7872  case IS_XMLROOT:
7873  Assert(list_length(xexpr->args) == 3);
7874 
7875  get_rule_expr((Node *) linitial(xexpr->args),
7876  context, true);
7877 
7878  appendStringInfoString(buf, ", VERSION ");
7879  con = (Const *) lsecond(xexpr->args);
7880  if (IsA(con, Const) &&
7881  con->constisnull)
7882  appendStringInfoString(buf, "NO VALUE");
7883  else
7884  get_rule_expr((Node *) con, context, false);
7885 
7886  con = (Const *) lthird(xexpr->args);
7887  Assert(IsA(con, Const));
7888  if (con->constisnull)
7889  /* suppress STANDALONE NO VALUE */ ;
7890  else
7891  {
7892  switch (DatumGetInt32(con->constvalue))
7893  {
7894  case XML_STANDALONE_YES:
7896  ", STANDALONE YES");
7897  break;
7898  case XML_STANDALONE_NO:
7900  ", STANDALONE NO");
7901  break;
7904  ", STANDALONE NO VALUE");
7905  break;
7906  default:
7907  break;
7908  }
7909  }
7910  break;
7911  case IS_DOCUMENT:
7912  get_rule_expr_paren((Node *) xexpr->args, context, false, node);
7913  break;
7914  }
7915 
7916  }
7917  if (xexpr->op == IS_XMLSERIALIZE)
7918  appendStringInfo(buf, " AS %s",
7920  xexpr->typmod));
7921  if (xexpr->op == IS_DOCUMENT)
7922  appendStringInfoString(buf, " IS DOCUMENT");
7923  else
7924  appendStringInfoChar(buf, ')');
7925  }
7926  break;
7927 
7928  case T_NullTest:
7929  {
7930  NullTest *ntest = (NullTest *) node;
7931 
7932  if (!PRETTY_PAREN(context))
7933  appendStringInfoChar(buf, '(');
7934  get_rule_expr_paren((Node *) ntest->arg, context, true, node);
7935  switch (ntest->nulltesttype)
7936  {
7937  case IS_NULL:
7938  appendStringInfoString(buf, " IS NULL");
7939  break;
7940  case IS_NOT_NULL:
7941  appendStringInfoString(buf, " IS NOT NULL");
7942  break;
7943  default:
7944  elog(ERROR, "unrecognized nulltesttype: %d",
7945  (int) ntest->nulltesttype);
7946  }
7947  if (!PRETTY_PAREN(context))
7948  appendStringInfoChar(buf, ')');
7949  }
7950  break;
7951 
7952  case T_BooleanTest:
7953  {
7954  BooleanTest *btest = (BooleanTest *) node;
7955 
7956  if (!PRETTY_PAREN(context))
7957  appendStringInfoChar(buf, '(');
7958  get_rule_expr_paren((Node *) btest->arg, context, false, node);
7959  switch (btest->booltesttype)
7960  {
7961  case IS_TRUE:
7962  appendStringInfoString(buf, " IS TRUE");
7963  break;
7964  case IS_NOT_TRUE:
7965  appendStringInfoString(buf, " IS NOT TRUE");
7966  break;
7967  case IS_FALSE:
7968  appendStringInfoString(buf, " IS FALSE");
7969  break;
7970  case IS_NOT_FALSE:
7971  appendStringInfoString(buf, " IS NOT FALSE");
7972  break;
7973  case IS_UNKNOWN:
7974  appendStringInfoString(buf, " IS UNKNOWN");
7975  break;
7976  case IS_NOT_UNKNOWN:
7977  appendStringInfoString(buf, " IS NOT UNKNOWN");
7978  break;
7979  default:
7980  elog(ERROR, "unrecognized booltesttype: %d",
7981  (int) btest->booltesttype);
7982  }
7983  if (!PRETTY_PAREN(context))
7984  appendStringInfoChar(buf, ')');
7985  }
7986  break;
7987 
7988  case T_CoerceToDomain:
7989  {
7990  CoerceToDomain *ctest = (CoerceToDomain *) node;
7991  Node *arg = (Node *) ctest->arg;
7992 
7993  if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
7994  !showimplicit)
7995  {
7996  /* don't show the implicit cast */
7997  get_rule_expr(arg, context, false);
7998  }
7999  else
8000  {
8001  get_coercion_expr(arg, context,
8002  ctest->resulttype,
8003  ctest->resulttypmod,
8004  node);
8005  }
8006  }
8007  break;
8008 
8009  case T_CoerceToDomainValue:
8010  appendStringInfoString(buf, "VALUE");
8011  break;
8012 
8013  case T_SetToDefault:
8014  appendStringInfoString(buf, "DEFAULT");
8015  break;
8016 
8017  case T_CurrentOfExpr:
8018  {
8019  CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
8020 
8021  if (cexpr->cursor_name)
8022  appendStringInfo(buf, "CURRENT OF %s",
8023  quote_identifier(cexpr->cursor_name));
8024  else
8025  appendStringInfo(buf, "CURRENT OF $%d",
8026  cexpr->cursor_param);
8027  }
8028  break;
8029 
8030  case T_InferenceElem:
8031  {
8032  InferenceElem *iexpr = (InferenceElem *) node;
8033  bool save_varprefix;
8034  bool need_parens;
8035 
8036  /*
8037  * InferenceElem can only refer to target relation, so a
8038  * prefix is not useful, and indeed would cause parse errors.
8039  */
8040  save_varprefix = context->varprefix;
8041  context->varprefix = false;
8042 
8043  /*
8044  * Parenthesize the element unless it's a simple Var or a bare
8045  * function call. Follows pg_get_indexdef_worker().
8046  */
8047  need_parens = !IsA(iexpr->expr, Var);
8048  if (IsA(iexpr->expr, FuncExpr) &&
8049  ((FuncExpr *) iexpr->expr)->funcformat ==
8051  need_parens = false;
8052 
8053  if (need_parens)
8054  appendStringInfoChar(buf, '(');
8055  get_rule_expr((Node *) iexpr->expr,
8056  context, false);
8057  if (need_parens)
8058  appendStringInfoChar(buf, ')');
8059 
8060  context->varprefix = save_varprefix;
8061 
8062  if (iexpr->infercollid)
8063  appendStringInfo(buf, " COLLATE %s",
8065 
8066  /* Add the operator class name, if not default */
8067  if (iexpr->inferopclass)
8068  {
8069  Oid inferopclass = iexpr->inferopclass;
8070  Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass);
8071 
8072  get_opclass_name(inferopclass, inferopcinputtype, buf);
8073  }
8074  }
8075  break;
8076 
8077  case T_List:
8078  {
8079  char *sep;
8080  ListCell *l;
8081 
8082  sep = "";
8083  foreach(l, (List *) node)
8084  {
8085  appendStringInfoString(buf, sep);
8086  get_rule_expr((Node *) lfirst(l), context, showimplicit);
8087  sep = ", ";
8088  }
8089  }
8090  break;
8091 
8092  default:
8093  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
8094  break;
8095  }
8096 }
8097 
8098 /*
8099  * get_rule_expr_toplevel - Parse back a toplevel expression
8100  *
8101  * Same as get_rule_expr(), except that if the expr is just a Var, we pass
8102  * istoplevel = true not false to get_variable(). This causes whole-row Vars
8103  * to get printed with decoration that will prevent expansion of "*".
8104  * We need to use this in contexts such as ROW() and VALUES(), where the
8105  * parser would expand "foo.*" appearing at top level. (In principle we'd
8106  * use this in get_target_list() too, but that has additional worries about
8107  * whether to print AS, so it needs to invoke get_variable() directly anyway.)
8108  */
8109 static void
8111  bool showimplicit)
8112 {
8113  if (node && IsA(node, Var))
8114  (void) get_variable((Var *) node, 0, true, context);
8115  else
8116  get_rule_expr(node, context, showimplicit);
8117 }
8118 
8119 
8120 /*
8121  * get_oper_expr - Parse back an OpExpr node
8122  */
8123 static void
8125 {
8126  StringInfo buf = context->buf;
8127  Oid opno = expr->opno;
8128  List *args = expr->args;
8129 
8130  if (!PRETTY_PAREN(context))
8131  appendStringInfoChar(buf, '(');
8132  if (list_length(args) == 2)
8133  {
8134  /* binary operator */
8135  Node *arg1 = (Node *) linitial(args);
8136  Node *arg2 = (Node *) lsecond(args);
8137 
8138  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8139  appendStringInfo(buf, " %s ",
8141  exprType(arg1),
8142  exprType(arg2)));
8143  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8144  }
8145  else
8146  {
8147  /* unary operator --- but which side? */
8148  Node *arg = (Node *) linitial(args);
8149  HeapTuple tp;
8150  Form_pg_operator optup;
8151 
8153  if (!HeapTupleIsValid(tp))
8154  elog(ERROR, "cache lookup failed for operator %u", opno);
8155  optup = (Form_pg_operator) GETSTRUCT(tp);
8156  switch (optup->oprkind)
8157  {
8158  case 'l':
8159  appendStringInfo(buf, "%s ",
8161  InvalidOid,
8162  exprType(arg)));
8163  get_rule_expr_paren(arg, context, true, (Node *) expr);
8164  break;
8165  case 'r':
8166  get_rule_expr_paren(arg, context, true, (Node *) expr);
8167  appendStringInfo(buf, " %s",
8169  exprType(arg),
8170  InvalidOid));
8171  break;
8172  default:
8173  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8174  }
8175  ReleaseSysCache(tp);
8176  }
8177  if (!PRETTY_PAREN(context))
8178  appendStringInfoChar(buf, ')');
8179 }
8180 
8181 /*
8182  * get_func_expr - Parse back a FuncExpr node
8183  */
8184 static void
8186  bool showimplicit)
8187 {
8188  StringInfo buf = context->buf;
8189  Oid funcoid = expr->funcid;
8190  Oid argtypes[FUNC_MAX_ARGS];
8191  int nargs;
8192  List *argnames;
8193  bool use_variadic;
8194  ListCell *l;
8195 
8196  /*
8197  * If the function call came from an implicit coercion, then just show the
8198  * first argument --- unless caller wants to see implicit coercions.
8199  */
8200  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8201  {
8202  get_rule_expr_paren((Node *) linitial(expr->args), context,
8203  false, (Node *) expr);
8204  return;
8205  }
8206 
8207  /*
8208  * If the function call came from a cast, then show the first argument
8209  * plus an explicit cast operation.
8210  */
8211  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8213  {
8214  Node *arg = linitial(expr->args);
8215  Oid rettype = expr->funcresulttype;
8216  int32 coercedTypmod;
8217 
8218  /* Get the typmod if this is a length-coercion function */
8219  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8220 
8221  get_coercion_expr(arg, context,
8222  rettype, coercedTypmod,
8223  (Node *) expr);
8224 
8225  return;
8226  }
8227 
8228  /*
8229  * Normal function: display as proname(args). First we need to extract
8230  * the argument datatypes.
8231  */
8232  if (list_length(expr->args) > FUNC_MAX_ARGS)
8233  ereport(ERROR,
8234  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8235  errmsg("too many arguments")));
8236  nargs = 0;
8237  argnames = NIL;
8238  foreach(l, expr->args)
8239  {
8240  Node *arg = (Node *) lfirst(l);
8241 
8242  if (IsA(arg, NamedArgExpr))
8243  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8244  argtypes[nargs] = exprType(arg);
8245  nargs++;
8246  }
8247 
8248  appendStringInfo(buf, "%s(",
8249  generate_function_name(funcoid, nargs,
8250  argnames, argtypes,
8251  expr->funcvariadic,
8252  &use_variadic,
8253  context->special_exprkind));
8254  nargs = 0;
8255  foreach(l, expr->args)
8256  {
8257  if (nargs++ > 0)
8258  appendStringInfoString(buf, ", ");
8259  if (use_variadic && lnext(l) == NULL)
8260  appendStringInfoString(buf, "VARIADIC ");
8261  get_rule_expr((Node *) lfirst(l), context, true);
8262  }
8263  appendStringInfoChar(buf, ')');
8264 }
8265 
8266 /*
8267  * get_agg_expr - Parse back an Aggref node
8268  */
8269 static void
8271  Aggref *original_aggref)
8272 {
8273  StringInfo buf = context->buf;
8274  Oid argtypes[FUNC_MAX_ARGS];
8275  int nargs;
8276  bool use_variadic;
8277 
8278  /*
8279  * For a combining aggregate, we look up and deparse the corresponding
8280  * partial aggregate instead. This is necessary because our input
8281  * argument list has been replaced; the new argument list always has just
8282  * one element, which will point to a partial Aggref that supplies us with
8283  * transition states to combine.
8284  */
8285  if (aggref->aggcombine)
8286  {
8287  TargetEntry *tle = linitial(aggref->args);
8288 
8289  Assert(list_length(aggref->args) == 1);
8290  Assert(IsA(tle, TargetEntry));
8291  resolve_special_varno((Node *) tle->expr, context, original_aggref,
8293  return;
8294  }
8295 
8296  /* Mark as PARTIAL, if appropriate. */
8297  if (original_aggref->aggpartial)
8298  appendStringInfoString(buf, "PARTIAL ");
8299 
8300  /* Extract the argument types as seen by the parser */
8301  nargs = get_aggregate_argtypes(aggref, argtypes);
8302 
8303  /* Print the aggregate name, schema-qualified if needed */
8304  appendStringInfo(buf, "%s(%s",
8305  generate_function_name(aggref->aggfnoid, nargs,
8306  NIL, argtypes,
8307  aggref->aggvariadic,
8308  &use_variadic,
8309  context->special_exprkind),
8310  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
8311 
8312  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
8313  {
8314  /*
8315  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
8316  * worry about inserting VARIADIC. So we can just dump the direct
8317  * args as-is.
8318  */
8319  Assert(!aggref->aggvariadic);
8320  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
8321  Assert(aggref->aggorder != NIL);
8322  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
8323  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8324  }
8325  else
8326  {
8327  /* aggstar can be set only in zero-argument aggregates */
8328  if (aggref->aggstar)
8329  appendStringInfoChar(buf, '*');
8330  else
8331  {
8332  ListCell *l;
8333  int i;
8334 
8335  i = 0;
8336  foreach(l, aggref->args)
8337  {
8338  TargetEntry *tle = (TargetEntry *) lfirst(l);
8339  Node *arg = (Node *) tle->expr;
8340 
8341  Assert(!IsA(arg, NamedArgExpr));
8342  if (tle->resjunk)
8343  continue;
8344  if (i++ > 0)
8345  appendStringInfoString(buf, ", ");
8346  if (use_variadic && i == nargs)
8347  appendStringInfoString(buf, "VARIADIC ");
8348  get_rule_expr(arg, context, true);
8349  }
8350  }
8351 
8352  if (aggref->aggorder != NIL)
8353  {
8354  appendStringInfoString(buf, " ORDER BY ");
8355  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8356  }
8357  }
8358 
8359  if (aggref->aggfilter != NULL)
8360  {
8361  appendStringInfoString(buf, ") FILTER (WHERE ");
8362  get_rule_expr((Node *) aggref->aggfilter, context, false);
8363  }
8364 
8365  appendStringInfoChar(buf, ')');
8366 }
8367 
8368 /*
8369  * This is a helper function for get_agg_expr(). It's used when we deparse
8370  * a combining Aggref; resolve_special_varno locates the corresponding partial
8371  * Aggref and then calls this.
8372  */
8373 static void
8374 get_agg_combine_expr(Node *node, deparse_context *context, void *private)
8375 {
8376  Aggref *aggref;
8377  Aggref *original_aggref = private;
8378 
8379  if (!IsA(node, Aggref))
8380  elog(ERROR, "combining Aggref does not point to an Aggref");
8381 
8382  aggref = (Aggref *) node;
8383  get_agg_expr(aggref, context, original_aggref);
8384 }
8385 
8386 /*
8387  * get_windowfunc_expr - Parse back a WindowFunc node
8388  */
8389 static void
8391 {
8392  StringInfo buf = context->buf;
8393  Oid argtypes[FUNC_MAX_ARGS];
8394  int nargs;
8395  List *argnames;
8396  ListCell *l;
8397 
8398  if (list_length(wfunc->args) > FUNC_MAX_ARGS)
8399  ereport(ERROR,
8400  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8401  errmsg("too many arguments")));
8402  nargs = 0;
8403  argnames = NIL;
8404  foreach(l, wfunc->args)
8405  {
8406  Node *arg = (Node *) lfirst(l);
8407 
8408  if (IsA(arg, NamedArgExpr))
8409  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8410  argtypes[nargs] = exprType(arg);
8411  nargs++;
8412  }
8413 
8414  appendStringInfo(buf, "%s(",
8415  generate_function_name(wfunc->winfnoid, nargs,
8416  argnames, argtypes,
8417  false, NULL,
8418  context->special_exprkind));
8419  /* winstar can be set only in zero-argument aggregates */
8420  if (wfunc->winstar)
8421  appendStringInfoChar(buf, '*');
8422  else
8423  get_rule_expr((Node *) wfunc->args, context, true);
8424 
8425  if (wfunc->aggfilter != NULL)
8426  {
8427  appendStringInfoString(buf, ") FILTER (WHERE ");
8428  get_rule_expr((Node *) wfunc->aggfilter, context, false);
8429  }
8430 
8431  appendStringInfoString(buf, ") OVER ");
8432 
8433  foreach(l, context->windowClause)
8434  {
8435  WindowClause *wc = (WindowClause *) lfirst(l);
8436 
8437  if (wc->winref == wfunc->winref)
8438  {
8439  if (wc->name)
8441  else
8442  get_rule_windowspec(wc, context->windowTList, context);
8443  break;
8444  }
8445  }
8446  if (l == NULL)
8447  {
8448  if (context->windowClause)
8449  elog(ERROR, "could not find window clause for winref %u",
8450  wfunc->winref);
8451 
8452  /*
8453  * In EXPLAIN, we don't have window context information available, so
8454  * we have to settle for this:
8455  */
8456  appendStringInfoString(buf, "(?)");
8457  }
8458 }
8459 
8460 /* ----------
8461  * get_coercion_expr
8462  *
8463  * Make a string representation of a value coerced to a specific type
8464  * ----------
8465  */
8466 static void
8468  Oid resulttype, int32 resulttypmod,
8469  Node *parentNode)
8470 {
8471  StringInfo buf = context->buf;
8472 
8473  /*
8474  * Since parse_coerce.c doesn't immediately collapse application of
8475  * length-coercion functions to constants, what we'll typically see in
8476  * such cases is a Const with typmod -1 and a length-coercion function
8477  * right above it. Avoid generating redundant output. However, beware of
8478  * suppressing casts when the user actually wrote something like
8479  * 'foo'::text::char(3).
8480  *
8481  * Note: it might seem that we are missing the possibility of needing to
8482  * print a COLLATE clause for such a Const. However, a Const could only
8483  * have nondefault collation in a post-constant-folding tree, in which the
8484  * length coercion would have been folded too. See also the special
8485  * handling of CollateExpr in coerce_to_target_type(): any collation
8486  * marking will be above the coercion node, not below it.
8487  */
8488  if (arg && IsA(arg, Const) &&
8489  ((Const *) arg)->consttype == resulttype &&
8490  ((Const *) arg)->consttypmod == -1)
8491  {
8492  /* Show the constant without normal ::typename decoration */
8493  get_const_expr((Const *) arg, context, -1);
8494  }
8495  else
8496  {
8497  if (!PRETTY_PAREN(context))
8498  appendStringInfoChar(buf, '(');
8499  get_rule_expr_paren(arg, context, false, parentNode);
8500  if (!PRETTY_PAREN(context))
8501  appendStringInfoChar(buf, ')');
8502  }
8503  appendStringInfo(buf, "::%s",
8504  format_type_with_typemod(resulttype, resulttypmod));
8505 }
8506 
8507 /* ----------
8508  * get_const_expr
8509  *
8510  * Make a string representation of a Const
8511  *
8512  * showtype can be -1 to never show "::typename" decoration, or +1 to always
8513  * show it, or 0 to show it only if the constant wouldn't be assumed to be
8514  * the right type by default.
8515  *
8516  * If the Const's collation isn't default for its type, show that too.
8517  * We mustn't do this when showtype is -1 (since that means the caller will
8518  * print "::typename", and we can't put a COLLATE clause in between). It's
8519  * caller's responsibility that collation isn't missed in such cases.
8520  * ----------
8521  */
8522 static void
8523 get_const_expr(Const *constval, deparse_context *context, int showtype)
8524 {
8525  StringInfo buf = context->buf;
8526  Oid typoutput;
8527  bool typIsVarlena;
8528  char *extval;
8529  bool needlabel = false;
8530 
8531  if (constval->constisnull)
8532  {
8533  /*
8534  * Always label the type of a NULL constant to prevent misdecisions
8535  * about type when reparsing.
8536  */
8537  appendStringInfoString(buf, "NULL");
8538  if (showtype >= 0)
8539  {
8540  appendStringInfo(buf, "::%s",
8542  constval->consttypmod));
8543  get_const_collation(constval, context);
8544  }
8545  return;
8546  }
8547 
8548  getTypeOutputInfo(constval->consttype,
8549  &typoutput, &typIsVarlena);
8550 
8551  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
8552 
8553  switch (constval->consttype)
8554  {
8555  case INT4OID:
8556 
8557  /*
8558  * INT4 can be printed without any decoration, unless it is
8559  * negative; in that case print it as '-nnn'::integer to ensure
8560  * that the output will re-parse as a constant, not as a constant
8561  * plus operator. In most cases we could get away with printing
8562  * (-nnn) instead, because of the way that gram.y handles negative
8563  * literals; but that doesn't work for INT_MIN, and it doesn't
8564  * seem that much prettier anyway.
8565  */
8566  if (extval[0] != '-')
8567  appendStringInfoString(buf, extval);
8568  else
8569  {
8570  appendStringInfo(buf, "'%s'", extval);
8571  needlabel = true; /* we must attach a cast */
8572  }
8573  break;
8574 
8575  case NUMERICOID:
8576 
8577  /*
8578  * NUMERIC can be printed without quotes if it looks like a float
8579  * constant (not an integer, and not Infinity or NaN) and doesn't
8580  * have a leading sign (for the same reason as for INT4).
8581  */
8582  if (isdigit((unsigned char) extval[0]) &&
8583  strcspn(extval, "eE.") != strlen(extval))
8584  {
8585  appendStringInfoString(buf, extval);
8586  }
8587  else
8588  {
8589  appendStringInfo(buf, "'%s'", extval);
8590  needlabel = true; /* we must attach a cast */
8591  }
8592  break;
8593 
8594  case BITOID:
8595  case VARBITOID:
8596  appendStringInfo(buf, "B'%s'", extval);
8597  break;
8598 
8599  case BOOLOID:
8600  if (strcmp(extval, "t") == 0)
8601  appendStringInfoString(buf, "true");
8602  else
8603  appendStringInfoString(buf, "false");
8604  break;
8605 
8606  default:
8607  simple_quote_literal(buf, extval);
8608  break;
8609  }
8610 
8611  pfree(extval);
8612 
8613  if (showtype < 0)
8614  return;
8615 
8616  /*
8617  * For showtype == 0, append ::typename unless the constant will be
8618  * implicitly typed as the right type when it is read in.
8619  *
8620  * XXX this code has to be kept in sync with the behavior of the parser,
8621  * especially make_const.
8622  */
8623  switch (constval->consttype)
8624  {
8625  case BOOLOID:
8626  case UNKNOWNOID:
8627  /* These types can be left unlabeled */
8628  needlabel = false;
8629  break;
8630  case INT4OID:
8631  /* We determined above whether a label is needed */
8632  break;
8633  case NUMERICOID:
8634 
8635  /*
8636  * Float-looking constants will be typed as numeric, which we
8637  * checked above; but if there's a nondefault typmod we need to
8638  * show it.
8639  */
8640  needlabel |= (constval->consttypmod >= 0);
8641  break;
8642  default:
8643  needlabel = true;
8644  break;
8645  }
8646  if (needlabel || showtype > 0)
8647  appendStringInfo(buf, "::%s",
8649  constval->consttypmod));
8650 
8651  get_const_collation(constval, context);
8652 }
8653 
8654 /*
8655  * helper for get_const_expr: append COLLATE if needed
8656  */
8657 static void
8659 {
8660  StringInfo buf = context->buf;
8661 
8662  if (OidIsValid(constval->constcollid))
8663  {
8664  Oid typcollation = get_typcollation(constval->consttype);
8665 
8666  if (constval->constcollid != typcollation)
8667  {
8668  appendStringInfo(buf, " COLLATE %s",
8670  }
8671  }
8672 }
8673 
8674 /*
8675  * simple_quote_literal - Format a string as a SQL literal, append to buf
8676  */
8677 static void
8679 {
8680  const char *valptr;
8681 
8682  /*
8683  * We form the string literal according to the prevailing setting of
8684  * standard_conforming_strings; we never use E''. User is responsible for
8685  * making sure result is used correctly.
8686  */
8687  appendStringInfoChar(buf, '\'');
8688  for (valptr = val; *valptr; valptr++)
8689  {
8690  char ch = *valptr;
8691 
8693  appendStringInfoChar(buf, ch);
8694  appendStringInfoChar(buf, ch);
8695  }
8696  appendStringInfoChar(buf, '\'');
8697 }
8698 
8699 
8700 /* ----------
8701  * get_sublink_expr - Parse back a sublink
8702  * ----------
8703  */
8704 static void
8706 {
8707  StringInfo buf = context->buf;
8708  Query *query = (Query *) (sublink->subselect);
8709  char *opname = NULL;
8710  bool need_paren;
8711 
8712  if (sublink->subLinkType == ARRAY_SUBLINK)
8713  appendStringInfoString(buf, "ARRAY(");
8714  else
8715  appendStringInfoChar(buf, '(');
8716 
8717  /*
8718  * Note that we print the name of only the first operator, when there are
8719  * multiple combining operators. This is an approximation that could go
8720  * wrong in various scenarios (operators in different schemas, renamed
8721  * operators, etc) but there is not a whole lot we can do about it, since
8722  * the syntax allows only one operator to be shown.
8723  */
8724  if (sublink->testexpr)
8725  {
8726  if (IsA(sublink->testexpr, OpExpr))
8727  {
8728  /* single combining operator */
8729  OpExpr *opexpr = (OpExpr *) sublink->testexpr;
8730 
8731  get_rule_expr(linitial(opexpr->args), context, true);
8732  opname = generate_operator_name(opexpr->opno,
8733  exprType(linitial(opexpr->args)),
8734  exprType(lsecond(opexpr->args)));
8735  }
8736  else if (IsA(sublink->testexpr, BoolExpr))
8737  {
8738  /* multiple combining operators, = or <> cases */
8739  char *sep;
8740  ListCell *l;
8741 
8742  appendStringInfoChar(buf, '(');
8743  sep = "";
8744  foreach(l, ((BoolExpr *) sublink->testexpr)->args)
8745  {
8746  OpExpr *opexpr = (OpExpr *) lfirst(l);
8747 
8748  Assert(IsA(opexpr, OpExpr));
8749  appendStringInfoString(buf, sep);
8750  get_rule_expr(linitial(opexpr->args), context, true);
8751  if (!opname)
8752  opname = generate_operator_name(opexpr->opno,
8753  exprType(linitial(opexpr->args)),
8754  exprType(lsecond(opexpr->args)));
8755  sep = ", ";
8756  }
8757  appendStringInfoChar(buf, ')');
8758  }
8759  else if (IsA(sublink->testexpr, RowCompareExpr))
8760  {
8761  /* multiple combining operators, < <= > >= cases */
8762  RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
8763 
8764  appendStringInfoChar(buf, '(');
8765  get_rule_expr((Node *) rcexpr->largs, context, true);
8766  opname = generate_operator_name(linitial_oid(rcexpr->opnos),
8767  exprType(linitial(rcexpr->largs)),
8768  exprType(linitial(rcexpr->rargs)));
8769  appendStringInfoChar(buf, ')');
8770  }
8771  else
8772  elog(ERROR, "unrecognized testexpr type: %d",
8773  (int) nodeTag(sublink->testexpr));
8774  }
8775 
8776  need_paren = true;
8777 
8778  switch (sublink->subLinkType)
8779  {
8780  case EXISTS_SUBLINK:
8781  appendStringInfoString(buf, "EXISTS ");
8782  break;
8783 
8784  case ANY_SUBLINK:
8785  if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
8786  appendStringInfoString(buf, " IN ");
8787  else
8788  appendStringInfo(buf, " %s ANY ", opname);
8789  break;
8790 
8791  case ALL_SUBLINK:
8792  appendStringInfo(buf, " %s ALL ", opname);
8793  break;
8794 
8795  case ROWCOMPARE_SUBLINK:
8796  appendStringInfo(buf, " %s ", opname);
8797  break;
8798 
8799  case EXPR_SUBLINK:
8800  case MULTIEXPR_SUBLINK:
8801  case ARRAY_SUBLINK:
8802  need_paren = false;
8803  break;
8804 
8805  case CTE_SUBLINK: /* shouldn't occur in a SubLink */
8806  default:
8807  elog(ERROR, "unrecognized sublink type: %d",
8808  (int) sublink->subLinkType);
8809  break;
8810  }
8811 
8812  if (need_paren)
8813  appendStringInfoChar(buf, '(');
8814 
8815  get_query_def(query, buf, context->namespaces, NULL,
8816  context->prettyFlags, context->wrapColumn,
8817  context->indentLevel);
8818 
8819  if (need_paren)
8820  appendStringInfoString(buf, "))");
8821  else
8822  appendStringInfoChar(buf, ')');
8823 }
8824 
8825 
8826 /* ----------
8827  * get_from_clause - Parse back a FROM clause
8828  *
8829  * "prefix" is the keyword that denotes the start of the list of FROM
8830  * elements. It is FROM when used to parse back SELECT and UPDATE, but
8831  * is USING when parsing back DELETE.
8832  * ----------
8833  */
8834 static void
8835 get_from_clause(Query *query, const char *prefix, deparse_context *context)
8836 {
8837  StringInfo buf = context->buf;
8838  bool first = true;
8839  ListCell *l;
8840 
8841  /*
8842  * We use the query's jointree as a guide to what to print. However, we
8843  * must ignore auto-added RTEs that are marked not inFromCl. (These can
8844  * only appear at the top level of the jointree, so it's sufficient to
8845  * check here.) This check also ensures we ignore the rule pseudo-RTEs
8846  * for NEW and OLD.
8847  */
8848  foreach(l, query->jointree->fromlist)
8849  {
8850  Node *jtnode = (Node *) lfirst(l);
8851 
8852  if (IsA(jtnode, RangeTblRef))
8853  {
8854  int varno = ((RangeTblRef *) jtnode)->rtindex;
8855  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
8856 
8857  if (!rte->inFromCl)
8858  continue;
8859  }
8860 
8861  if (first)
8862  {
8863  appendContextKeyword(context, prefix,
8865  first = false;
8866 
8867  get_from_clause_item(jtnode, query, context);
8868  }
8869  else
8870  {
8871  StringInfoData itembuf;
8872 
8873  appendStringInfoString(buf, ", ");
8874 
8875  /*
8876  * Put the new FROM item's text into itembuf so we can decide
8877  * after we've got it whether or not it needs to go on a new line.
8878  */
8879  initStringInfo(&itembuf);
8880  context->buf = &itembuf;
8881 
8882  get_from_clause_item(jtnode, query, context);
8883 
8884  /* Restore context's output buffer */
8885  context->buf = buf;
8886 
8887  /* Consider line-wrapping if enabled */
8888  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
8889  {
8890  /* Does the new item start with a new line? */
8891  if (itembuf.len > 0 && itembuf.data[0] == '\n')
8892  {
8893  /* If so, we shouldn't add anything */
8894  /* instead, remove any trailing spaces currently in buf */
8896  }
8897  else
8898  {
8899  char *trailing_nl;
8900 
8901  /* Locate the start of the current line in the buffer */
8902  trailing_nl = strrchr(buf->data, '\n');
8903  if (trailing_nl == NULL)
8904  trailing_nl = buf->data;
8905  else
8906  trailing_nl++;
8907 
8908  /*
8909  * Add a newline, plus some indentation, if the new item
8910  * would cause an overflow.
8911  */
8912  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
8913  appendContextKeyword(context, "", -PRETTYINDENT_STD,
8916  }
8917  }
8918 
8919  /* Add the new item */
8920  appendStringInfoString(buf, itembuf.data);
8921 
8922  /* clean up */
8923  pfree(itembuf.data);
8924  }
8925  }
8926 }
8927 
8928 static void
8930 {
8931  StringInfo buf = context->buf;
8933 
8934  if (IsA(jtnode, RangeTblRef))
8935  {
8936  int varno = ((RangeTblRef *) jtnode)->rtindex;
8937  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
8938  char *refname = get_rtable_name(varno, context);
8939  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
8940  RangeTblFunction *rtfunc1 = NULL;
8941  bool printalias;
8942 
8943  if (rte->lateral)
8944  appendStringInfoString(buf, "LATERAL ");
8945 
8946  /* Print the FROM item proper */
8947  switch (rte->rtekind)
8948  {
8949  case RTE_RELATION:
8950  /* Normal relation RTE */
8951  appendStringInfo(buf, "%s%s",
8952  only_marker(rte),
8954  context->namespaces));
8955  break;
8956  case RTE_SUBQUERY:
8957  /* Subquery RTE */
8958  appendStringInfoChar(buf, '(');
8959  get_query_def(rte->subquery, buf, context->namespaces, NULL,
8960  context->prettyFlags, context->wrapColumn,
8961  context->indentLevel);
8962  appendStringInfoChar(buf, ')');
8963  break;
8964  case RTE_FUNCTION:
8965  /* Function RTE */
8966  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
8967 
8968  /*
8969  * Omit ROWS FROM() syntax for just one function, unless it
8970  * has both a coldeflist and WITH ORDINALITY. If it has both,
8971  * we must use ROWS FROM() syntax to avoid ambiguity about
8972  * whether the coldeflist includes the ordinality column.
8973  */
8974  if (list_length(rte->functions) == 1 &&
8975  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
8976  {
8977  get_rule_expr(rtfunc1->funcexpr, context, true);
8978  /* we'll print the coldeflist below, if it has one */
8979  }
8980  else
8981  {
8982  bool all_unnest;
8983  ListCell *lc;
8984 
8985  /*
8986  * If all the function calls in the list are to unnest,
8987  * and none need a coldeflist, then collapse the list back
8988  * down to UNNEST(args). (If we had more than one
8989  * built-in unnest function, this would get more
8990  * difficult.)
8991  *
8992  * XXX This is pretty ugly, since it makes not-terribly-
8993  * future-proof assumptions about what the parser would do
8994  * with the output; but the alternative is to emit our
8995  * nonstandard ROWS FROM() notation for what might have
8996  * been a perfectly spec-compliant multi-argument
8997  * UNNEST().
8998  */
8999  all_unnest = true;
9000  foreach(lc, rte->functions)
9001  {
9002  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9003 
9004  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9005  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9006  rtfunc->funccolnames != NIL)
9007  {
9008  all_unnest = false;
9009  break;
9010  }
9011  }
9012 
9013  if (all_unnest)
9014  {
9015  List *allargs = NIL;
9016 
9017  foreach(lc, rte->functions)
9018  {
9019  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9020  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9021 
9022  allargs = list_concat(allargs, list_copy(args));
9023  }
9024 
9025  appendStringInfoString(buf, "UNNEST(");
9026  get_rule_expr((Node *) allargs, context, true);
9027  appendStringInfoChar(buf, ')');
9028  }
9029  else
9030  {
9031  int funcno = 0;
9032 
9033  appendStringInfoString(buf, "ROWS FROM(");
9034  foreach(lc, rte->functions)
9035  {
9036  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9037 
9038  if (funcno > 0)
9039  appendStringInfoString(buf, ", ");
9040  get_rule_expr(rtfunc->funcexpr, context, true);
9041  if (rtfunc->funccolnames != NIL)
9042  {
9043  /* Reconstruct the column definition list */
9044  appendStringInfoString(buf, " AS ");
9046  NULL,
9047  context);
9048  }
9049  funcno++;
9050  }
9051  appendStringInfoChar(buf, ')');
9052  }
9053  /* prevent printing duplicate coldeflist below */
9054  rtfunc1 = NULL;
9055  }
9056  if (rte->funcordinality)
9057  appendStringInfoString(buf, " WITH ORDINALITY");
9058  break;
9059  case RTE_VALUES:
9060  /* Values list RTE */
9061  appendStringInfoChar(buf, '(');
9062  get_values_def(rte->values_lists, context);
9063  appendStringInfoChar(buf, ')');
9064  break;
9065  case RTE_CTE:
9067  break;
9068  default:
9069  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9070  break;
9071  }
9072 
9073  /* Print the relation alias, if needed */
9074  printalias = false;
9075  if (rte->alias != NULL)
9076  {
9077  /* Always print alias if user provided one */
9078  printalias = true;
9079  }
9080  else if (colinfo->printaliases)
9081  {
9082  /* Always print alias if we need to print column aliases */
9083  printalias = true;
9084  }
9085  else if (rte->rtekind == RTE_RELATION)
9086  {
9087  /*
9088  * No need to print alias if it's same as relation name (this
9089  * would normally be the case, but not if set_rtable_names had to
9090  * resolve a conflict).
9091  */
9092  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9093  printalias = true;
9094  }
9095  else if (rte->rtekind == RTE_FUNCTION)
9096  {
9097  /*
9098  * For a function RTE, always print alias. This covers possible
9099  * renaming of the function and/or instability of the
9100  * FigureColname rules for things that aren't simple functions.
9101  * Note we'd need to force it anyway for the columndef list case.
9102  */
9103  printalias = true;
9104  }
9105  else if (rte->rtekind == RTE_VALUES)
9106  {
9107  /* Alias is syntactically required for VALUES */
9108  printalias = true;
9109  }
9110  else if (rte->rtekind == RTE_CTE)
9111  {
9112  /*
9113  * No need to print alias if it's same as CTE name (this would
9114  * normally be the case, but not if set_rtable_names had to
9115  * resolve a conflict).
9116  */
9117  if (strcmp(refname, rte->ctename) != 0)
9118  printalias = true;
9119  }
9120  if (printalias)
9121  appendStringInfo(buf, " %s", quote_identifier(refname));
9122 
9123  /* Print the column definitions or aliases, if needed */
9124  if (rtfunc1 && rtfunc1->funccolnames != NIL)
9125  {
9126  /* Reconstruct the columndef list, which is also the aliases */
9127  get_from_clause_coldeflist(rtfunc1, colinfo, context);
9128  }
9129  else
9130  {
9131  /* Else print column aliases as needed */
9132  get_column_alias_list(colinfo, context);
9133  }
9134 
9135  /* Tablesample clause must go after any alias */
9136  if (rte->rtekind == RTE_RELATION && rte->tablesample)
9137  get_tablesample_def(rte->tablesample, context);
9138  }
9139  else if (IsA(jtnode, JoinExpr))
9140  {
9141  JoinExpr *j = (JoinExpr *) jtnode;
9142  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
9143  bool need_paren_on_right;
9144 
9145  need_paren_on_right = PRETTY_PAREN(context) &&
9146  !IsA(j->rarg, RangeTblRef) &&
9147  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
9148 
9149  if (!PRETTY_PAREN(context) || j->alias != NULL)
9150  appendStringInfoChar(buf, '(');
9151 
9152  get_from_clause_item(j->larg, query, context);
9153 
9154  switch (j->jointype)
9155  {
9156  case JOIN_INNER:
9157  if (j->quals)
9158  appendContextKeyword(context, " JOIN ",
9162  else
9163  appendContextKeyword(context, " CROSS JOIN ",
9167  break;
9168  case JOIN_LEFT:
9169  appendContextKeyword(context, " LEFT JOIN ",
9173  break;
9174  case JOIN_FULL:
9175  appendContextKeyword(context, " FULL JOIN ",
9179  break;
9180  case JOIN_RIGHT:
9181  appendContextKeyword(context, " RIGHT JOIN ",
9185  break;
9186  default:
9187  elog(ERROR, "unrecognized join type: %d",
9188  (int) j->jointype);
9189  }
9190 
9191  if (need_paren_on_right)
9192  appendStringInfoChar(buf, '(');
9193  get_from_clause_item(j->rarg, query, context);
9194  if (need_paren_on_right)
9195  appendStringInfoChar(buf, ')');
9196 
9197  if (j->usingClause)
9198  {
9199  ListCell *lc;
9200  bool first = true;
9201 
9202  appendStringInfoString(buf, " USING (");
9203  /* Use the assigned names, not what's in usingClause */
9204  foreach(lc, colinfo->usingNames)
9205  {
9206  char *colname = (char *) lfirst(lc);
9207 
9208  if (first)
9209  first = false;
9210  else
9211  appendStringInfoString(buf, ", ");
9213  }
9214  appendStringInfoChar(buf, ')');
9215  }
9216  else if (j->quals)
9217  {
9218  appendStringInfoString(buf, " ON ");
9219  if (!PRETTY_PAREN(context))
9220  appendStringInfoChar(buf, '(');
9221  get_rule_expr(j->quals, context, false);
9222  if (!PRETTY_PAREN(context))
9223  appendStringInfoChar(buf, ')');
9224  }
9225 
9226  if (!PRETTY_PAREN(context) || j->alias != NULL)
9227  appendStringInfoChar(buf, ')');
9228 
9229  /* Yes, it's correct to put alias after the right paren ... */
9230  if (j->alias != NULL)
9231  {
9232  appendStringInfo(buf, " %s",
9234  get_column_alias_list(colinfo, context);
9235  }
9236  }
9237  else
9238  elog(ERROR, "unrecognized node type: %d",
9239  (int) nodeTag(jtnode));
9240 }
9241 
9242 /*
9243  * get_column_alias_list - print column alias list for an RTE
9244  *
9245  * Caller must already have printed the relation's alias name.
9246  */
9247 static void
9249 {
9250  StringInfo buf = context->buf;
9251  int i;
9252  bool first = true;
9253 
9254  /* Don't print aliases if not needed */
9255  if (!colinfo->printaliases)
9256  return;
9257 
9258  for (i = 0; i < colinfo->num_new_cols; i++)
9259  {
9260  char *colname = colinfo->new_colnames[i];
9261 
9262  if (first)
9263  {
9264  appendStringInfoChar(buf, '(');
9265  first = false;
9266  }
9267  else
9268  appendStringInfoString(buf, ", ");
9270  }
9271  if (!first)
9272  appendStringInfoChar(buf, ')');
9273 }
9274 
9275 /*
9276  * get_from_clause_coldeflist - reproduce FROM clause coldeflist
9277  *
9278  * When printing a top-level coldeflist (which is syntactically also the
9279  * relation's column alias list), use column names from colinfo. But when
9280  * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
9281  * original coldeflist's names, which are available in rtfunc->funccolnames.
9282  * Pass NULL for colinfo to select the latter behavior.
9283  *
9284  * The coldeflist is appended immediately (no space) to buf. Caller is
9285  * responsible for ensuring that an alias or AS is present before it.
9286  */
9287 static void
9289  deparse_columns *colinfo,
9290  deparse_context *context)
9291 {
9292  StringInfo buf = context->buf;
9293  ListCell *l1;
9294  ListCell *l2;
9295  ListCell *l3;
9296  ListCell *l4;
9297  int i;
9298 
9299  appendStringInfoChar(buf, '(');
9300 
9301  /* there's no forfour(), so must chase one list the hard way */
9302  i = 0;
9303  l4 = list_head(rtfunc->funccolnames);
9304  forthree(l1, rtfunc->funccoltypes,
9305  l2, rtfunc->funccoltypmods,
9306  l3, rtfunc->funccolcollations)
9307  {
9308  Oid atttypid = lfirst_oid(l1);
9309  int32 atttypmod = lfirst_int(l2);
9310  Oid attcollation = lfirst_oid(l3);
9311  char *attname;
9312 
9313  if (colinfo)
9314  attname = colinfo->colnames[i];
9315  else
9316  attname = strVal(lfirst(l4));
9317 
9318  Assert(attname); /* shouldn't be any dropped columns here */
9319 
9320  if (i > 0)
9321  appendStringInfoString(buf, ", ");
9322  appendStringInfo(buf, "%s %s",
9323  quote_identifier(attname),
9324  format_type_with_typemod(atttypid, atttypmod));
9325  if (OidIsValid(attcollation) &&
9326  attcollation != get_typcollation(atttypid))
9327  appendStringInfo(buf, " COLLATE %s",
9328  generate_collation_name(attcollation));
9329 
9330  l4 = lnext(l4);
9331  i++;
9332  }
9333 
9334  appendStringInfoChar(buf, ')');
9335 }
9336 
9337 /*
9338  * get_tablesample_def - print a TableSampleClause
9339  */
9340 static void
9342 {
9343  StringInfo buf = context->buf;
9344  Oid argtypes[1];
9345  int nargs;
9346  ListCell *l;
9347 
9348  /*
9349  * We should qualify the handler's function name if it wouldn't be
9350  * resolved by lookup in the current search path.
9351  */
9352  argtypes[0] = INTERNALOID;
9353  appendStringInfo(buf, " TABLESAMPLE %s (",
9354  generate_function_name(tablesample->tsmhandler, 1,
9355  NIL, argtypes,
9356  false, NULL, EXPR_KIND_NONE));
9357 
9358  nargs = 0;
9359  foreach(l, tablesample->args)
9360  {
9361  if (nargs++ > 0)
9362  appendStringInfoString(buf, ", ");
9363  get_rule_expr((Node *) lfirst(l), context, false);
9364  }
9365  appendStringInfoChar(buf, ')');
9366 
9367  if (tablesample->repeatable != NULL)
9368  {
9369  appendStringInfoString(buf, " REPEATABLE (");
9370  get_rule_expr((Node *) tablesample->repeatable, context, false);
9371  appendStringInfoChar(buf, ')');
9372  }
9373 }
9374 
9375 /*
9376  * get_opclass_name - fetch name of an index operator class
9377  *
9378  * The opclass name is appended (after a space) to buf.
9379  *
9380  * Output is suppressed if the opclass is the default for the given
9381  * actual_datatype. (If you don't want this behavior, just pass
9382  * InvalidOid for actual_datatype.)
9383  */
9384 static void
9385 get_opclass_name(Oid opclass, Oid actual_datatype,
9386  StringInfo buf)
9387 {
9388  HeapTuple ht_opc;
9389  Form_pg_opclass opcrec;
9390  char *opcname;
9391  char *nspname;
9392 
9393  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
9394  if (!HeapTupleIsValid(ht_opc))
9395  elog(ERROR, "cache lookup failed for opclass %u", opclass);
9396  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
9397 
9398  if (!OidIsValid(actual_datatype) ||
9399  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
9400  {
9401  /* Okay, we need the opclass name. Do we need to qualify it? */
9402  opcname = NameStr(opcrec->opcname);
9403  if (OpclassIsVisible(opclass))
9404  appendStringInfo(buf, " %s", quote_identifier(opcname));
9405  else
9406  {
9407  nspname = get_namespace_name(opcrec->opcnamespace);
9408  appendStringInfo(buf, " %s.%s",
9409  quote_identifier(nspname),
9410  quote_identifier(opcname));
9411  }
9412  }
9413  ReleaseSysCache(ht_opc);
9414 }
9415 
9416 /*
9417  * processIndirection - take care of array and subfield assignment
9418  *
9419  * We strip any top-level FieldStore or assignment ArrayRef nodes that
9420  * appear in the input, and return the subexpression that's to be assigned.
9421  * If printit is true, we also print out the appropriate decoration for the
9422  * base column name (that the caller just printed).
9423  */
9424 static Node *
9425 processIndirection(Node *node, deparse_context *context, bool printit)
9426 {
9427  StringInfo buf = context->buf;
9428 
9429  for (;;)
9430  {
9431  if (node == NULL)
9432  break;
9433  if (IsA(node, FieldStore))
9434  {
9435  FieldStore *fstore = (FieldStore *) node;
9436  Oid typrelid;
9437  char *fieldname;
9438 
9439  /* lookup tuple type */
9440  typrelid = get_typ_typrelid(fstore->resulttype);
9441  if (!OidIsValid(typrelid))
9442  elog(ERROR, "argument type %s of FieldStore is not a tuple type",
9443  format_type_be(fstore->resulttype));
9444 
9445  /*
9446  * Print the field name. There should only be one target field in
9447  * stored rules. There could be more than that in executable
9448  * target lists, but this function cannot be used for that case.
9449  */
9450  Assert(list_length(fstore->fieldnums) == 1);
9451  fieldname = get_relid_attribute_name(typrelid,
9452  linitial_int(fstore->fieldnums));
9453  if (printit)
9454  appendStringInfo(buf, ".%s", quote_identifier(fieldname));
9455 
9456  /*
9457  * We ignore arg since it should be an uninteresting reference to
9458  * the target column or subcolumn.
9459  */
9460  node = (Node *) linitial(fstore->newvals);
9461  }
9462  else if (IsA(node, ArrayRef))
9463  {
9464  ArrayRef *aref = (ArrayRef *) node;
9465 
9466  if (aref->refassgnexpr == NULL)
9467  break;
9468  if (printit)
9469  printSubscripts(aref, context);
9470 
9471  /*
9472  * We ignore refexpr since it should be an uninteresting reference
9473  * to the target column or subcolumn.
9474  */
9475  node = (Node *) aref->refassgnexpr;
9476  }
9477  else
9478  break;
9479  }
9480 
9481  return node;
9482 }
9483 
9484 static void
9486 {
9487  StringInfo buf = context->buf;
9488  ListCell *lowlist_item;
9489  ListCell *uplist_item;
9490 
9491  lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
9492  foreach(uplist_item, aref->refupperindexpr)
9493  {
9494  appendStringInfoChar(buf, '[');
9495  if (lowlist_item)
9496  {
9497  /* If subexpression is NULL, get_rule_expr prints nothing */
9498  get_rule_expr((Node *) lfirst(lowlist_item), context, false);
9499  appendStringInfoChar(buf, ':');
9500  lowlist_item = lnext(lowlist_item);
9501  }
9502  /* If subexpression is NULL, get_rule_expr prints nothing */
9503  get_rule_expr((Node *) lfirst(uplist_item), context, false);
9504  appendStringInfoChar(buf, ']');
9505  }
9506 }
9507 
9508 /*
9509  * quote_identifier - Quote an identifier only if needed
9510  *
9511  * When quotes are needed, we palloc the required space; slightly
9512  * space-wasteful but well worth it for notational simplicity.
9513  */
9514 const char *
9515 quote_identifier(const char *ident)
9516 {
9517  /*
9518  * Can avoid quoting if ident starts with a lowercase letter or underscore
9519  * and contains only lowercase letters, digits, and underscores, *and* is
9520  * not any SQL keyword. Otherwise, supply quotes.
9521  */
9522  int nquotes = 0;
9523  bool safe;
9524  const char *ptr;
9525  char *result;
9526  char *optr;
9527 
9528  /*
9529  * would like to use <ctype.h> macros here, but they might yield unwanted
9530  * locale-specific results...
9531  */
9532  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
9533 
9534  for (ptr = ident; *ptr; ptr++)
9535  {
9536  char ch = *ptr;
9537 
9538  if ((ch >= 'a' && ch <= 'z') ||
9539  (ch >= '0' && ch <= '9') ||
9540  (ch == '_'))
9541  {
9542  /* okay */
9543  }
9544  else
9545  {
9546  safe = false;
9547  if (ch == '"')
9548  nquotes++;
9549  }
9550  }
9551 
9553  safe = false;
9554 
9555  if (safe)
9556  {
9557  /*
9558  * Check for keyword. We quote keywords except for unreserved ones.
9559  * (In some cases we could avoid quoting a col_name or type_func_name
9560  * keyword, but it seems much harder than it's worth to tell that.)
9561  *
9562  * Note: ScanKeywordLookup() does case-insensitive comparison, but
9563  * that's fine, since we already know we have all-lower-case.
9564  */
9565  const ScanKeyword *keyword = ScanKeywordLookup(ident,
9566  ScanKeywords,
9567  NumScanKeywords);
9568 
9569  if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
9570  safe = false;
9571  }
9572 
9573  if (safe)
9574  return ident; /* no change needed */
9575 
9576  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
9577 
9578  optr = result;
9579  *optr++ = '"';
9580  for (ptr = ident; *ptr; ptr++)
9581  {
9582  char ch = *ptr;
9583 
9584  if (ch == '"')
9585  *optr++ = '"';
9586  *optr++ = ch;
9587  }
9588  *optr++ = '"';
9589  *optr = '\0';
9590 
9591  return result;
9592 }
9593 
9594 /*
9595  * quote_qualified_identifier - Quote a possibly-qualified identifier
9596  *
9597  * Return a name of the form qualifier.ident, or just ident if qualifier
9598  * is NULL, quoting each component if necessary. The result is palloc'd.
9599  */
9600 char *
9601 quote_qualified_identifier(const char *qualifier,
9602  const char *ident)
9603 {
9605 
9606  initStringInfo(&buf);
9607  if (qualifier)
9608  appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
9610  return buf.data;
9611 }
9612 
9613 /*
9614  * get_relation_name
9615  * Get the unqualified name of a relation specified by OID
9616  *
9617  * This differs from the underlying get_rel_name() function in that it will
9618  * throw error instead of silently returning NULL if the OID is bad.
9619  */
9620 static char *
9622 {
9623  char *relname = get_rel_name(relid);
9624 
9625  if (!relname)
9626  elog(ERROR, "cache lookup failed for relation %u", relid);
9627  return relname;
9628 }
9629 
9630 /*
9631  * generate_relation_name
9632  * Compute the name to display for a relation specified by OID
9633  *
9634  * The result includes all necessary quoting and schema-prefixing.
9635  *
9636  * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
9637  * We will forcibly qualify the relation name if it equals any CTE name
9638  * visible in the namespace list.
9639  */
9640 static char *
9641 generate_relation_name(Oid relid, List *namespaces)
9642 {
9643  HeapTuple tp;
9644  Form_pg_class reltup;
9645  bool need_qual;
9646  ListCell *nslist;
9647  char *relname;
9648  char *nspname;
9649  char *result;
9650 
9651  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
9652  if (!HeapTupleIsValid(tp))
9653  elog(ERROR, "cache lookup failed for relation %u", relid);
9654  reltup = (Form_pg_class) GETSTRUCT(tp);
9655  relname = NameStr(reltup->relname);
9656 
9657  /* Check for conflicting CTE name */
9658  need_qual = false;
9659  foreach(nslist, namespaces)
9660  {
9661  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
9662  ListCell *ctlist;
9663 
9664  foreach(ctlist, dpns->ctes)
9665  {
9666  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
9667 
9668  if (strcmp(cte->ctename, relname) == 0)
9669  {
9670  need_qual = true;
9671  break;
9672  }
9673  }
9674  if (need_qual)
9675  break;
9676  }
9677 
9678  /* Otherwise, qualify the name if not visible in search path */
9679  if (!need_qual)
9680  need_qual = !RelationIsVisible(relid);
9681 
9682  if (need_qual)
9683  nspname = get_namespace_name(reltup->relnamespace);
9684  else
9685  nspname = NULL;
9686 
9687  result = quote_qualified_identifier(nspname, relname);
9688 
9689  ReleaseSysCache(tp);
9690 
9691  return result;
9692 }
9693 
9694 /*
9695  * generate_qualified_relation_name
9696  * Compute the name to display for a relation specified by OID
9697  *
9698  * As above, but unconditionally schema-qualify the name.
9699  */
9700 static char *
9702 {
9703  HeapTuple tp;
9704  Form_pg_class reltup;
9705  char *relname;
9706  char *nspname;
9707  char *result;
9708 
9709  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
9710  if (!HeapTupleIsValid(tp))
9711  elog(ERROR, "cache lookup failed for relation %u", relid);
9712  reltup = (Form_pg_class) GETSTRUCT(tp);
9713  relname = NameStr(reltup->relname);
9714 
9715  nspname = get_namespace_name(reltup->relnamespace);
9716  if (!nspname)
9717  elog(ERROR, "cache lookup failed for namespace %u",
9718  reltup->relnamespace);
9719 
9720  result = quote_qualified_identifier(nspname, relname);
9721 
9722  ReleaseSysCache(tp);
9723 
9724  return result;
9725 }
9726 
9727 /*
9728  * generate_function_name
9729  * Compute the name to display for a function specified by OID,
9730  * given that it is being called with the specified actual arg names and
9731  * types. (Those matter because of ambiguous-function resolution rules.)
9732  *
9733  * If we're dealing with a potentially variadic function (in practice, this
9734  * means a FuncExpr or Aggref, not some other way of calling a function), then
9735  * has_variadic must specify whether variadic arguments have been merged,
9736  * and *use_variadic_p will be set to indicate whether to print VARIADIC in
9737  * the output. For non-FuncExpr cases, has_variadic should be FALSE and
9738  * use_variadic_p can be NULL.
9739  *
9740  * The result includes all necessary quoting and schema-prefixing.
9741  */
9742 static char *
9743 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
9744  bool has_variadic, bool *use_variadic_p,
9745  ParseExprKind special_exprkind)
9746 {
9747  char *result;
9748  HeapTuple proctup;
9749  Form_pg_proc procform;
9750  char *proname;
9751  bool use_variadic;
9752  char *nspname;
9753  FuncDetailCode p_result;
9754  Oid p_funcid;
9755  Oid p_rettype;
9756  bool p_retset;
9757  int p_nvargs;
9758  Oid p_vatype;
9759  Oid *p_true_typeids;
9760  bool force_qualify = false;
9761 
9762  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
9763  if (!HeapTupleIsValid(proctup))
9764  elog(ERROR, "cache lookup failed for function %u", funcid);
9765  procform = (Form_pg_proc) GETSTRUCT(proctup);
9766  proname = NameStr(procform->proname);
9767 
9768  /*
9769  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
9770  * qualification in some special cases.
9771  */
9772  if (special_exprkind == EXPR_KIND_GROUP_BY)
9773  {
9774  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
9775  force_qualify = true;
9776  }
9777 
9778  /*
9779  * Determine whether VARIADIC should be printed. We must do this first
9780  * since it affects the lookup rules in func_get_detail().
9781  *
9782  * Currently, we always print VARIADIC if the function has a merged
9783  * variadic-array argument. Note that this is always the case for
9784  * functions taking a VARIADIC argument type other than VARIADIC ANY.
9785  *
9786  * In principle, if VARIADIC wasn't originally specified and the array
9787  * actual argument is deconstructable, we could print the array elements
9788  * separately and not print VARIADIC, thus more nearly reproducing the
9789  * original input. For the moment that seems like too much complication
9790  * for the benefit, and anyway we do not know whether VARIADIC was
9791  * originally specified if it's a non-ANY type.
9792  */
9793  if (use_variadic_p)
9794  {
9795  /* Parser should not have set funcvariadic unless fn is variadic */
9796  Assert(!has_variadic || OidIsValid(procform->provariadic));
9797  use_variadic = has_variadic;
9798  *use_variadic_p = use_variadic;
9799  }
9800  else
9801  {
9802  Assert(!has_variadic);
9803  use_variadic = false;
9804  }
9805 
9806  /*
9807  * The idea here is to schema-qualify only if the parser would fail to
9808  * resolve the correct function given the unqualified func name with the
9809  * specified argtypes and VARIADIC flag. But if we already decided to
9810  * force qualification, then we can skip the lookup and pretend we didn't
9811  * find it.
9812  */
9813  if (!force_qualify)
9814  p_result = func_get_detail(list_make1(makeString(proname)),
9815  NIL, argnames, nargs, argtypes,
9816  !use_variadic, true,
9817  &p_funcid, &p_rettype,
9818  &p_retset, &p_nvargs, &p_vatype,
9819  &p_true_typeids, NULL);
9820  else
9821  {
9822  p_result = FUNCDETAIL_NOTFOUND;
9823  p_funcid = InvalidOid;
9824  }
9825 
9826  if ((p_result == FUNCDETAIL_NORMAL ||
9827  p_result == FUNCDETAIL_AGGREGATE ||
9828  p_result == FUNCDETAIL_WINDOWFUNC) &&
9829  p_funcid == funcid)
9830  nspname = NULL;
9831  else
9832  nspname = get_namespace_name(procform->pronamespace);
9833 
9834  result = quote_qualified_identifier(nspname, proname);
9835 
9836  ReleaseSysCache(proctup);
9837 
9838  return result;
9839 }
9840 
9841 /*
9842  * generate_operator_name
9843  * Compute the name to display for an operator specified by OID,
9844  * given that it is being called with the specified actual arg types.
9845  * (Arg types matter because of ambiguous-operator resolution rules.
9846  * Pass InvalidOid for unused arg of a unary operator.)
9847  *
9848  * The result includes all necessary quoting and schema-prefixing,
9849  * plus the OPERATOR() decoration needed to use a qualified operator name
9850  * in an expression.
9851  */
9852 static char *
9853 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
9854 {
9856  HeapTuple opertup;
9857  Form_pg_operator operform;
9858  char *oprname;
9859  char *nspname;
9860  Operator p_result;
9861 
9862  initStringInfo(&buf);
9863 
9864  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
9865  if (!HeapTupleIsValid(opertup))
9866  elog(ERROR, "cache lookup failed for operator %u", operid);
9867  operform = (Form_pg_operator) GETSTRUCT(opertup);
9868  oprname = NameStr(operform->oprname);
9869 
9870  /*
9871  * The idea here is to schema-qualify only if the parser would fail to
9872  * resolve the correct operator given the unqualified op name with the
9873  * specified argtypes.
9874  */
9875  switch (operform->oprkind)
9876  {
9877  case 'b':
9878  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
9879  true, -1);
9880  break;
9881  case 'l':
9882  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
9883  true, -1);
9884  break;
9885  case 'r':
9886  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
9887  true, -1);
9888  break;
9889  default:
9890  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
9891  p_result = NULL; /* keep compiler quiet */
9892  break;
9893  }
9894 
9895  if (p_result != NULL && oprid(p_result) == operid)
9896  nspname = NULL;
9897  else
9898  {
9899  nspname = get_namespace_name(operform->oprnamespace);
9900  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
9901  }
9902 
9903  appendStringInfoString(&buf, oprname);
9904 
9905  if (nspname)
9906  appendStringInfoChar(&buf, ')');
9907 
9908  if (p_result != NULL)
9909  ReleaseSysCache(p_result);
9910 
9911  ReleaseSysCache(opertup);
9912 
9913  return buf.data;
9914 }
9915 
9916 /*
9917  * generate_collation_name
9918  * Compute the name to display for a collation specified by OID
9919  *
9920  * The result includes all necessary quoting and schema-prefixing.
9921  */
9922 char *
9924 {
9925  HeapTuple tp;
9926  Form_pg_collation colltup;
9927  char *collname;
9928  char *nspname;
9929  char *result;
9930 
9931  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
9932  if (!HeapTupleIsValid(tp))
9933  elog(ERROR, "cache lookup failed for collation %u", collid);
9934  colltup = (Form_pg_collation) GETSTRUCT(tp);
9935  collname = NameStr(colltup->collname);
9936 
9937  if (!CollationIsVisible(collid))
9938  nspname = get_namespace_name(colltup->collnamespace);
9939  else
9940  nspname = NULL;
9941 
9942  result = quote_qualified_identifier(nspname, collname);
9943 
9944  ReleaseSysCache(tp);
9945 
9946  return result;
9947 }
9948 
9949 /*
9950  * Given a C string, produce a TEXT datum.
9951  *
9952  * We assume that the input was palloc'd and may be freed.
9953  */
9954 static text *
9955 string_to_text(char *str)
9956 {
9957  text *result;
9958 
9959  result = cstring_to_text(str);
9960  pfree(str);
9961  return result;
9962 }
9963 
9964 /*
9965  * Generate a C string representing a relation's reloptions, or NULL if none.
9966  */
9967 static char *
9969 {
9970  char *result = NULL;
9971  HeapTuple tuple;
9972  Datum reloptions;
9973  bool isnull;
9974 
9975  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
9976  if (!HeapTupleIsValid(tuple))
9977  elog(ERROR, "cache lookup failed for relation %u", relid);
9978 
9979  reloptions = SysCacheGetAttr(RELOID, tuple,
9980  Anum_pg_class_reloptions, &isnull);
9981  if (!isnull)
9982  {
9984  Datum *options;
9985  int noptions;
9986  int i;
9987 
9988  initStringInfo(&buf);
9989 
9991  TEXTOID, -1, false, 'i',
9992  &options, NULL, &noptions);
9993 
9994  for (i = 0; i < noptions; i++)
9995  {
9996  char *option = TextDatumGetCString(options[i]);
9997  char *name;
9998  char *separator;
9999  char *value;
10000 
10001  /*
10002  * Each array element should have the form name=value. If the "="
10003  * is missing for some reason, treat it like an empty value.
10004  */
10005  name = option;
10006  separator = strchr(option, '=');
10007  if (separator)
10008  {
10009  *separator = '\0';
10010  value = separator + 1;
10011  }
10012  else
10013  value = "";
10014 
10015  if (i > 0)
10016  appendStringInfoString(&buf, ", ");
10017  appendStringInfo(&buf, "%s=", quote_identifier(name));
10018 
10019  /*
10020  * In general we need to quote the value; but to avoid unnecessary
10021  * clutter, do not quote if it is an identifier that would not
10022  * need quoting. (We could also allow numbers, but that is a bit
10023  * trickier than it looks --- for example, are leading zeroes
10024  * significant? We don't want to assume very much here about what
10025  * custom reloptions might mean.)
10026  */
10027  if (quote_identifier(value) == value)
10028  appendStringInfoString(&buf, value);
10029  else
10030  simple_quote_literal(&buf, value);
10031 
10032  pfree(option);
10033  }
10034 
10035  result = buf.data;
10036  }
10037 
10038  ReleaseSysCache(tuple);
10039 
10040  return result;
10041 }
Datum constvalue
Definition: primnodes.h:181
#define list_make2(x1, x2)
Definition: pg_list.h:134
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:824
Value * makeString(char *str)
Definition: value.c:53
List * rtable_columns
Definition: ruleutils.c:147
List * aggdistinct
Definition: primnodes.h:278
signed short int16
Definition: c.h:252
#define ConstraintOidIndexId
Definition: indexing.h:124
Oid funcresulttype
Definition: primnodes.h:425
Node * limitOffset
Definition: parsenodes.h:149
List * namespaces
Definition: ruleutils.c:105
char * refname
Definition: parsenodes.h:1096
#define NIL
Definition: pg_list.h:69
static void decompile_column_index_array(Datum column_index_array, Oid relId, StringInfo buf)
Definition: ruleutils.c:1677
List * rtable_names
Definition: ruleutils.c:146
Definition: c.h:473
#define SPI_OK_CONNECT
Definition: spi.h:47
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:9743
#define INDOPTION_NULLS_FIRST
Definition: pg_index.h:100
bool copiedOrder
Definition: parsenodes.h:1103
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
Expr * refassgnexpr
Definition: primnodes.h:385
#define FKCONSTR_MATCH_SIMPLE
Definition: parsenodes.h:1819
Query * getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
Definition: rewriteManip.c:921
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:9621
static struct @76 value
List * args
Definition: primnodes.h:1040
#define CONSTRAINT_FOREIGN
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:795
bool aggvariadic
Definition: primnodes.h:281
void * stringToNode(char *str)
Definition: read.c:38
List * args
Definition: primnodes.h:959
#define TRIGGER_FOR_DELETE(type)
Definition: pg_trigger.h:131
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4462
#define Anum_pg_depend_refobjsubid
Definition: pg_depend.h:73
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define TriggerOidIndexId
Definition: indexing.h:235
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6086
List * joinaliasvars
Definition: parsenodes.h:830
#define NAMEOID
Definition: pg_type.h:300
Index varlevelsup
Definition: primnodes.h:158
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:79
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1371
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2600
#define VARDATA(PTR)
Definition: postgres.h:305
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5330
List * sortClause
Definition: parsenodes.h:147
#define Anum_pg_constraint_confkey
static char * pg_get_triggerdef_worker(Oid trigid, bool pretty)
Definition: ruleutils.c:732
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:694
List * args
Definition: primnodes.h:317
List * content
Definition: parsenodes.h:1074
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7048
char * name
Definition: primnodes.h:1077
Definition: syscache.h:36
static const char * get_simple_binary_op_name(OpExpr *expr)
Definition: ruleutils.c:6737
List * nestParams
Definition: plannodes.h:616
#define HASH_CONTEXT
Definition: hsearch.h:93
ExprState xprstate
Definition: execnodes.h:766
List * args
Definition: primnodes.h:335
#define HASH_ELEM
Definition: hsearch.h:87
List * args
Definition: primnodes.h:432
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9515
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1243
int32 resulttypmod
Definition: primnodes.h:1148
static char * make_colname_unique(char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
Definition: ruleutils.c:3666
Alias * alias
Definition: parsenodes.h:862
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:772
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:986
#define PRETTYFLAG_INDENT
Definition: ruleutils.c:86
List * colnames
Definition: primnodes.h:42
MemoryContext hcxt
Definition: hsearch.h:78
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:6551
#define DatumGetInt32(X)
Definition: postgres.h:480
FromExpr * jointree
Definition: parsenodes.h:129
#define INTERNALlanguageId
Definition: pg_language.h:74
#define RelationGetDescr(relation)
Definition: rel.h:353
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:965
OnConflictExpr * onConflict
Definition: parsenodes.h:133
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
int SPI_connect(void)
Definition: spi.c:85
Oid oprid(Operator op)
Definition: parse_oper.c:243
const ScanKeyword * ScanKeywordLookup(const char *text, const ScanKeyword *keywords, int num_keywords)
Definition: keywords.c:64
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:270
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5210
Datum pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:618
List * initPlan
Definition: execnodes.h:1045
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
#define NUMERICOID
Definition: pg_type.h:542
#define FKCONSTR_ACTION_NOACTION
Definition: parsenodes.h:1810
#define Anum_pg_class_reloptions
Definition: pg_class.h:130
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1769
#define DatumGetObjectId(X)
Definition: postgres.h:508
char * pstrdup(const char *in)
Definition: mcxt.c:1168
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:547
#define FRAMEOPTION_START_VALUE
Definition: parsenodes.h:501
#define RelationRelationId
Definition: pg_class.h:29
#define DependReferenceIndexId
Definition: indexing.h:141
Oid resulttype
Definition: primnodes.h:785
#define FKCONSTR_ACTION_SETDEFAULT
Definition: parsenodes.h:1814
int SPI_finish(void)
Definition: spi.c:160
#define Anum_pg_trigger_tgqual
Definition: pg_trigger.h:91
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:89
Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:980
#define DependRelationId
Definition: pg_depend.h:29
int resultRelation
Definition: parsenodes.h:114
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4830
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5094
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Oid type
Definition: primnodes.h:1082
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:792
List * subPlan
Definition: execnodes.h:1047
Datum pg_get_viewdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:574
char * pg_get_indexdef_string(Oid indexrelid)
Definition: ruleutils.c:997
#define Anum_pg_proc_prosrc
Definition: pg_proc.h:115
const int NumScanKeywords
Definition: keywords.c:45
Index tleSortGroupRef
Definition: parsenodes.h:1004
Expr * arg
Definition: primnodes.h:764
static const char * query_getrulebyoid
Definition: ruleutils.c:289
static void set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
Definition: ruleutils.c:3187
#define Anum_pg_index_indclass
Definition: pg_index.h:89
#define AccessShareLock
Definition: lockdefs.h:36
static char * pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, bool attrsOnly, bool showTblSpc, int prettyFlags)
Definition: ruleutils.c:1019
#define INT4OID
Definition: pg_type.h:316
List * groupingSets
Definition: parsenodes.h:139
#define PRETTYINDENT_VAR
Definition: ruleutils.c:80
static char * pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
Definition: ruleutils.c:488
Size entrysize
Definition: hsearch.h:73
char * pg_get_indexdef_columns(Oid indexrelid, bool pretty)
Definition: ruleutils.c:1004
ParamKind paramkind
Definition: primnodes.h:229
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:8835
SPITupleTable * SPI_tuptable
Definition: spi.c:41
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:491
#define CONSTRAINT_EXCLUSION
#define VARBITOID
Definition: pg_type.h:534
#define strVal(v)
Definition: value.h:54
#define ClanguageId
Definition: pg_language.h:77
CoercionForm coercionformat
Definition: primnodes.h:1150
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ViewSelectRuleName
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:507
List * args
Definition: primnodes.h:276
#define TRIGGER_FOR_UPDATE(type)
Definition: pg_trigger.h:132
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
#define MemSet(start, val, len)
Definition: c.h:849
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5401
AttrNumber varattno
Definition: primnodes.h:153
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5268
Oid array_typeid
Definition: primnodes.h:925
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Expr * arg
Definition: primnodes.h:715
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define PROPARALLEL_RESTRICTED
Definition: pg_proc.h:5340
#define FRAMEOPTION_BETWEEN
Definition: parsenodes.h:489
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4079
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2872
#define PRETTY_INDENT(context)
Definition: ruleutils.c:93
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5617
#define UNRESERVED_KEYWORD
Definition: keywords.h:18
List * fromlist
Definition: primnodes.h:1383
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:548
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool * is_new_col
Definition: ruleutils.c:239
List * funccolnames
Definition: parsenodes.h:898
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:887
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:156
bool funcordinality
Definition: parsenodes.h:841
#define PROARGMODE_VARIADIC
Definition: pg_proc.h:5351
bool aggstar
Definition: primnodes.h:280
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple * vals
Definition: spi.h:27
List * rowMarks
Definition: parsenodes.h:152
Index winref
Definition: primnodes.h:337
char * resname
Definition: primnodes.h:1282
Node * utilityStmt
Definition: parsenodes.h:111
List * arg_names
Definition: primnodes.h:1079
static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
Definition: ruleutils.c:3934
Definition: primnodes.h:148
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:5672
#define CONSTRAINT_UNIQUE
#define FRAMEOPTION_START_UNBOUNDED_PRECEDING
Definition: parsenodes.h:490
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:8523
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:228
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:291
#define OidIsValid(objectId)
Definition: c.h:530
ParseExprKind
Definition: parse_node.h:32
#define Anum_pg_constraint_conbin
static void expand_colnames_array_to(deparse_columns *colinfo, int n)
Definition: ruleutils.c:3710
static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, deparse_columns *colinfo)
Definition: ruleutils.c:3734
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
int natts
Definition: tupdesc.h:73
List * values_lists
Definition: parsenodes.h:846
Node * quals
Definition: primnodes.h:1384
#define lsecond(l)
Definition: pg_list.h:114
uint64 SPI_processed
Definition: spi.c:39
#define PROARGMODE_INOUT
Definition: pg_proc.h:5350
LockClauseStrength strength
Definition: parsenodes.h:1122
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
bool hasDistinctOn
Definition: parsenodes.h:120
static text * string_to_text(char *str)
Definition: ruleutils.c:9955
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:9923
#define Anum_pg_proc_proconfig
Definition: pg_proc.h:117
#define PROARGMODE_OUT
Definition: pg_proc.h:5349
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:9853
char bool
Definition: c.h:199
signed int int32
Definition: c.h:253
List * windowClause
Definition: parsenodes.h:143
static void get_basic_select_query(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4703
List * targetList
Definition: parsenodes.h:131
Datum pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:723
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
Oid get_rel_tablespace(Oid relid)
Definition: lsyscache.c:1796
List * arbiterElems
Definition: primnodes.h:1402
bool hasRecursive
Definition: parsenodes.h:121
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:9641
static void get_setop_query(Node *setOp, Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4961
#define ARR_LBOUND(a)
Definition: array.h:277
Node * larg
Definition: primnodes.h:1363
GroupingSetKind kind
Definition: parsenodes.h:1073
char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
Definition: spi.c:866
static char * relname(char const *dir, char const *base)
Definition: zic.c:755
#define FUNC_MAX_ARGS
#define list_make1(x1)
Definition: pg_list.h:133
static void get_oper_expr(OpExpr *expr, deparse_context *context)
Definition: ruleutils.c:8124
#define NAMEDATALEN
#define linitial_int(l)
Definition: pg_list.h:111
#define CONSTRAINT_CHECK
#define CONSTRAINT_PRIMARY
#define DatumGetName(X)
Definition: postgres.h:593
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:384
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:2675
char * relname
Definition: primnodes.h:74
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:132
Oid consttype
Definition: primnodes.h:177
static void get_func_expr(FuncExpr *expr, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8185
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags, int wrapColumn)
Definition: ruleutils.c:4277
static void get_sublink_expr(SubLink *sublink, deparse_context *context)
Definition: ruleutils.c:8705
static text * pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
Definition: ruleutils.c:1772
Definition: dynahash.c:193
#define Anum_pg_proc_probin
Definition: pg_proc.h:116
static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
Definition: ruleutils.c:2956
CoercionForm funcformat
Definition: primnodes.h:429
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define TRIGGER_FOR_ROW(type)
Definition: pg_trigger.h:126
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2425
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:9341
void pfree(void *pointer)
Definition: mcxt.c:995
static void print_function_rettype(StringInfo buf, HeapTuple proctup)
Definition: ruleutils.c:2203
static void convert(const int32 val, char *const buf)
Definition: zic.c:1702
Var * paramval
Definition: plannodes.h:623
Datum pg_get_functiondef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1938
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1287
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
List * distinctClause
Definition: parsenodes.h:145
Oid funcid
Definition: primnodes.h:424
#define FRAMEOPTION_START_VALUE_FOLLOWING
Definition: parsenodes.h:498
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:972
static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
Definition: ruleutils.c:8390
struct PlanState * planstate
Definition: execnodes.h:767
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:2702
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5863
Expr * expr
Definition: execnodes.h:578
static void get_parameter(Param *param, deparse_context *context)
Definition: ruleutils.c:6671
List * usingNames
Definition: ruleutils.c:267
#define TRIGGER_FOR_AFTER(type)
Definition: pg_trigger.h:128
#define lfirst_int(lc)
Definition: pg_list.h:107
List * partitionClause
Definition: parsenodes.h:1097
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5331
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4530
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:8678
Oid vartype
Definition: primnodes.h:155
List * args
Definition: primnodes.h:1020
#define ARR_DIMS(a)
Definition: array.h:275
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:32
BoolExprType boolop
Definition: primnodes.h:537
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:602
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:523
#define PROARGMODE_TABLE
Definition: pg_proc.h:5352
Expr * arg
Definition: primnodes.h:1106
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:404
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:831
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:898
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:49
#define DatumGetByteaP(X)
Definition: fmgr.h:246
List * set_deparse_context_planstate(List *dpcontext, Node *planstate, List *ancestors)
Definition: ruleutils.c:2651
static bool is_input_argument(int nth, const char *argmodes)
Definition: ruleutils.c:2383
Oid constcollid
Definition: primnodes.h:179
static SPIPlanPtr plan_getrulebyoid
Definition: ruleutils.c:288
static char * pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
Definition: ruleutils.c:640
#define outerPlanState(node)
Definition: execnodes.h:1072
Datum pg_get_viewdef_name(PG_FUNCTION_ARGS)
Definition: ruleutils.c:599
Definition: c.h:488
#define INT2OID
Definition: pg_type.h:308
static void get_rule_expr_toplevel(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
Node * limitCount
Definition: parsenodes.h:150
Datum pg_get_function_arg_default(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2422
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:8658
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void * list_nth(const List *list, int n)
Definition: list.c:410
int * rightattnos
Definition: ruleutils.c:266
#define NoLock
Definition: lockdefs.h:34
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:625
static char * buf
Definition: pg_test_fsync.c:65
const ScanKeyword ScanKeywords[]
Definition: keywords.c:41
#define Anum_pg_proc_proargdefaults
Definition: pg_proc.h:113
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define PRETTY_PAREN(context)
Definition: ruleutils.c:92
List * refupperindexpr
Definition: primnodes.h:379
static const char * query_getviewrule
Definition: ruleutils.c:291
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
void check_stack_depth(void)
Definition: postgres.c:3095
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:6975
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:481
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
static void push_child_plan(deparse_namespace *dpns, PlanState *ps, deparse_namespace *save_dpns)
Definition: ruleutils.c:4009
List * reflowerindexpr
Definition: primnodes.h:381
List * deparse_context_for(const char *aliasname, Oid relid)
Definition: ruleutils.c:2558
Datum pg_get_function_result(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2179
List * aggorder
Definition: primnodes.h:277
#define FRAMEOPTION_END_CURRENT_ROW
Definition: parsenodes.h:495
Expr * arg
Definition: primnodes.h:1129
AttrNumber resno
Definition: primnodes.h:1281
#define FRAMEOPTION_START_VALUE_PRECEDING
Definition: parsenodes.h:496
#define CStringGetDatum(X)
Definition: postgres.h:586
#define DatumGetInt16(X)
Definition: postgres.h:452
char string[11]
Definition: preproc-type.c:46
#define DatumGetBool(X)
Definition: postgres.h:401
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:271
static void get_rule_windowspec(WindowClause *wc, List *targetList, deparse_context *context)
Definition: ruleutils.c:5300
#define FRAMEOPTION_END_UNBOUNDED_FOLLOWING
Definition: parsenodes.h:493
FuncDetailCode
Definition: parse_func.h:22
char * name
Definition: primnodes.h:454
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:9385
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:62
char * cursor_name
Definition: primnodes.h:1204
List * aggdirectargs
Definition: primnodes.h:275
Oid resulttype
Definition: primnodes.h:744
static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
Definition: ruleutils.c:3354
Oid winfnoid
Definition: primnodes.h:331
bool CollationIsVisible(Oid collid)
Definition: namespace.c:1980
#define RECORDOID
Definition: pg_type.h:668
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7029
Expr * arg
Definition: primnodes.h:784
List * elements
Definition: primnodes.h:928
#define TYPECACHE_GT_OPR
Definition: typcache.h:112
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
static SPIPlanPtr splan
Definition: regress.c:461
#define TRIGGER_FOR_BEFORE(type)
Definition: pg_trigger.h:127
Definition: type.h:83
int get_func_trftypes(HeapTuple procTup, Oid **p_trftypes)
Definition: funcapi.c:886
List * returningList
Definition: parsenodes.h:135
#define PROPARALLEL_SAFE
Definition: pg_proc.h:5339
#define FRAMEOPTION_START_CURRENT_ROW
Definition: parsenodes.h:494
#define lnext(lc)
Definition: pg_list.h:105
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5150
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PROARGMODE_IN
Definition: pg_proc.h:5348
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:329
static int print_function_arguments(StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults)
Definition: ruleutils.c:2241
#define PRETTYINDENT_STD
Definition: ruleutils.c:78
Datum array_ref(ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:3063
Definition: nodes.h:291
#define Anum_pg_constraint_conkey
List * newvals
Definition: primnodes.h:742
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5341
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3070
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:8467
#define FKCONSTR_ACTION_CASCADE
Definition: parsenodes.h:1812
#define FRAMEOPTION_NONDEFAULT
Definition: parsenodes.h:486
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:814
Definition: nodes.h:138
ParseExprKind special_exprkind
Definition: ruleutils.c:112
bool aggpartial
Definition: primnodes.h:284
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5332
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1399
static char ** options
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static char * flatten_reloptions(Oid relid)
Definition: ruleutils.c:9968
static char * pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags)
Definition: ruleutils.c:1345
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:9601
List * usingClause
Definition: primnodes.h:1365
Index varno
Definition: primnodes.h:151
Definition: nodes.h:137
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Datum pg_get_ruledef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:476
float float4
Definition: c.h:376
XmlExprOp op
Definition: primnodes.h:1076
Node * startOffset
Definition: parsenodes.h:1100
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
List * args
Definition: primnodes.h:882
#define FKCONSTR_MATCH_FULL
Definition: parsenodes.h:1817
Definition: c.h:462
Datum pg_get_expr_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1747
#define TextDatumGetCString(d)
Definition: builtins.h:807
CoercionForm coerceformat
Definition: primnodes.h:813
void * palloc0(Size size)
Definition: mcxt.c:923
Node * quals
Definition: primnodes.h:1366
Datum pg_get_ruledef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:465
BoolTestType booltesttype
Definition: primnodes.h:1130
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
uintptr_t Datum
Definition: postgres.h:374
CoercionForm convertformat
Definition: primnodes.h:835
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
static SPIPlanPtr plan_getviewrule
Definition: ruleutils.c:290
List * outer_tlist
Definition: ruleutils.c:157
int * leftattnos
Definition: ruleutils.c:265
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5812
Datum pg_get_viewdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:562
#define DatumGetChar(X)
Definition: postgres.h:417
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1152
char * pg_get_constraintdef_command(Oid constraintId)
Definition: ruleutils.c:1336
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
char * conditionname
Definition: parsenodes.h:2618
Size keysize
Definition: hsearch.h:72
Oid resulttype
Definition: primnodes.h:765
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1807
#define TRIGGER_FOR_TRUNCATE(type)
Definition: pg_trigger.h:133
unsigned int Index
Definition: c.h:361
TupleDesc tupdesc
Definition: spi.h:26
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
TupleDesc rd_att
Definition: rel.h:84
NullTestType nulltesttype
Definition: primnodes.h:1107
int32 typmod
Definition: primnodes.h:1083
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6171
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
Definition: ruleutils.c:6763
Plan * plan
Definition: execnodes.h:1027
#define SPI_OK_SELECT
Definition: spi.h:51
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define InvalidOid
Definition: postgres_ext.h:36
List * funccoltypmods
Definition: parsenodes.h:900
Oid aggfnoid
Definition: primnodes.h:270
#define INTERNALOID
Definition: pg_type.h:686
List * named_args
Definition: primnodes.h:1078
List * windowTList
Definition: ruleutils.c:107
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2749
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:82
Datum pg_get_serial_sequence(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1845
bool quote_all_identifiers
Definition: ruleutils.c:294
#define INNER_VAR
Definition: primnodes.h:138
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:8374
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:3861
CmdType commandType
Definition: parsenodes.h:103
List * args
Definition: primnodes.h:1080
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
#define Anum_pg_index_indpred
Definition: pg_index.h:92
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
List * using_names
Definition: ruleutils.c:151
#define BITOID
Definition: pg_type.h:530
List * lcons(void *datum, List *list)
Definition: list.c:259
List * funccolcollations
Definition: parsenodes.h:901
#define Max(x, y)
Definition: c.h:792
PGDLLIMPORT bool standard_conforming_strings
static void printSubscripts(ArrayRef *aref, deparse_context *context)
Definition: ruleutils.c:9485
#define makeNode(_type_)
Definition: nodes.h:539
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:2526
text * cstring_to_text(const char *s)
Definition: varlena.c:150
char * plan_name
Definition: primnodes.h:666
Node * rarg
Definition: primnodes.h:1364
FormData_pg_constraint * Form_pg_constraint
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4026
Expr * arg
Definition: primnodes.h:453
Alias * alias
Definition: primnodes.h:1367
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define FRAMEOPTION_RANGE
Definition: parsenodes.h:487
JoinType jointype
Definition: primnodes.h:1361
#define Assert(condition)
Definition: c.h:667
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7080
#define lfirst(lc)
Definition: pg_list.h:106
#define Anum_pg_trigger_tgargs
Definition: pg_trigger.h:90
#define StrNCpy(dst, src, len)
Definition: c.h:822
char * aliasname
Definition: primnodes.h:41
#define FRAMEOPTION_END_VALUE_FOLLOWING
Definition: parsenodes.h:499
char * map_xml_name_to_sql_identifier(char *name)
Definition: xml.c:1913
List * functions
Definition: parsenodes.h:840
static char * get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
Definition: ruleutils.c:5908
List * windowClause
Definition: ruleutils.c:106
#define INDOPTION_DESC
Definition: pg_index.h:99
Expr * aggfilter
Definition: primnodes.h:336
Datum pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2154
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:89
int16 category
Definition: keywords.h:28
Expr * expr
Definition: primnodes.h:1280
#define TriggerRelationId
Definition: pg_trigger.h:34
XmlOptionType xmloption
Definition: primnodes.h:1081
int paramid
Definition: primnodes.h:230
Datum pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
Definition: ruleutils.c:586
PlanState * outer_planstate
Definition: ruleutils.c:155
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:2499
#define TRIGGER_FOR_INSERT(type)
Definition: pg_trigger.h:130
#define linitial_oid(l)
Definition: pg_list.h:112
Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1320
Node * endOffset
Definition: parsenodes.h:1101
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition: lsyscache.c:903
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static Node * processIndirection(Node *node, deparse_context *context, bool printit)
Definition: ruleutils.c:9425
#define only_marker(rte)
Definition: ruleutils.c:455
Oid row_typeid
Definition: primnodes.h:960
static int list_length(const List *l)
Definition: pg_list.h:89
Datum pg_get_indexdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:967
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:740
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:70
Expr * arg
Definition: primnodes.h:849
bool aggcombine
Definition: primnodes.h:283
Expr * aggfilter
Definition: primnodes.h:279
SetOperation op
Definition: parsenodes.h:1348
#define SPI_OK_FINISH
Definition: spi.h:48
Index ctelevelsup
Definition: parsenodes.h:853
#define FRAMEOPTION_ROWS
Definition: parsenodes.h:488
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1123
List * parParam
Definition: primnodes.h:682
bool amcanorder
Definition: amapi.h:124
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
#define BOOLOID
Definition: pg_type.h:288
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:470
#define FRAMEOPTION_END_VALUE_PRECEDING
Definition: parsenodes.h:497
#define ARR_NDIM(a)
Definition: array.h:271
List * args
Definition: primnodes.h:538
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1024
#define UNKNOWNOID
Definition: pg_type.h:423
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1257
const char * name
Definition: encode.c:521
PlanState * planstate
Definition: ruleutils.c:153
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:2852
#define InvalidAttrNumber
Definition: attnum.h:23
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4344
#define nodeTag(nodeptr)
Definition: nodes.h:496
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4417
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:2915
List * targetlist
Definition: plannodes.h:121
#define PRETTYFLAG_PAREN
Definition: ruleutils.c:85
Datum pg_get_function_arguments(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2128
int32 consttypmod
Definition: primnodes.h:178
Datum pg_get_expr(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1717
#define DatumGetPointer(X)
Definition: postgres.h:557
CoercionForm coerceformat
Definition: primnodes.h:788
#define Anum_pg_index_indcollation
Definition: pg_index.h:88
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:8270
RTEKind rtekind
Definition: parsenodes.h:791
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9248
Datum pg_get_constraintdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1308
Node * arbiterWhere
Definition: primnodes.h:1404
List * orderClause
Definition: parsenodes.h:1098
char * text_to_cstring(const text *t)
Definition: varlena.c:183
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
Datum pg_get_triggerdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:715
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2525
static char * generate_qualified_relation_name(Oid relid)
Definition: ruleutils.c:9701
static void set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
Definition: ruleutils.c:3022
#define Int32GetDatum(X)
Definition: postgres.h:487
char * ctename
Definition: parsenodes.h:852
List * cteList
Definition: parsenodes.h:126
Node * setOperations
Definition: parsenodes.h:154
e
Definition: preproc-init.c:82
Query * subquery
Definition: parsenodes.h:809
List * groupClause
Definition: parsenodes.h:137
List * index_tlist
Definition: ruleutils.c:159
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:2048
static bool colname_is_unique(char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
Definition: ruleutils.c:3612
void * palloc(Size size)
Definition: mcxt.c:894
StringInfo buf
Definition: ruleutils.c:104
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
bool RelationIsVisible(Oid relid)
Definition: namespace.c:696
bool hasSubLinks
Definition: parsenodes.h:119
static void get_special_variable(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:6065
List * inner_tlist
Definition: ruleutils.c:158
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1434
List * fieldnums
Definition: primnodes.h:743
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4056
void list_free(List *list)
Definition: list.c:1133
int i
bool hasForUpdate
Definition: parsenodes.h:123
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define TYPECACHE_LT_OPR
Definition: typcache.h:111
int count_nonjunk_tlist_entries(List *tlist)
Definition: tlist.c:170
List * funccoltypes
Definition: parsenodes.h:899
List * onConflictSet
Definition: primnodes.h:1408
#define NameStr(name)
Definition: c.h:494
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
static void print_function_trftypes(StringInfo buf, HeapTuple proctup)
Definition: ruleutils.c:2395
void * arg
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define FKCONSTR_ACTION_RESTRICT
Definition: parsenodes.h:1811
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:502
#define lthird(l)
Definition: pg_list.h:118
Oid get_constraint_index(Oid constraintId)
Definition: pg_depend.c:621
bool useHashTable
Definition: primnodes.h:673
List * parentUsing
Definition: ruleutils.c:245
Definition: c.h:434
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
MinMaxOp op
Definition: primnodes.h:1039
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:4647
char aggkind
Definition: primnodes.h:285
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
Definition: ruleutils.c:4095
int32 resulttypmod
Definition: primnodes.h:766
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define ConstraintRelationId
Definition: pg_constraint.h:29
Expr * arg
Definition: primnodes.h:881
Oid opno
Definition: primnodes.h:471
int32 resulttypmod
Definition: primnodes.h:810
#define elog
Definition: elog.h:218
#define CONSTRAINT_TRIGGER
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9288
Alias * eref
Definition: parsenodes.h:863
Expr * result
Definition: primnodes.h:894
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
List * args
Definition: primnodes.h:477
#define innerPlanState(node)
Definition: execnodes.h:1071
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:375
Node * havingQual
Definition: parsenodes.h:141
CoercionForm relabelformat
Definition: primnodes.h:768
Expr * defresult
Definition: primnodes.h:883
Expr * expr
Definition: primnodes.h:893
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
CoercionForm row_format
Definition: primnodes.h:971
#define INDEX_VAR
Definition: primnodes.h:140
NameData * Name
Definition: c.h:492
CoercionForm
Definition: primnodes.h:411
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1761
#define RELKIND_RELATION
Definition: pg_class.h:155
#define FKCONSTR_ACTION_SETNULL
Definition: parsenodes.h:1813
Node * onConflictWhere
Definition: primnodes.h:1409
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
static size_t noptions
#define RELKIND_SEQUENCE
Definition: pg_class.h:157
int rtindex
Definition: primnodes.h:1368
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
#define GetCTETargetList(cte)
Definition: parsenodes.h:1198
struct TableSampleClause * tablesample
Definition: parsenodes.h:804
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define FKCONSTR_MATCH_PARTIAL
Definition: parsenodes.h:1818
int16 AttrNumber
Definition: attnum.h:21
List * deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
Definition: ruleutils.c:2600
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:3915
#define OUTER_VAR
Definition: primnodes.h:139
long val
Definition: informix.c:689
char ** new_colnames
Definition: ruleutils.c:238
#define Anum_pg_constraint_conexclop
#define PG_RETURN_NULL()
Definition: fmgr.h:289
#define PG_RETURN_NAME(x)
Definition: fmgr.h:307
#define FRAMEOPTION_END_VALUE
Definition: parsenodes.h:503
bool constisnull
Definition: primnodes.h:182
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * aliascolnames
Definition: parsenodes.h:1183
bool funcvariadic
Definition: primnodes.h:427
#define Anum_pg_index_indoption
Definition: pg_index.h:90
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:8929
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
List * list_delete_first(List *list)
Definition: list.c:666
Datum pg_get_userbyid(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1807
Expr * refexpr
Definition: primnodes.h:383
char * payload
Definition: parsenodes.h:2619
bool winstar
Definition: primnodes.h:338
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1277
#define TRIGGER_FOR_INSTEAD(type)
Definition: pg_trigger.h:129
Definition: nodes.h:139
AttrNumber fieldnum
Definition: primnodes.h:716
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1037
BoolExprType
Definition: primnodes.h:529
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:606
int32 vartypmod
Definition: primnodes.h:156
#define DatumGetArrayTypeP(X)
Definition: array.h:242
char ** colnames
Definition: ruleutils.c:221
List * args
Definition: primnodes.h:683