PostgreSQL Source Code  git master
ruleutils.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * ruleutils.c
4  * Functions to convert stored expressions/querytrees back to
5  * source text
6  *
7  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/utils/adt/ruleutils.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 
22 #include "access/amapi.h"
23 #include "access/htup_details.h"
24 #include "access/relation.h"
25 #include "access/table.h"
26 #include "catalog/pg_aggregate.h"
27 #include "catalog/pg_am.h"
28 #include "catalog/pg_authid.h"
29 #include "catalog/pg_collation.h"
30 #include "catalog/pg_constraint.h"
31 #include "catalog/pg_depend.h"
32 #include "catalog/pg_language.h"
33 #include "catalog/pg_opclass.h"
34 #include "catalog/pg_operator.h"
36 #include "catalog/pg_proc.h"
38 #include "catalog/pg_trigger.h"
39 #include "catalog/pg_type.h"
40 #include "commands/defrem.h"
41 #include "commands/tablespace.h"
42 #include "common/keywords.h"
43 #include "executor/spi.h"
44 #include "funcapi.h"
45 #include "mb/pg_wchar.h"
46 #include "miscadmin.h"
47 #include "nodes/makefuncs.h"
48 #include "nodes/nodeFuncs.h"
49 #include "nodes/pathnodes.h"
50 #include "optimizer/optimizer.h"
51 #include "parser/parse_agg.h"
52 #include "parser/parse_func.h"
53 #include "parser/parse_node.h"
54 #include "parser/parse_oper.h"
55 #include "parser/parse_relation.h"
56 #include "parser/parser.h"
57 #include "parser/parsetree.h"
58 #include "rewrite/rewriteHandler.h"
59 #include "rewrite/rewriteManip.h"
60 #include "rewrite/rewriteSupport.h"
61 #include "utils/array.h"
62 #include "utils/builtins.h"
63 #include "utils/fmgroids.h"
64 #include "utils/guc.h"
65 #include "utils/hsearch.h"
66 #include "utils/lsyscache.h"
67 #include "utils/partcache.h"
68 #include "utils/rel.h"
69 #include "utils/ruleutils.h"
70 #include "utils/snapmgr.h"
71 #include "utils/syscache.h"
72 #include "utils/typcache.h"
73 #include "utils/varlena.h"
74 #include "utils/xml.h"
75 
76 /* ----------
77  * Pretty formatting constants
78  * ----------
79  */
80 
81 /* Indent counts */
82 #define PRETTYINDENT_STD 8
83 #define PRETTYINDENT_JOIN 4
84 #define PRETTYINDENT_VAR 4
85 
86 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
87 
88 /* Pretty flags */
89 #define PRETTYFLAG_PAREN 0x0001
90 #define PRETTYFLAG_INDENT 0x0002
91 #define PRETTYFLAG_SCHEMA 0x0004
92 
93 /* Standard conversion of a "bool pretty" option to detailed flags */
94 #define GET_PRETTY_FLAGS(pretty) \
95  ((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
96  : PRETTYFLAG_INDENT)
97 
98 /* Default line length for pretty-print wrapping: 0 means wrap always */
99 #define WRAP_COLUMN_DEFAULT 0
100 
101 /* macros to test if pretty action needed */
102 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
103 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
104 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
105 
106 
107 /* ----------
108  * Local data types
109  * ----------
110  */
111 
112 /* Context info needed for invoking a recursive querytree display routine */
113 typedef struct
114 {
115  StringInfo buf; /* output buffer to append to */
116  List *namespaces; /* List of deparse_namespace nodes */
117  List *windowClause; /* Current query level's WINDOW clause */
118  List *windowTList; /* targetlist for resolving WINDOW clause */
119  int prettyFlags; /* enabling of pretty-print functions */
120  int wrapColumn; /* max line length, or -1 for no limit */
121  int indentLevel; /* current indent level for pretty-print */
122  bool varprefix; /* true to print prefixes on Vars */
123  ParseExprKind special_exprkind; /* set only for exprkinds needing special
124  * handling */
125  Bitmapset *appendparents; /* if not null, map child Vars of these relids
126  * back to the parent rel */
128 
129 /*
130  * Each level of query context around a subtree needs a level of Var namespace.
131  * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
132  * the current context's namespaces list.
133  *
134  * rtable is the list of actual RTEs from the Query or PlannedStmt.
135  * rtable_names holds the alias name to be used for each RTE (either a C
136  * string, or NULL for nameless RTEs such as unnamed joins).
137  * rtable_columns holds the column alias names to be used for each RTE.
138  *
139  * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
140  * in the PlannedStmt case).
141  * ctes is a list of CommonTableExpr nodes (only used in the Query case).
142  * appendrels, if not null (it's only used in the PlannedStmt case), is an
143  * array of AppendRelInfo nodes, indexed by child relid. We use that to map
144  * child-table Vars to their inheritance parents.
145  *
146  * In some cases we need to make names of merged JOIN USING columns unique
147  * across the whole query, not only per-RTE. If so, unique_using is true
148  * and using_names is a list of C strings representing names already assigned
149  * to USING columns.
150  *
151  * When deparsing plan trees, there is always just a single item in the
152  * deparse_namespace list (since a plan tree never contains Vars with
153  * varlevelsup > 0). We store the Plan node that is the immediate
154  * parent of the expression to be deparsed, as well as a list of that
155  * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
156  * as well as their targetlists, and the index tlist if the current plan node
157  * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
158  * from the current Plan node, but it seems notationally clearer to set them
159  * up as separate fields.)
160  */
161 typedef struct
162 {
163  List *rtable; /* List of RangeTblEntry nodes */
164  List *rtable_names; /* Parallel list of names for RTEs */
165  List *rtable_columns; /* Parallel list of deparse_columns structs */
166  List *subplans; /* List of Plan trees for SubPlans */
167  List *ctes; /* List of CommonTableExpr nodes */
168  AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
169  /* Workspace for column alias assignment: */
170  bool unique_using; /* Are we making USING names globally unique */
171  List *using_names; /* List of assigned names for USING columns */
172  /* Remaining fields are used only when deparsing a Plan tree: */
173  Plan *plan; /* immediate parent of current expression */
174  List *ancestors; /* ancestors of plan */
175  Plan *outer_plan; /* outer subnode, or NULL if none */
176  Plan *inner_plan; /* inner subnode, or NULL if none */
177  List *outer_tlist; /* referent for OUTER_VAR Vars */
178  List *inner_tlist; /* referent for INNER_VAR Vars */
179  List *index_tlist; /* referent for INDEX_VAR Vars */
180  /* Special namespace representing a function signature: */
181  char *funcname;
182  int numargs;
183  char **argnames;
185 
186 /*
187  * Per-relation data about column alias names.
188  *
189  * Selecting aliases is unreasonably complicated because of the need to dump
190  * rules/views whose underlying tables may have had columns added, deleted, or
191  * renamed since the query was parsed. We must nonetheless print the rule/view
192  * in a form that can be reloaded and will produce the same results as before.
193  *
194  * For each RTE used in the query, we must assign column aliases that are
195  * unique within that RTE. SQL does not require this of the original query,
196  * but due to factors such as *-expansion we need to be able to uniquely
197  * reference every column in a decompiled query. As long as we qualify all
198  * column references, per-RTE uniqueness is sufficient for that.
199  *
200  * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
201  * since they just inherit column names from their input RTEs, and we can't
202  * rename the columns at the join level. Most of the time this isn't an issue
203  * because we don't need to reference the join's output columns as such; we
204  * can reference the input columns instead. That approach can fail for merged
205  * JOIN USING columns, however, so when we have one of those in an unnamed
206  * join, we have to make that column's alias globally unique across the whole
207  * query to ensure it can be referenced unambiguously.
208  *
209  * Another problem is that a JOIN USING clause requires the columns to be
210  * merged to have the same aliases in both input RTEs, and that no other
211  * columns in those RTEs or their children conflict with the USING names.
212  * To handle that, we do USING-column alias assignment in a recursive
213  * traversal of the query's jointree. When descending through a JOIN with
214  * USING, we preassign the USING column names to the child columns, overriding
215  * other rules for column alias assignment. We also mark each RTE with a list
216  * of all USING column names selected for joins containing that RTE, so that
217  * when we assign other columns' aliases later, we can avoid conflicts.
218  *
219  * Another problem is that if a JOIN's input tables have had columns added or
220  * deleted since the query was parsed, we must generate a column alias list
221  * for the join that matches the current set of input columns --- otherwise, a
222  * change in the number of columns in the left input would throw off matching
223  * of aliases to columns of the right input. Thus, positions in the printable
224  * column alias list are not necessarily one-for-one with varattnos of the
225  * JOIN, so we need a separate new_colnames[] array for printing purposes.
226  */
227 typedef struct
228 {
229  /*
230  * colnames is an array containing column aliases to use for columns that
231  * existed when the query was parsed. Dropped columns have NULL entries.
232  * This array can be directly indexed by varattno to get a Var's name.
233  *
234  * Non-NULL entries are guaranteed unique within the RTE, *except* when
235  * this is for an unnamed JOIN RTE. In that case we merely copy up names
236  * from the two input RTEs.
237  *
238  * During the recursive descent in set_using_names(), forcible assignment
239  * of a child RTE's column name is represented by pre-setting that element
240  * of the child's colnames array. So at that stage, NULL entries in this
241  * array just mean that no name has been preassigned, not necessarily that
242  * the column is dropped.
243  */
244  int num_cols; /* length of colnames[] array */
245  char **colnames; /* array of C strings and NULLs */
246 
247  /*
248  * new_colnames is an array containing column aliases to use for columns
249  * that would exist if the query was re-parsed against the current
250  * definitions of its base tables. This is what to print as the column
251  * alias list for the RTE. This array does not include dropped columns,
252  * but it will include columns added since original parsing. Indexes in
253  * it therefore have little to do with current varattno values. As above,
254  * entries are unique unless this is for an unnamed JOIN RTE. (In such an
255  * RTE, we never actually print this array, but we must compute it anyway
256  * for possible use in computing column names of upper joins.) The
257  * parallel array is_new_col marks which of these columns are new since
258  * original parsing. Entries with is_new_col false must match the
259  * non-NULL colnames entries one-for-one.
260  */
261  int num_new_cols; /* length of new_colnames[] array */
262  char **new_colnames; /* array of C strings */
263  bool *is_new_col; /* array of bool flags */
264 
265  /* This flag tells whether we should actually print a column alias list */
267 
268  /* This list has all names used as USING names in joins above this RTE */
269  List *parentUsing; /* names assigned to parent merged columns */
270 
271  /*
272  * If this struct is for a JOIN RTE, we fill these fields during the
273  * set_using_names() pass to describe its relationship to its child RTEs.
274  *
275  * leftattnos and rightattnos are arrays with one entry per existing
276  * output column of the join (hence, indexable by join varattno). For a
277  * simple reference to a column of the left child, leftattnos[i] is the
278  * child RTE's attno and rightattnos[i] is zero; and conversely for a
279  * column of the right child. But for merged columns produced by JOIN
280  * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
281  * Note that a simple reference might be to a child RTE column that's been
282  * dropped; but that's OK since the column could not be used in the query.
283  *
284  * If it's a JOIN USING, usingNames holds the alias names selected for the
285  * merged columns (these might be different from the original USING list,
286  * if we had to modify names to achieve uniqueness).
287  */
288  int leftrti; /* rangetable index of left child */
289  int rightrti; /* rangetable index of right child */
290  int *leftattnos; /* left-child varattnos of join cols, or 0 */
291  int *rightattnos; /* right-child varattnos of join cols, or 0 */
292  List *usingNames; /* names assigned to merged columns */
294 
295 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
296 #define deparse_columns_fetch(rangetable_index, dpns) \
297  ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
298 
299 /*
300  * Entry in set_rtable_names' hash table
301  */
302 typedef struct
303 {
304  char name[NAMEDATALEN]; /* Hash key --- must be first */
305  int counter; /* Largest addition used so far for name */
306 } NameHashEntry;
307 
308 /* Callback signature for resolve_special_varno() */
309 typedef void (*rsv_callback) (Node *node, deparse_context *context,
310  void *callback_arg);
311 
312 
313 /* ----------
314  * Global data
315  * ----------
316  */
318 static const char *const query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
320 static const char *const query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
321 
322 /* GUC parameters */
324 
325 
326 /* ----------
327  * Local functions
328  *
329  * Most of these functions used to use fixed-size buffers to build their
330  * results. Now, they take an (already initialized) StringInfo object
331  * as a parameter, and append their text output to its contents.
332  * ----------
333  */
334 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
335  bool forceprefix, bool showimplicit,
336  int prettyFlags, int startIndent);
337 static char *pg_get_viewdef_worker(Oid viewoid,
338  int prettyFlags, int wrapColumn);
339 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
340 static int decompile_column_index_array(Datum column_index_array, Oid relId,
341  StringInfo buf);
342 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
343 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
344  const Oid *excludeOps,
345  bool attrsOnly, bool keysOnly,
346  bool showTblSpc, bool inherits,
347  int prettyFlags, bool missing_ok);
348 static char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
349  bool missing_ok);
350 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
351  bool attrsOnly, bool missing_ok);
352 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
353  int prettyFlags, bool missing_ok);
354 static text *pg_get_expr_worker(text *expr, Oid relid, int prettyFlags);
356  bool print_table_args, bool print_defaults);
357 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
358 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
359 static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
360 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
361  Bitmapset *rels_used);
362 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
363  List *parent_namespaces);
364 static void set_simple_column_names(deparse_namespace *dpns);
365 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
366 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
367  List *parentUsing);
369  RangeTblEntry *rte,
370  deparse_columns *colinfo);
372  deparse_columns *colinfo);
373 static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
374  deparse_columns *colinfo);
375 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
376  deparse_columns *colinfo);
377 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
378 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
379  deparse_columns *colinfo);
380 static char *get_rtable_name(int rtindex, deparse_context *context);
381 static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
383  WorkTableScan *wtscan);
384 static void push_child_plan(deparse_namespace *dpns, Plan *plan,
385  deparse_namespace *save_dpns);
386 static void pop_child_plan(deparse_namespace *dpns,
387  deparse_namespace *save_dpns);
388 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
389  deparse_namespace *save_dpns);
390 static void pop_ancestor_plan(deparse_namespace *dpns,
391  deparse_namespace *save_dpns);
392 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
393  int prettyFlags);
394 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
395  int prettyFlags, int wrapColumn);
396 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
397  TupleDesc resultDesc, bool colNamesVisible,
398  int prettyFlags, int wrapColumn, int startIndent);
399 static void get_values_def(List *values_lists, deparse_context *context);
400 static void get_with_clause(Query *query, deparse_context *context);
401 static void get_select_query_def(Query *query, deparse_context *context,
402  TupleDesc resultDesc, bool colNamesVisible);
403 static void get_insert_query_def(Query *query, deparse_context *context,
404  bool colNamesVisible);
405 static void get_update_query_def(Query *query, deparse_context *context,
406  bool colNamesVisible);
407 static void get_update_query_targetlist_def(Query *query, List *targetList,
408  deparse_context *context,
409  RangeTblEntry *rte);
410 static void get_delete_query_def(Query *query, deparse_context *context,
411  bool colNamesVisible);
412 static void get_merge_query_def(Query *query, deparse_context *context,
413  bool colNamesVisible);
414 static void get_utility_query_def(Query *query, deparse_context *context);
415 static void get_basic_select_query(Query *query, deparse_context *context,
416  TupleDesc resultDesc, bool colNamesVisible);
417 static void get_target_list(List *targetList, deparse_context *context,
418  TupleDesc resultDesc, bool colNamesVisible);
419 static void get_setop_query(Node *setOp, Query *query,
420  deparse_context *context,
421  TupleDesc resultDesc, bool colNamesVisible);
422 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
423  bool force_colno,
424  deparse_context *context);
425 static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
426  bool omit_parens, deparse_context *context);
427 static void get_rule_orderby(List *orderList, List *targetList,
428  bool force_colno, deparse_context *context);
429 static void get_rule_windowclause(Query *query, deparse_context *context);
430 static void get_rule_windowspec(WindowClause *wc, List *targetList,
431  deparse_context *context);
432 static char *get_variable(Var *var, int levelsup, bool istoplevel,
433  deparse_context *context);
434 static void get_special_variable(Node *node, deparse_context *context,
435  void *callback_arg);
436 static void resolve_special_varno(Node *node, deparse_context *context,
437  rsv_callback callback, void *callback_arg);
438 static Node *find_param_referent(Param *param, deparse_context *context,
439  deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
440 static void get_parameter(Param *param, deparse_context *context);
441 static const char *get_simple_binary_op_name(OpExpr *expr);
442 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
443 static void appendContextKeyword(deparse_context *context, const char *str,
444  int indentBefore, int indentAfter, int indentPlus);
446 static void get_rule_expr(Node *node, deparse_context *context,
447  bool showimplicit);
448 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
449  bool showimplicit);
450 static void get_rule_list_toplevel(List *lst, deparse_context *context,
451  bool showimplicit);
452 static void get_rule_expr_funccall(Node *node, deparse_context *context,
453  bool showimplicit);
454 static bool looks_like_function(Node *node);
455 static void get_oper_expr(OpExpr *expr, deparse_context *context);
456 static void get_func_expr(FuncExpr *expr, deparse_context *context,
457  bool showimplicit);
458 static void get_agg_expr(Aggref *aggref, deparse_context *context,
459  Aggref *original_aggref);
460 static void get_agg_expr_helper(Aggref *aggref, deparse_context *context,
461  Aggref *original_aggref, const char *funcname,
462  const char *options, bool is_json_objectagg);
463 static void get_agg_combine_expr(Node *node, deparse_context *context,
464  void *callback_arg);
465 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
466 static void get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
467  const char *funcname, const char *options,
468  bool is_json_objectagg);
469 static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
470 static void get_coercion_expr(Node *arg, deparse_context *context,
471  Oid resulttype, int32 resulttypmod,
472  Node *parentNode);
473 static void get_const_expr(Const *constval, deparse_context *context,
474  int showtype);
475 static void get_const_collation(Const *constval, deparse_context *context);
477 static void get_json_constructor(JsonConstructorExpr *ctor,
478  deparse_context *context, bool showimplicit);
480  StringInfo buf);
482  deparse_context *context,
483  const char *funcname,
484  bool is_json_objectagg);
485 static void simple_quote_literal(StringInfo buf, const char *val);
486 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
487 static void get_tablefunc(TableFunc *tf, deparse_context *context,
488  bool showimplicit);
489 static void get_from_clause(Query *query, const char *prefix,
490  deparse_context *context);
491 static void get_from_clause_item(Node *jtnode, Query *query,
492  deparse_context *context);
493 static void get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
494  deparse_context *context);
495 static void get_column_alias_list(deparse_columns *colinfo,
496  deparse_context *context);
497 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
498  deparse_columns *colinfo,
499  deparse_context *context);
500 static void get_tablesample_def(TableSampleClause *tablesample,
501  deparse_context *context);
502 static void get_opclass_name(Oid opclass, Oid actual_datatype,
503  StringInfo buf);
504 static Node *processIndirection(Node *node, deparse_context *context);
505 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
506 static char *get_relation_name(Oid relid);
507 static char *generate_relation_name(Oid relid, List *namespaces);
508 static char *generate_qualified_relation_name(Oid relid);
509 static char *generate_function_name(Oid funcid, int nargs,
510  List *argnames, Oid *argtypes,
511  bool has_variadic, bool *use_variadic_p,
512  ParseExprKind special_exprkind);
513 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
514 static void add_cast_to(StringInfo buf, Oid typid);
515 static char *generate_qualified_type_name(Oid typid);
516 static text *string_to_text(char *str);
517 static char *flatten_reloptions(Oid relid);
518 static void get_reloptions(StringInfo buf, Datum reloptions);
519 
520 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
521 
522 
523 /* ----------
524  * pg_get_ruledef - Do it all and return a text
525  * that could be used as a statement
526  * to recreate the rule
527  * ----------
528  */
529 Datum
531 {
532  Oid ruleoid = PG_GETARG_OID(0);
533  int prettyFlags;
534  char *res;
535 
536  prettyFlags = PRETTYFLAG_INDENT;
537 
538  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
539 
540  if (res == NULL)
541  PG_RETURN_NULL();
542 
544 }
545 
546 
547 Datum
549 {
550  Oid ruleoid = PG_GETARG_OID(0);
551  bool pretty = PG_GETARG_BOOL(1);
552  int prettyFlags;
553  char *res;
554 
555  prettyFlags = GET_PRETTY_FLAGS(pretty);
556 
557  res = pg_get_ruledef_worker(ruleoid, prettyFlags);
558 
559  if (res == NULL)
560  PG_RETURN_NULL();
561 
563 }
564 
565 
566 static char *
567 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
568 {
569  Datum args[1];
570  char nulls[1];
571  int spirc;
572  HeapTuple ruletup;
573  TupleDesc rulettc;
575 
576  /*
577  * Do this first so that string is alloc'd in outer context not SPI's.
578  */
580 
581  /*
582  * Connect to SPI manager
583  */
584  if (SPI_connect() != SPI_OK_CONNECT)
585  elog(ERROR, "SPI_connect failed");
586 
587  /*
588  * On the first call prepare the plan to lookup pg_rewrite. We read
589  * pg_rewrite over the SPI manager instead of using the syscache to be
590  * checked for read access on pg_rewrite.
591  */
592  if (plan_getrulebyoid == NULL)
593  {
594  Oid argtypes[1];
596 
597  argtypes[0] = OIDOID;
598  plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
599  if (plan == NULL)
600  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
603  }
604 
605  /*
606  * Get the pg_rewrite tuple for this rule
607  */
608  args[0] = ObjectIdGetDatum(ruleoid);
609  nulls[0] = ' ';
610  spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
611  if (spirc != SPI_OK_SELECT)
612  elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
613  if (SPI_processed != 1)
614  {
615  /*
616  * There is no tuple data available here, just keep the output buffer
617  * empty.
618  */
619  }
620  else
621  {
622  /*
623  * Get the rule's definition and put it into executor's memory
624  */
625  ruletup = SPI_tuptable->vals[0];
626  rulettc = SPI_tuptable->tupdesc;
627  make_ruledef(&buf, ruletup, rulettc, prettyFlags);
628  }
629 
630  /*
631  * Disconnect from SPI manager
632  */
633  if (SPI_finish() != SPI_OK_FINISH)
634  elog(ERROR, "SPI_finish failed");
635 
636  if (buf.len == 0)
637  return NULL;
638 
639  return buf.data;
640 }
641 
642 
643 /* ----------
644  * pg_get_viewdef - Mainly the same thing, but we
645  * only return the SELECT part of a view
646  * ----------
647  */
648 Datum
650 {
651  /* By OID */
652  Oid viewoid = PG_GETARG_OID(0);
653  int prettyFlags;
654  char *res;
655 
656  prettyFlags = PRETTYFLAG_INDENT;
657 
658  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
659 
660  if (res == NULL)
661  PG_RETURN_NULL();
662 
664 }
665 
666 
667 Datum
669 {
670  /* By OID */
671  Oid viewoid = PG_GETARG_OID(0);
672  bool pretty = PG_GETARG_BOOL(1);
673  int prettyFlags;
674  char *res;
675 
676  prettyFlags = GET_PRETTY_FLAGS(pretty);
677 
678  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
679 
680  if (res == NULL)
681  PG_RETURN_NULL();
682 
684 }
685 
686 Datum
688 {
689  /* By OID */
690  Oid viewoid = PG_GETARG_OID(0);
691  int wrap = PG_GETARG_INT32(1);
692  int prettyFlags;
693  char *res;
694 
695  /* calling this implies we want pretty printing */
696  prettyFlags = GET_PRETTY_FLAGS(true);
697 
698  res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
699 
700  if (res == NULL)
701  PG_RETURN_NULL();
702 
704 }
705 
706 Datum
708 {
709  /* By qualified name */
710  text *viewname = PG_GETARG_TEXT_PP(0);
711  int prettyFlags;
712  RangeVar *viewrel;
713  Oid viewoid;
714  char *res;
715 
716  prettyFlags = PRETTYFLAG_INDENT;
717 
718  /* Look up view name. Can't lock it - we might not have privileges. */
720  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
721 
722  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
723 
724  if (res == NULL)
725  PG_RETURN_NULL();
726 
728 }
729 
730 
731 Datum
733 {
734  /* By qualified name */
735  text *viewname = PG_GETARG_TEXT_PP(0);
736  bool pretty = PG_GETARG_BOOL(1);
737  int prettyFlags;
738  RangeVar *viewrel;
739  Oid viewoid;
740  char *res;
741 
742  prettyFlags = GET_PRETTY_FLAGS(pretty);
743 
744  /* Look up view name. Can't lock it - we might not have privileges. */
746  viewoid = RangeVarGetRelid(viewrel, NoLock, false);
747 
748  res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
749 
750  if (res == NULL)
751  PG_RETURN_NULL();
752 
754 }
755 
756 /*
757  * Common code for by-OID and by-name variants of pg_get_viewdef
758  */
759 static char *
760 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
761 {
762  Datum args[2];
763  char nulls[2];
764  int spirc;
765  HeapTuple ruletup;
766  TupleDesc rulettc;
768 
769  /*
770  * Do this first so that string is alloc'd in outer context not SPI's.
771  */
773 
774  /*
775  * Connect to SPI manager
776  */
777  if (SPI_connect() != SPI_OK_CONNECT)
778  elog(ERROR, "SPI_connect failed");
779 
780  /*
781  * On the first call prepare the plan to lookup pg_rewrite. We read
782  * pg_rewrite over the SPI manager instead of using the syscache to be
783  * checked for read access on pg_rewrite.
784  */
785  if (plan_getviewrule == NULL)
786  {
787  Oid argtypes[2];
789 
790  argtypes[0] = OIDOID;
791  argtypes[1] = NAMEOID;
792  plan = SPI_prepare(query_getviewrule, 2, argtypes);
793  if (plan == NULL)
794  elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
797  }
798 
799  /*
800  * Get the pg_rewrite tuple for the view's SELECT rule
801  */
802  args[0] = ObjectIdGetDatum(viewoid);
804  nulls[0] = ' ';
805  nulls[1] = ' ';
806  spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
807  if (spirc != SPI_OK_SELECT)
808  elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
809  if (SPI_processed != 1)
810  {
811  /*
812  * There is no tuple data available here, just keep the output buffer
813  * empty.
814  */
815  }
816  else
817  {
818  /*
819  * Get the rule's definition and put it into executor's memory
820  */
821  ruletup = SPI_tuptable->vals[0];
822  rulettc = SPI_tuptable->tupdesc;
823  make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
824  }
825 
826  /*
827  * Disconnect from SPI manager
828  */
829  if (SPI_finish() != SPI_OK_FINISH)
830  elog(ERROR, "SPI_finish failed");
831 
832  if (buf.len == 0)
833  return NULL;
834 
835  return buf.data;
836 }
837 
838 /* ----------
839  * pg_get_triggerdef - Get the definition of a trigger
840  * ----------
841  */
842 Datum
844 {
845  Oid trigid = PG_GETARG_OID(0);
846  char *res;
847 
848  res = pg_get_triggerdef_worker(trigid, false);
849 
850  if (res == NULL)
851  PG_RETURN_NULL();
852 
854 }
855 
856 Datum
858 {
859  Oid trigid = PG_GETARG_OID(0);
860  bool pretty = PG_GETARG_BOOL(1);
861  char *res;
862 
863  res = pg_get_triggerdef_worker(trigid, pretty);
864 
865  if (res == NULL)
866  PG_RETURN_NULL();
867 
869 }
870 
871 static char *
872 pg_get_triggerdef_worker(Oid trigid, bool pretty)
873 {
874  HeapTuple ht_trig;
875  Form_pg_trigger trigrec;
877  Relation tgrel;
878  ScanKeyData skey[1];
879  SysScanDesc tgscan;
880  int findx = 0;
881  char *tgname;
882  char *tgoldtable;
883  char *tgnewtable;
884  Datum value;
885  bool isnull;
886 
887  /*
888  * Fetch the pg_trigger tuple by the Oid of the trigger
889  */
890  tgrel = table_open(TriggerRelationId, AccessShareLock);
891 
892  ScanKeyInit(&skey[0],
893  Anum_pg_trigger_oid,
894  BTEqualStrategyNumber, F_OIDEQ,
895  ObjectIdGetDatum(trigid));
896 
897  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
898  NULL, 1, skey);
899 
900  ht_trig = systable_getnext(tgscan);
901 
902  if (!HeapTupleIsValid(ht_trig))
903  {
904  systable_endscan(tgscan);
906  return NULL;
907  }
908 
909  trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
910 
911  /*
912  * Start the trigger definition. Note that the trigger's name should never
913  * be schema-qualified, but the trigger rel's name may be.
914  */
916 
917  tgname = NameStr(trigrec->tgname);
918  appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
919  OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
920  quote_identifier(tgname));
921 
922  if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
923  appendStringInfoString(&buf, "BEFORE");
924  else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
925  appendStringInfoString(&buf, "AFTER");
926  else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
927  appendStringInfoString(&buf, "INSTEAD OF");
928  else
929  elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
930 
931  if (TRIGGER_FOR_INSERT(trigrec->tgtype))
932  {
933  appendStringInfoString(&buf, " INSERT");
934  findx++;
935  }
936  if (TRIGGER_FOR_DELETE(trigrec->tgtype))
937  {
938  if (findx > 0)
939  appendStringInfoString(&buf, " OR DELETE");
940  else
941  appendStringInfoString(&buf, " DELETE");
942  findx++;
943  }
944  if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
945  {
946  if (findx > 0)
947  appendStringInfoString(&buf, " OR UPDATE");
948  else
949  appendStringInfoString(&buf, " UPDATE");
950  findx++;
951  /* tgattr is first var-width field, so OK to access directly */
952  if (trigrec->tgattr.dim1 > 0)
953  {
954  int i;
955 
956  appendStringInfoString(&buf, " OF ");
957  for (i = 0; i < trigrec->tgattr.dim1; i++)
958  {
959  char *attname;
960 
961  if (i > 0)
962  appendStringInfoString(&buf, ", ");
963  attname = get_attname(trigrec->tgrelid,
964  trigrec->tgattr.values[i], false);
966  }
967  }
968  }
969  if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
970  {
971  if (findx > 0)
972  appendStringInfoString(&buf, " OR TRUNCATE");
973  else
974  appendStringInfoString(&buf, " TRUNCATE");
975  findx++;
976  }
977 
978  /*
979  * In non-pretty mode, always schema-qualify the target table name for
980  * safety. In pretty mode, schema-qualify only if not visible.
981  */
982  appendStringInfo(&buf, " ON %s ",
983  pretty ?
984  generate_relation_name(trigrec->tgrelid, NIL) :
985  generate_qualified_relation_name(trigrec->tgrelid));
986 
987  if (OidIsValid(trigrec->tgconstraint))
988  {
989  if (OidIsValid(trigrec->tgconstrrelid))
990  appendStringInfo(&buf, "FROM %s ",
991  generate_relation_name(trigrec->tgconstrrelid, NIL));
992  if (!trigrec->tgdeferrable)
993  appendStringInfoString(&buf, "NOT ");
994  appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
995  if (trigrec->tginitdeferred)
996  appendStringInfoString(&buf, "DEFERRED ");
997  else
998  appendStringInfoString(&buf, "IMMEDIATE ");
999  }
1000 
1001  value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
1002  tgrel->rd_att, &isnull);
1003  if (!isnull)
1004  tgoldtable = NameStr(*DatumGetName(value));
1005  else
1006  tgoldtable = NULL;
1007  value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
1008  tgrel->rd_att, &isnull);
1009  if (!isnull)
1010  tgnewtable = NameStr(*DatumGetName(value));
1011  else
1012  tgnewtable = NULL;
1013  if (tgoldtable != NULL || tgnewtable != NULL)
1014  {
1015  appendStringInfoString(&buf, "REFERENCING ");
1016  if (tgoldtable != NULL)
1017  appendStringInfo(&buf, "OLD TABLE AS %s ",
1018  quote_identifier(tgoldtable));
1019  if (tgnewtable != NULL)
1020  appendStringInfo(&buf, "NEW TABLE AS %s ",
1021  quote_identifier(tgnewtable));
1022  }
1023 
1024  if (TRIGGER_FOR_ROW(trigrec->tgtype))
1025  appendStringInfoString(&buf, "FOR EACH ROW ");
1026  else
1027  appendStringInfoString(&buf, "FOR EACH STATEMENT ");
1028 
1029  /* If the trigger has a WHEN qualification, add that */
1030  value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
1031  tgrel->rd_att, &isnull);
1032  if (!isnull)
1033  {
1034  Node *qual;
1035  char relkind;
1036  deparse_context context;
1037  deparse_namespace dpns;
1038  RangeTblEntry *oldrte;
1039  RangeTblEntry *newrte;
1040 
1041  appendStringInfoString(&buf, "WHEN (");
1042 
1044 
1045  relkind = get_rel_relkind(trigrec->tgrelid);
1046 
1047  /* Build minimal OLD and NEW RTEs for the rel */
1048  oldrte = makeNode(RangeTblEntry);
1049  oldrte->rtekind = RTE_RELATION;
1050  oldrte->relid = trigrec->tgrelid;
1051  oldrte->relkind = relkind;
1052  oldrte->rellockmode = AccessShareLock;
1053  oldrte->alias = makeAlias("old", NIL);
1054  oldrte->eref = oldrte->alias;
1055  oldrte->lateral = false;
1056  oldrte->inh = false;
1057  oldrte->inFromCl = true;
1058 
1059  newrte = makeNode(RangeTblEntry);
1060  newrte->rtekind = RTE_RELATION;
1061  newrte->relid = trigrec->tgrelid;
1062  newrte->relkind = relkind;
1063  newrte->rellockmode = AccessShareLock;
1064  newrte->alias = makeAlias("new", NIL);
1065  newrte->eref = newrte->alias;
1066  newrte->lateral = false;
1067  newrte->inh = false;
1068  newrte->inFromCl = true;
1069 
1070  /* Build two-element rtable */
1071  memset(&dpns, 0, sizeof(dpns));
1072  dpns.rtable = list_make2(oldrte, newrte);
1073  dpns.subplans = NIL;
1074  dpns.ctes = NIL;
1075  dpns.appendrels = NULL;
1076  set_rtable_names(&dpns, NIL, NULL);
1077  set_simple_column_names(&dpns);
1078 
1079  /* Set up context with one-deep namespace stack */
1080  context.buf = &buf;
1081  context.namespaces = list_make1(&dpns);
1082  context.windowClause = NIL;
1083  context.windowTList = NIL;
1084  context.varprefix = true;
1085  context.prettyFlags = GET_PRETTY_FLAGS(pretty);
1086  context.wrapColumn = WRAP_COLUMN_DEFAULT;
1087  context.indentLevel = PRETTYINDENT_STD;
1088  context.special_exprkind = EXPR_KIND_NONE;
1089  context.appendparents = NULL;
1090 
1091  get_rule_expr(qual, &context, false);
1092 
1093  appendStringInfoString(&buf, ") ");
1094  }
1095 
1096  appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
1097  generate_function_name(trigrec->tgfoid, 0,
1098  NIL, NULL,
1099  false, NULL, EXPR_KIND_NONE));
1100 
1101  if (trigrec->tgnargs > 0)
1102  {
1103  char *p;
1104  int i;
1105 
1106  value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
1107  tgrel->rd_att, &isnull);
1108  if (isnull)
1109  elog(ERROR, "tgargs is null for trigger %u", trigid);
1110  p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
1111  for (i = 0; i < trigrec->tgnargs; i++)
1112  {
1113  if (i > 0)
1114  appendStringInfoString(&buf, ", ");
1116  /* advance p to next string embedded in tgargs */
1117  while (*p)
1118  p++;
1119  p++;
1120  }
1121  }
1122 
1123  /* We deliberately do not put semi-colon at end */
1124  appendStringInfoChar(&buf, ')');
1125 
1126  /* Clean up */
1127  systable_endscan(tgscan);
1128 
1129  table_close(tgrel, AccessShareLock);
1130 
1131  return buf.data;
1132 }
1133 
1134 /* ----------
1135  * pg_get_indexdef - Get the definition of an index
1136  *
1137  * In the extended version, there is a colno argument as well as pretty bool.
1138  * if colno == 0, we want a complete index definition.
1139  * if colno > 0, we only want the Nth index key's variable or expression.
1140  *
1141  * Note that the SQL-function versions of this omit any info about the
1142  * index tablespace; this is intentional because pg_dump wants it that way.
1143  * However pg_get_indexdef_string() includes the index tablespace.
1144  * ----------
1145  */
1146 Datum
1148 {
1149  Oid indexrelid = PG_GETARG_OID(0);
1150  int prettyFlags;
1151  char *res;
1152 
1153  prettyFlags = PRETTYFLAG_INDENT;
1154 
1155  res = pg_get_indexdef_worker(indexrelid, 0, NULL,
1156  false, false,
1157  false, false,
1158  prettyFlags, true);
1159 
1160  if (res == NULL)
1161  PG_RETURN_NULL();
1162 
1164 }
1165 
1166 Datum
1168 {
1169  Oid indexrelid = PG_GETARG_OID(0);
1170  int32 colno = PG_GETARG_INT32(1);
1171  bool pretty = PG_GETARG_BOOL(2);
1172  int prettyFlags;
1173  char *res;
1174 
1175  prettyFlags = GET_PRETTY_FLAGS(pretty);
1176 
1177  res = pg_get_indexdef_worker(indexrelid, colno, NULL,
1178  colno != 0, false,
1179  false, false,
1180  prettyFlags, true);
1181 
1182  if (res == NULL)
1183  PG_RETURN_NULL();
1184 
1186 }
1187 
1188 /*
1189  * Internal version for use by ALTER TABLE.
1190  * Includes a tablespace clause in the result.
1191  * Returns a palloc'd C string; no pretty-printing.
1192  */
1193 char *
1195 {
1196  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1197  false, false,
1198  true, true,
1199  0, false);
1200 }
1201 
1202 /* Internal version that just reports the key-column definitions */
1203 char *
1204 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1205 {
1206  int prettyFlags;
1207 
1208  prettyFlags = GET_PRETTY_FLAGS(pretty);
1209 
1210  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1211  true, true,
1212  false, false,
1213  prettyFlags, false);
1214 }
1215 
1216 /* Internal version, extensible with flags to control its behavior */
1217 char *
1219 {
1220  bool pretty = ((flags & RULE_INDEXDEF_PRETTY) != 0);
1221  bool keys_only = ((flags & RULE_INDEXDEF_KEYS_ONLY) != 0);
1222  int prettyFlags;
1223 
1224  prettyFlags = GET_PRETTY_FLAGS(pretty);
1225 
1226  return pg_get_indexdef_worker(indexrelid, 0, NULL,
1227  true, keys_only,
1228  false, false,
1229  prettyFlags, false);
1230 }
1231 
1232 /*
1233  * Internal workhorse to decompile an index definition.
1234  *
1235  * This is now used for exclusion constraints as well: if excludeOps is not
1236  * NULL then it points to an array of exclusion operator OIDs.
1237  */
1238 static char *
1239 pg_get_indexdef_worker(Oid indexrelid, int colno,
1240  const Oid *excludeOps,
1241  bool attrsOnly, bool keysOnly,
1242  bool showTblSpc, bool inherits,
1243  int prettyFlags, bool missing_ok)
1244 {
1245  /* might want a separate isConstraint parameter later */
1246  bool isConstraint = (excludeOps != NULL);
1247  HeapTuple ht_idx;
1248  HeapTuple ht_idxrel;
1249  HeapTuple ht_am;
1250  Form_pg_index idxrec;
1251  Form_pg_class idxrelrec;
1252  Form_pg_am amrec;
1253  IndexAmRoutine *amroutine;
1254  List *indexprs;
1255  ListCell *indexpr_item;
1256  List *context;
1257  Oid indrelid;
1258  int keyno;
1259  Datum indcollDatum;
1260  Datum indclassDatum;
1261  Datum indoptionDatum;
1262  oidvector *indcollation;
1263  oidvector *indclass;
1264  int2vector *indoption;
1266  char *str;
1267  char *sep;
1268 
1269  /*
1270  * Fetch the pg_index tuple by the Oid of the index
1271  */
1272  ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1273  if (!HeapTupleIsValid(ht_idx))
1274  {
1275  if (missing_ok)
1276  return NULL;
1277  elog(ERROR, "cache lookup failed for index %u", indexrelid);
1278  }
1279  idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1280 
1281  indrelid = idxrec->indrelid;
1282  Assert(indexrelid == idxrec->indexrelid);
1283 
1284  /* Must get indcollation, indclass, and indoption the hard way */
1285  indcollDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1286  Anum_pg_index_indcollation);
1287  indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1288 
1289  indclassDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1290  Anum_pg_index_indclass);
1291  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1292 
1293  indoptionDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1294  Anum_pg_index_indoption);
1295  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1296 
1297  /*
1298  * Fetch the pg_class tuple of the index relation
1299  */
1300  ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1301  if (!HeapTupleIsValid(ht_idxrel))
1302  elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1303  idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1304 
1305  /*
1306  * Fetch the pg_am tuple of the index' access method
1307  */
1308  ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1309  if (!HeapTupleIsValid(ht_am))
1310  elog(ERROR, "cache lookup failed for access method %u",
1311  idxrelrec->relam);
1312  amrec = (Form_pg_am) GETSTRUCT(ht_am);
1313 
1314  /* Fetch the index AM's API struct */
1315  amroutine = GetIndexAmRoutine(amrec->amhandler);
1316 
1317  /*
1318  * Get the index expressions, if any. (NOTE: we do not use the relcache
1319  * versions of the expressions and predicate, because we want to display
1320  * non-const-folded expressions.)
1321  */
1322  if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
1323  {
1324  Datum exprsDatum;
1325  char *exprsString;
1326 
1327  exprsDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1328  Anum_pg_index_indexprs);
1329  exprsString = TextDatumGetCString(exprsDatum);
1330  indexprs = (List *) stringToNode(exprsString);
1331  pfree(exprsString);
1332  }
1333  else
1334  indexprs = NIL;
1335 
1336  indexpr_item = list_head(indexprs);
1337 
1338  context = deparse_context_for(get_relation_name(indrelid), indrelid);
1339 
1340  /*
1341  * Start the index definition. Note that the index's name should never be
1342  * schema-qualified, but the indexed rel's name may be.
1343  */
1344  initStringInfo(&buf);
1345 
1346  if (!attrsOnly)
1347  {
1348  if (!isConstraint)
1349  appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
1350  idxrec->indisunique ? "UNIQUE " : "",
1351  quote_identifier(NameStr(idxrelrec->relname)),
1352  idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
1353  && !inherits ? "ONLY " : "",
1354  (prettyFlags & PRETTYFLAG_SCHEMA) ?
1355  generate_relation_name(indrelid, NIL) :
1357  quote_identifier(NameStr(amrec->amname)));
1358  else /* currently, must be EXCLUDE constraint */
1359  appendStringInfo(&buf, "EXCLUDE USING %s (",
1360  quote_identifier(NameStr(amrec->amname)));
1361  }
1362 
1363  /*
1364  * Report the indexed attributes
1365  */
1366  sep = "";
1367  for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1368  {
1369  AttrNumber attnum = idxrec->indkey.values[keyno];
1370  Oid keycoltype;
1371  Oid keycolcollation;
1372 
1373  /*
1374  * Ignore non-key attributes if told to.
1375  */
1376  if (keysOnly && keyno >= idxrec->indnkeyatts)
1377  break;
1378 
1379  /* Otherwise, print INCLUDE to divide key and non-key attrs. */
1380  if (!colno && keyno == idxrec->indnkeyatts)
1381  {
1382  appendStringInfoString(&buf, ") INCLUDE (");
1383  sep = "";
1384  }
1385 
1386  if (!colno)
1387  appendStringInfoString(&buf, sep);
1388  sep = ", ";
1389 
1390  if (attnum != 0)
1391  {
1392  /* Simple index column */
1393  char *attname;
1394  int32 keycoltypmod;
1395 
1396  attname = get_attname(indrelid, attnum, false);
1397  if (!colno || colno == keyno + 1)
1399  get_atttypetypmodcoll(indrelid, attnum,
1400  &keycoltype, &keycoltypmod,
1401  &keycolcollation);
1402  }
1403  else
1404  {
1405  /* expressional index */
1406  Node *indexkey;
1407 
1408  if (indexpr_item == NULL)
1409  elog(ERROR, "too few entries in indexprs list");
1410  indexkey = (Node *) lfirst(indexpr_item);
1411  indexpr_item = lnext(indexprs, indexpr_item);
1412  /* Deparse */
1413  str = deparse_expression_pretty(indexkey, context, false, false,
1414  prettyFlags, 0);
1415  if (!colno || colno == keyno + 1)
1416  {
1417  /* Need parens if it's not a bare function call */
1418  if (looks_like_function(indexkey))
1420  else
1421  appendStringInfo(&buf, "(%s)", str);
1422  }
1423  keycoltype = exprType(indexkey);
1424  keycolcollation = exprCollation(indexkey);
1425  }
1426 
1427  /* Print additional decoration for (selected) key columns */
1428  if (!attrsOnly && keyno < idxrec->indnkeyatts &&
1429  (!colno || colno == keyno + 1))
1430  {
1431  int16 opt = indoption->values[keyno];
1432  Oid indcoll = indcollation->values[keyno];
1433  Datum attoptions = get_attoptions(indexrelid, keyno + 1);
1434  bool has_options = attoptions != (Datum) 0;
1435 
1436  /* Add collation, if not default for column */
1437  if (OidIsValid(indcoll) && indcoll != keycolcollation)
1438  appendStringInfo(&buf, " COLLATE %s",
1439  generate_collation_name((indcoll)));
1440 
1441  /* Add the operator class name, if not default */
1442  get_opclass_name(indclass->values[keyno],
1443  has_options ? InvalidOid : keycoltype, &buf);
1444 
1445  if (has_options)
1446  {
1447  appendStringInfoString(&buf, " (");
1448  get_reloptions(&buf, attoptions);
1449  appendStringInfoChar(&buf, ')');
1450  }
1451 
1452  /* Add options if relevant */
1453  if (amroutine->amcanorder)
1454  {
1455  /* if it supports sort ordering, report DESC and NULLS opts */
1456  if (opt & INDOPTION_DESC)
1457  {
1458  appendStringInfoString(&buf, " DESC");
1459  /* NULLS FIRST is the default in this case */
1460  if (!(opt & INDOPTION_NULLS_FIRST))
1461  appendStringInfoString(&buf, " NULLS LAST");
1462  }
1463  else
1464  {
1465  if (opt & INDOPTION_NULLS_FIRST)
1466  appendStringInfoString(&buf, " NULLS FIRST");
1467  }
1468  }
1469 
1470  /* Add the exclusion operator if relevant */
1471  if (excludeOps != NULL)
1472  appendStringInfo(&buf, " WITH %s",
1473  generate_operator_name(excludeOps[keyno],
1474  keycoltype,
1475  keycoltype));
1476  }
1477  }
1478 
1479  if (!attrsOnly)
1480  {
1481  appendStringInfoChar(&buf, ')');
1482 
1483  if (idxrec->indnullsnotdistinct)
1484  appendStringInfoString(&buf, " NULLS NOT DISTINCT");
1485 
1486  /*
1487  * If it has options, append "WITH (options)"
1488  */
1489  str = flatten_reloptions(indexrelid);
1490  if (str)
1491  {
1492  appendStringInfo(&buf, " WITH (%s)", str);
1493  pfree(str);
1494  }
1495 
1496  /*
1497  * Print tablespace, but only if requested
1498  */
1499  if (showTblSpc)
1500  {
1501  Oid tblspc;
1502 
1503  tblspc = get_rel_tablespace(indexrelid);
1504  if (OidIsValid(tblspc))
1505  {
1506  if (isConstraint)
1507  appendStringInfoString(&buf, " USING INDEX");
1508  appendStringInfo(&buf, " TABLESPACE %s",
1510  }
1511  }
1512 
1513  /*
1514  * If it's a partial index, decompile and append the predicate
1515  */
1516  if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
1517  {
1518  Node *node;
1519  Datum predDatum;
1520  char *predString;
1521 
1522  /* Convert text string to node tree */
1523  predDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1524  Anum_pg_index_indpred);
1525  predString = TextDatumGetCString(predDatum);
1526  node = (Node *) stringToNode(predString);
1527  pfree(predString);
1528 
1529  /* Deparse */
1530  str = deparse_expression_pretty(node, context, false, false,
1531  prettyFlags, 0);
1532  if (isConstraint)
1533  appendStringInfo(&buf, " WHERE (%s)", str);
1534  else
1535  appendStringInfo(&buf, " WHERE %s", str);
1536  }
1537  }
1538 
1539  /* Clean up */
1540  ReleaseSysCache(ht_idx);
1541  ReleaseSysCache(ht_idxrel);
1542  ReleaseSysCache(ht_am);
1543 
1544  return buf.data;
1545 }
1546 
1547 /* ----------
1548  * pg_get_querydef
1549  *
1550  * Public entry point to deparse one query parsetree.
1551  * The pretty flags are determined by GET_PRETTY_FLAGS(pretty).
1552  *
1553  * The result is a palloc'd C string.
1554  * ----------
1555  */
1556 char *
1557 pg_get_querydef(Query *query, bool pretty)
1558 {
1560  int prettyFlags;
1561 
1562  prettyFlags = GET_PRETTY_FLAGS(pretty);
1563 
1564  initStringInfo(&buf);
1565 
1566  get_query_def(query, &buf, NIL, NULL, true,
1567  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
1568 
1569  return buf.data;
1570 }
1571 
1572 /*
1573  * pg_get_statisticsobjdef
1574  * Get the definition of an extended statistics object
1575  */
1576 Datum
1578 {
1579  Oid statextid = PG_GETARG_OID(0);
1580  char *res;
1581 
1582  res = pg_get_statisticsobj_worker(statextid, false, true);
1583 
1584  if (res == NULL)
1585  PG_RETURN_NULL();
1586 
1588 }
1589 
1590 /*
1591  * Internal version for use by ALTER TABLE.
1592  * Includes a tablespace clause in the result.
1593  * Returns a palloc'd C string; no pretty-printing.
1594  */
1595 char *
1597 {
1598  return pg_get_statisticsobj_worker(statextid, false, false);
1599 }
1600 
1601 /*
1602  * pg_get_statisticsobjdef_columns
1603  * Get columns and expressions for an extended statistics object
1604  */
1605 Datum
1607 {
1608  Oid statextid = PG_GETARG_OID(0);
1609  char *res;
1610 
1611  res = pg_get_statisticsobj_worker(statextid, true, true);
1612 
1613  if (res == NULL)
1614  PG_RETURN_NULL();
1615 
1617 }
1618 
1619 /*
1620  * Internal workhorse to decompile an extended statistics object.
1621  */
1622 static char *
1623 pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
1624 {
1625  Form_pg_statistic_ext statextrec;
1626  HeapTuple statexttup;
1628  int colno;
1629  char *nsp;
1630  ArrayType *arr;
1631  char *enabled;
1632  Datum datum;
1633  bool ndistinct_enabled;
1634  bool dependencies_enabled;
1635  bool mcv_enabled;
1636  int i;
1637  List *context;
1638  ListCell *lc;
1639  List *exprs = NIL;
1640  bool has_exprs;
1641  int ncolumns;
1642 
1643  statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1644 
1645  if (!HeapTupleIsValid(statexttup))
1646  {
1647  if (missing_ok)
1648  return NULL;
1649  elog(ERROR, "cache lookup failed for statistics object %u", statextid);
1650  }
1651 
1652  /* has the statistics expressions? */
1653  has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1654 
1655  statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1656 
1657  /*
1658  * Get the statistics expressions, if any. (NOTE: we do not use the
1659  * relcache versions of the expressions, because we want to display
1660  * non-const-folded expressions.)
1661  */
1662  if (has_exprs)
1663  {
1664  Datum exprsDatum;
1665  char *exprsString;
1666 
1667  exprsDatum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1668  Anum_pg_statistic_ext_stxexprs);
1669  exprsString = TextDatumGetCString(exprsDatum);
1670  exprs = (List *) stringToNode(exprsString);
1671  pfree(exprsString);
1672  }
1673  else
1674  exprs = NIL;
1675 
1676  /* count the number of columns (attributes and expressions) */
1677  ncolumns = statextrec->stxkeys.dim1 + list_length(exprs);
1678 
1679  initStringInfo(&buf);
1680 
1681  if (!columns_only)
1682  {
1683  nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
1684  appendStringInfo(&buf, "CREATE STATISTICS %s",
1686  NameStr(statextrec->stxname)));
1687 
1688  /*
1689  * Decode the stxkind column so that we know which stats types to
1690  * print.
1691  */
1692  datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1693  Anum_pg_statistic_ext_stxkind);
1694  arr = DatumGetArrayTypeP(datum);
1695  if (ARR_NDIM(arr) != 1 ||
1696  ARR_HASNULL(arr) ||
1697  ARR_ELEMTYPE(arr) != CHAROID)
1698  elog(ERROR, "stxkind is not a 1-D char array");
1699  enabled = (char *) ARR_DATA_PTR(arr);
1700 
1701  ndistinct_enabled = false;
1702  dependencies_enabled = false;
1703  mcv_enabled = false;
1704 
1705  for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1706  {
1707  if (enabled[i] == STATS_EXT_NDISTINCT)
1708  ndistinct_enabled = true;
1709  else if (enabled[i] == STATS_EXT_DEPENDENCIES)
1710  dependencies_enabled = true;
1711  else if (enabled[i] == STATS_EXT_MCV)
1712  mcv_enabled = true;
1713 
1714  /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */
1715  }
1716 
1717  /*
1718  * If any option is disabled, then we'll need to append the types
1719  * clause to show which options are enabled. We omit the types clause
1720  * on purpose when all options are enabled, so a pg_dump/pg_restore
1721  * will create all statistics types on a newer postgres version, if
1722  * the statistics had all options enabled on the original version.
1723  *
1724  * But if the statistics is defined on just a single column, it has to
1725  * be an expression statistics. In that case we don't need to specify
1726  * kinds.
1727  */
1728  if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) &&
1729  (ncolumns > 1))
1730  {
1731  bool gotone = false;
1732 
1733  appendStringInfoString(&buf, " (");
1734 
1735  if (ndistinct_enabled)
1736  {
1737  appendStringInfoString(&buf, "ndistinct");
1738  gotone = true;
1739  }
1740 
1741  if (dependencies_enabled)
1742  {
1743  appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
1744  gotone = true;
1745  }
1746 
1747  if (mcv_enabled)
1748  appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
1749 
1750  appendStringInfoChar(&buf, ')');
1751  }
1752 
1753  appendStringInfoString(&buf, " ON ");
1754  }
1755 
1756  /* decode simple column references */
1757  for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
1758  {
1759  AttrNumber attnum = statextrec->stxkeys.values[colno];
1760  char *attname;
1761 
1762  if (colno > 0)
1763  appendStringInfoString(&buf, ", ");
1764 
1765  attname = get_attname(statextrec->stxrelid, attnum, false);
1766 
1768  }
1769 
1770  context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1771  statextrec->stxrelid);
1772 
1773  foreach(lc, exprs)
1774  {
1775  Node *expr = (Node *) lfirst(lc);
1776  char *str;
1777  int prettyFlags = PRETTYFLAG_PAREN;
1778 
1779  str = deparse_expression_pretty(expr, context, false, false,
1780  prettyFlags, 0);
1781 
1782  if (colno > 0)
1783  appendStringInfoString(&buf, ", ");
1784 
1785  /* Need parens if it's not a bare function call */
1786  if (looks_like_function(expr))
1788  else
1789  appendStringInfo(&buf, "(%s)", str);
1790 
1791  colno++;
1792  }
1793 
1794  if (!columns_only)
1795  appendStringInfo(&buf, " FROM %s",
1796  generate_relation_name(statextrec->stxrelid, NIL));
1797 
1798  ReleaseSysCache(statexttup);
1799 
1800  return buf.data;
1801 }
1802 
1803 /*
1804  * Generate text array of expressions for statistics object.
1805  */
1806 Datum
1808 {
1809  Oid statextid = PG_GETARG_OID(0);
1810  Form_pg_statistic_ext statextrec;
1811  HeapTuple statexttup;
1812  Datum datum;
1813  List *context;
1814  ListCell *lc;
1815  List *exprs = NIL;
1816  bool has_exprs;
1817  char *tmp;
1818  ArrayBuildState *astate = NULL;
1819 
1820  statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1821 
1822  if (!HeapTupleIsValid(statexttup))
1823  PG_RETURN_NULL();
1824 
1825  /* Does the stats object have expressions? */
1826  has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1827 
1828  /* no expressions? we're done */
1829  if (!has_exprs)
1830  {
1831  ReleaseSysCache(statexttup);
1832  PG_RETURN_NULL();
1833  }
1834 
1835  statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1836 
1837  /*
1838  * Get the statistics expressions, and deparse them into text values.
1839  */
1840  datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1841  Anum_pg_statistic_ext_stxexprs);
1842  tmp = TextDatumGetCString(datum);
1843  exprs = (List *) stringToNode(tmp);
1844  pfree(tmp);
1845 
1846  context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1847  statextrec->stxrelid);
1848 
1849  foreach(lc, exprs)
1850  {
1851  Node *expr = (Node *) lfirst(lc);
1852  char *str;
1853  int prettyFlags = PRETTYFLAG_INDENT;
1854 
1855  str = deparse_expression_pretty(expr, context, false, false,
1856  prettyFlags, 0);
1857 
1858  astate = accumArrayResult(astate,
1860  false,
1861  TEXTOID,
1863  }
1864 
1865  ReleaseSysCache(statexttup);
1866 
1868 }
1869 
1870 /*
1871  * pg_get_partkeydef
1872  *
1873  * Returns the partition key specification, ie, the following:
1874  *
1875  * { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
1876  */
1877 Datum
1879 {
1880  Oid relid = PG_GETARG_OID(0);
1881  char *res;
1882 
1883  res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
1884 
1885  if (res == NULL)
1886  PG_RETURN_NULL();
1887 
1889 }
1890 
1891 /* Internal version that just reports the column definitions */
1892 char *
1893 pg_get_partkeydef_columns(Oid relid, bool pretty)
1894 {
1895  int prettyFlags;
1896 
1897  prettyFlags = GET_PRETTY_FLAGS(pretty);
1898 
1899  return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
1900 }
1901 
1902 /*
1903  * Internal workhorse to decompile a partition key definition.
1904  */
1905 static char *
1906 pg_get_partkeydef_worker(Oid relid, int prettyFlags,
1907  bool attrsOnly, bool missing_ok)
1908 {
1910  HeapTuple tuple;
1911  oidvector *partclass;
1912  oidvector *partcollation;
1913  List *partexprs;
1914  ListCell *partexpr_item;
1915  List *context;
1916  Datum datum;
1918  int keyno;
1919  char *str;
1920  char *sep;
1921 
1922  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
1923  if (!HeapTupleIsValid(tuple))
1924  {
1925  if (missing_ok)
1926  return NULL;
1927  elog(ERROR, "cache lookup failed for partition key of %u", relid);
1928  }
1929 
1930  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
1931 
1932  Assert(form->partrelid == relid);
1933 
1934  /* Must get partclass and partcollation the hard way */
1935  datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1936  Anum_pg_partitioned_table_partclass);
1937  partclass = (oidvector *) DatumGetPointer(datum);
1938 
1939  datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1940  Anum_pg_partitioned_table_partcollation);
1941  partcollation = (oidvector *) DatumGetPointer(datum);
1942 
1943 
1944  /*
1945  * Get the expressions, if any. (NOTE: we do not use the relcache
1946  * versions of the expressions, because we want to display
1947  * non-const-folded expressions.)
1948  */
1949  if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
1950  {
1951  Datum exprsDatum;
1952  char *exprsString;
1953 
1954  exprsDatum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1955  Anum_pg_partitioned_table_partexprs);
1956  exprsString = TextDatumGetCString(exprsDatum);
1957  partexprs = (List *) stringToNode(exprsString);
1958 
1959  if (!IsA(partexprs, List))
1960  elog(ERROR, "unexpected node type found in partexprs: %d",
1961  (int) nodeTag(partexprs));
1962 
1963  pfree(exprsString);
1964  }
1965  else
1966  partexprs = NIL;
1967 
1968  partexpr_item = list_head(partexprs);
1969  context = deparse_context_for(get_relation_name(relid), relid);
1970 
1971  initStringInfo(&buf);
1972 
1973  switch (form->partstrat)
1974  {
1976  if (!attrsOnly)
1977  appendStringInfoString(&buf, "HASH");
1978  break;
1980  if (!attrsOnly)
1981  appendStringInfoString(&buf, "LIST");
1982  break;
1984  if (!attrsOnly)
1985  appendStringInfoString(&buf, "RANGE");
1986  break;
1987  default:
1988  elog(ERROR, "unexpected partition strategy: %d",
1989  (int) form->partstrat);
1990  }
1991 
1992  if (!attrsOnly)
1993  appendStringInfoString(&buf, " (");
1994  sep = "";
1995  for (keyno = 0; keyno < form->partnatts; keyno++)
1996  {
1997  AttrNumber attnum = form->partattrs.values[keyno];
1998  Oid keycoltype;
1999  Oid keycolcollation;
2000  Oid partcoll;
2001 
2002  appendStringInfoString(&buf, sep);
2003  sep = ", ";
2004  if (attnum != 0)
2005  {
2006  /* Simple attribute reference */
2007  char *attname;
2008  int32 keycoltypmod;
2009 
2010  attname = get_attname(relid, attnum, false);
2013  &keycoltype, &keycoltypmod,
2014  &keycolcollation);
2015  }
2016  else
2017  {
2018  /* Expression */
2019  Node *partkey;
2020 
2021  if (partexpr_item == NULL)
2022  elog(ERROR, "too few entries in partexprs list");
2023  partkey = (Node *) lfirst(partexpr_item);
2024  partexpr_item = lnext(partexprs, partexpr_item);
2025 
2026  /* Deparse */
2027  str = deparse_expression_pretty(partkey, context, false, false,
2028  prettyFlags, 0);
2029  /* Need parens if it's not a bare function call */
2030  if (looks_like_function(partkey))
2032  else
2033  appendStringInfo(&buf, "(%s)", str);
2034 
2035  keycoltype = exprType(partkey);
2036  keycolcollation = exprCollation(partkey);
2037  }
2038 
2039  /* Add collation, if not default for column */
2040  partcoll = partcollation->values[keyno];
2041  if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
2042  appendStringInfo(&buf, " COLLATE %s",
2043  generate_collation_name((partcoll)));
2044 
2045  /* Add the operator class name, if not default */
2046  if (!attrsOnly)
2047  get_opclass_name(partclass->values[keyno], keycoltype, &buf);
2048  }
2049 
2050  if (!attrsOnly)
2051  appendStringInfoChar(&buf, ')');
2052 
2053  /* Clean up */
2054  ReleaseSysCache(tuple);
2055 
2056  return buf.data;
2057 }
2058 
2059 /*
2060  * pg_get_partition_constraintdef
2061  *
2062  * Returns partition constraint expression as a string for the input relation
2063  */
2064 Datum
2066 {
2067  Oid relationId = PG_GETARG_OID(0);
2068  Expr *constr_expr;
2069  int prettyFlags;
2070  List *context;
2071  char *consrc;
2072 
2073  constr_expr = get_partition_qual_relid(relationId);
2074 
2075  /* Quick exit if no partition constraint */
2076  if (constr_expr == NULL)
2077  PG_RETURN_NULL();
2078 
2079  /*
2080  * Deparse and return the constraint expression.
2081  */
2082  prettyFlags = PRETTYFLAG_INDENT;
2083  context = deparse_context_for(get_relation_name(relationId), relationId);
2084  consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
2085  false, prettyFlags, 0);
2086 
2088 }
2089 
2090 /*
2091  * pg_get_partconstrdef_string
2092  *
2093  * Returns the partition constraint as a C-string for the input relation, with
2094  * the given alias. No pretty-printing.
2095  */
2096 char *
2097 pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
2098 {
2099  Expr *constr_expr;
2100  List *context;
2101 
2102  constr_expr = get_partition_qual_relid(partitionId);
2103  context = deparse_context_for(aliasname, partitionId);
2104 
2105  return deparse_expression((Node *) constr_expr, context, true, false);
2106 }
2107 
2108 /*
2109  * pg_get_constraintdef
2110  *
2111  * Returns the definition for the constraint, ie, everything that needs to
2112  * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
2113  */
2114 Datum
2116 {
2117  Oid constraintId = PG_GETARG_OID(0);
2118  int prettyFlags;
2119  char *res;
2120 
2121  prettyFlags = PRETTYFLAG_INDENT;
2122 
2123  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2124 
2125  if (res == NULL)
2126  PG_RETURN_NULL();
2127 
2129 }
2130 
2131 Datum
2133 {
2134  Oid constraintId = PG_GETARG_OID(0);
2135  bool pretty = PG_GETARG_BOOL(1);
2136  int prettyFlags;
2137  char *res;
2138 
2139  prettyFlags = GET_PRETTY_FLAGS(pretty);
2140 
2141  res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2142 
2143  if (res == NULL)
2144  PG_RETURN_NULL();
2145 
2147 }
2148 
2149 /*
2150  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
2151  */
2152 char *
2154 {
2155  return pg_get_constraintdef_worker(constraintId, true, 0, false);
2156 }
2157 
2158 /*
2159  * As of 9.4, we now use an MVCC snapshot for this.
2160  */
2161 static char *
2162 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
2163  int prettyFlags, bool missing_ok)
2164 {
2165  HeapTuple tup;
2166  Form_pg_constraint conForm;
2168  SysScanDesc scandesc;
2169  ScanKeyData scankey[1];
2171  Relation relation = table_open(ConstraintRelationId, AccessShareLock);
2172 
2173  ScanKeyInit(&scankey[0],
2174  Anum_pg_constraint_oid,
2175  BTEqualStrategyNumber, F_OIDEQ,
2176  ObjectIdGetDatum(constraintId));
2177 
2178  scandesc = systable_beginscan(relation,
2179  ConstraintOidIndexId,
2180  true,
2181  snapshot,
2182  1,
2183  scankey);
2184 
2185  /*
2186  * We later use the tuple with SysCacheGetAttr() as if we had obtained it
2187  * via SearchSysCache, which works fine.
2188  */
2189  tup = systable_getnext(scandesc);
2190 
2191  UnregisterSnapshot(snapshot);
2192 
2193  if (!HeapTupleIsValid(tup))
2194  {
2195  if (missing_ok)
2196  {
2197  systable_endscan(scandesc);
2198  table_close(relation, AccessShareLock);
2199  return NULL;
2200  }
2201  elog(ERROR, "could not find tuple for constraint %u", constraintId);
2202  }
2203 
2204  conForm = (Form_pg_constraint) GETSTRUCT(tup);
2205 
2206  initStringInfo(&buf);
2207 
2208  if (fullCommand)
2209  {
2210  if (OidIsValid(conForm->conrelid))
2211  {
2212  /*
2213  * Currently, callers want ALTER TABLE (without ONLY) for CHECK
2214  * constraints, and other types of constraints don't inherit
2215  * anyway so it doesn't matter whether we say ONLY or not. Someday
2216  * we might need to let callers specify whether to put ONLY in the
2217  * command.
2218  */
2219  appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
2220  generate_qualified_relation_name(conForm->conrelid),
2221  quote_identifier(NameStr(conForm->conname)));
2222  }
2223  else
2224  {
2225  /* Must be a domain constraint */
2226  Assert(OidIsValid(conForm->contypid));
2227  appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
2228  generate_qualified_type_name(conForm->contypid),
2229  quote_identifier(NameStr(conForm->conname)));
2230  }
2231  }
2232 
2233  switch (conForm->contype)
2234  {
2235  case CONSTRAINT_FOREIGN:
2236  {
2237  Datum val;
2238  bool isnull;
2239  const char *string;
2240 
2241  /* Start off the constraint definition */
2242  appendStringInfoString(&buf, "FOREIGN KEY (");
2243 
2244  /* Fetch and build referencing-column list */
2245  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2246  Anum_pg_constraint_conkey);
2247 
2248  decompile_column_index_array(val, conForm->conrelid, &buf);
2249 
2250  /* add foreign relation name */
2251  appendStringInfo(&buf, ") REFERENCES %s(",
2252  generate_relation_name(conForm->confrelid,
2253  NIL));
2254 
2255  /* Fetch and build referenced-column list */
2256  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2257  Anum_pg_constraint_confkey);
2258 
2259  decompile_column_index_array(val, conForm->confrelid, &buf);
2260 
2261  appendStringInfoChar(&buf, ')');
2262 
2263  /* Add match type */
2264  switch (conForm->confmatchtype)
2265  {
2266  case FKCONSTR_MATCH_FULL:
2267  string = " MATCH FULL";
2268  break;
2270  string = " MATCH PARTIAL";
2271  break;
2272  case FKCONSTR_MATCH_SIMPLE:
2273  string = "";
2274  break;
2275  default:
2276  elog(ERROR, "unrecognized confmatchtype: %d",
2277  conForm->confmatchtype);
2278  string = ""; /* keep compiler quiet */
2279  break;
2280  }
2281  appendStringInfoString(&buf, string);
2282 
2283  /* Add ON UPDATE and ON DELETE clauses, if needed */
2284  switch (conForm->confupdtype)
2285  {
2287  string = NULL; /* suppress default */
2288  break;
2290  string = "RESTRICT";
2291  break;
2293  string = "CASCADE";
2294  break;
2296  string = "SET NULL";
2297  break;
2299  string = "SET DEFAULT";
2300  break;
2301  default:
2302  elog(ERROR, "unrecognized confupdtype: %d",
2303  conForm->confupdtype);
2304  string = NULL; /* keep compiler quiet */
2305  break;
2306  }
2307  if (string)
2308  appendStringInfo(&buf, " ON UPDATE %s", string);
2309 
2310  switch (conForm->confdeltype)
2311  {
2313  string = NULL; /* suppress default */
2314  break;
2316  string = "RESTRICT";
2317  break;
2319  string = "CASCADE";
2320  break;
2322  string = "SET NULL";
2323  break;
2325  string = "SET DEFAULT";
2326  break;
2327  default:
2328  elog(ERROR, "unrecognized confdeltype: %d",
2329  conForm->confdeltype);
2330  string = NULL; /* keep compiler quiet */
2331  break;
2332  }
2333  if (string)
2334  appendStringInfo(&buf, " ON DELETE %s", string);
2335 
2336  /*
2337  * Add columns specified to SET NULL or SET DEFAULT if
2338  * provided.
2339  */
2340  val = SysCacheGetAttr(CONSTROID, tup,
2341  Anum_pg_constraint_confdelsetcols, &isnull);
2342  if (!isnull)
2343  {
2344  appendStringInfoString(&buf, " (");
2345  decompile_column_index_array(val, conForm->conrelid, &buf);
2346  appendStringInfoChar(&buf, ')');
2347  }
2348 
2349  break;
2350  }
2351  case CONSTRAINT_PRIMARY:
2352  case CONSTRAINT_UNIQUE:
2353  {
2354  Datum val;
2355  Oid indexId;
2356  int keyatts;
2357  HeapTuple indtup;
2358 
2359  /* Start off the constraint definition */
2360  if (conForm->contype == CONSTRAINT_PRIMARY)
2361  appendStringInfoString(&buf, "PRIMARY KEY ");
2362  else
2363  appendStringInfoString(&buf, "UNIQUE ");
2364 
2365  indexId = conForm->conindid;
2366 
2367  indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2368  if (!HeapTupleIsValid(indtup))
2369  elog(ERROR, "cache lookup failed for index %u", indexId);
2370  if (conForm->contype == CONSTRAINT_UNIQUE &&
2371  ((Form_pg_index) GETSTRUCT(indtup))->indnullsnotdistinct)
2372  appendStringInfoString(&buf, "NULLS NOT DISTINCT ");
2373 
2374  appendStringInfoChar(&buf, '(');
2375 
2376  /* Fetch and build target column list */
2377  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2378  Anum_pg_constraint_conkey);
2379 
2380  keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2381  if (conForm->conperiod)
2382  appendStringInfoString(&buf, " WITHOUT OVERLAPS");
2383 
2384  appendStringInfoChar(&buf, ')');
2385 
2386  /* Build including column list (from pg_index.indkeys) */
2387  val = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2388  Anum_pg_index_indnatts);
2389  if (DatumGetInt32(val) > keyatts)
2390  {
2391  Datum cols;
2392  Datum *keys;
2393  int nKeys;
2394  int j;
2395 
2396  appendStringInfoString(&buf, " INCLUDE (");
2397 
2398  cols = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2399  Anum_pg_index_indkey);
2400 
2402  &keys, NULL, &nKeys);
2403 
2404  for (j = keyatts; j < nKeys; j++)
2405  {
2406  char *colName;
2407 
2408  colName = get_attname(conForm->conrelid,
2409  DatumGetInt16(keys[j]), false);
2410  if (j > keyatts)
2411  appendStringInfoString(&buf, ", ");
2413  }
2414 
2415  appendStringInfoChar(&buf, ')');
2416  }
2417  ReleaseSysCache(indtup);
2418 
2419  /* XXX why do we only print these bits if fullCommand? */
2420  if (fullCommand && OidIsValid(indexId))
2421  {
2422  char *options = flatten_reloptions(indexId);
2423  Oid tblspc;
2424 
2425  if (options)
2426  {
2427  appendStringInfo(&buf, " WITH (%s)", options);
2428  pfree(options);
2429  }
2430 
2431  /*
2432  * Print the tablespace, unless it's the database default.
2433  * This is to help ALTER TABLE usage of this facility,
2434  * which needs this behavior to recreate exact catalog
2435  * state.
2436  */
2437  tblspc = get_rel_tablespace(indexId);
2438  if (OidIsValid(tblspc))
2439  appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2441  }
2442 
2443  break;
2444  }
2445  case CONSTRAINT_CHECK:
2446  {
2447  Datum val;
2448  char *conbin;
2449  char *consrc;
2450  Node *expr;
2451  List *context;
2452 
2453  /* Fetch constraint expression in parsetree form */
2454  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2455  Anum_pg_constraint_conbin);
2456 
2457  conbin = TextDatumGetCString(val);
2458  expr = stringToNode(conbin);
2459 
2460  /* Set up deparsing context for Var nodes in constraint */
2461  if (conForm->conrelid != InvalidOid)
2462  {
2463  /* relation constraint */
2464  context = deparse_context_for(get_relation_name(conForm->conrelid),
2465  conForm->conrelid);
2466  }
2467  else
2468  {
2469  /* domain constraint --- can't have Vars */
2470  context = NIL;
2471  }
2472 
2473  consrc = deparse_expression_pretty(expr, context, false, false,
2474  prettyFlags, 0);
2475 
2476  /*
2477  * Now emit the constraint definition, adding NO INHERIT if
2478  * necessary.
2479  *
2480  * There are cases where the constraint expression will be
2481  * fully parenthesized and we don't need the outer parens ...
2482  * but there are other cases where we do need 'em. Be
2483  * conservative for now.
2484  *
2485  * Note that simply checking for leading '(' and trailing ')'
2486  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2487  */
2488  appendStringInfo(&buf, "CHECK (%s)%s",
2489  consrc,
2490  conForm->connoinherit ? " NO INHERIT" : "");
2491  break;
2492  }
2493  case CONSTRAINT_NOTNULL:
2494  {
2496 
2498 
2499  appendStringInfo(&buf, "NOT NULL %s",
2500  quote_identifier(get_attname(conForm->conrelid,
2501  attnum, false)));
2502  if (((Form_pg_constraint) GETSTRUCT(tup))->connoinherit)
2503  appendStringInfoString(&buf, " NO INHERIT");
2504  break;
2505  }
2506 
2507  case CONSTRAINT_TRIGGER:
2508 
2509  /*
2510  * There isn't an ALTER TABLE syntax for creating a user-defined
2511  * constraint trigger, but it seems better to print something than
2512  * throw an error; if we throw error then this function couldn't
2513  * safely be applied to all rows of pg_constraint.
2514  */
2515  appendStringInfoString(&buf, "TRIGGER");
2516  break;
2517  case CONSTRAINT_EXCLUSION:
2518  {
2519  Oid indexOid = conForm->conindid;
2520  Datum val;
2521  Datum *elems;
2522  int nElems;
2523  int i;
2524  Oid *operators;
2525 
2526  /* Extract operator OIDs from the pg_constraint tuple */
2527  val = SysCacheGetAttrNotNull(CONSTROID, tup,
2528  Anum_pg_constraint_conexclop);
2529 
2531  &elems, NULL, &nElems);
2532 
2533  operators = (Oid *) palloc(nElems * sizeof(Oid));
2534  for (i = 0; i < nElems; i++)
2535  operators[i] = DatumGetObjectId(elems[i]);
2536 
2537  /* pg_get_indexdef_worker does the rest */
2538  /* suppress tablespace because pg_dump wants it that way */
2540  pg_get_indexdef_worker(indexOid,
2541  0,
2542  operators,
2543  false,
2544  false,
2545  false,
2546  false,
2547  prettyFlags,
2548  false));
2549  break;
2550  }
2551  default:
2552  elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2553  break;
2554  }
2555 
2556  if (conForm->condeferrable)
2557  appendStringInfoString(&buf, " DEFERRABLE");
2558  if (conForm->condeferred)
2559  appendStringInfoString(&buf, " INITIALLY DEFERRED");
2560  if (!conForm->convalidated)
2561  appendStringInfoString(&buf, " NOT VALID");
2562 
2563  /* Cleanup */
2564  systable_endscan(scandesc);
2565  table_close(relation, AccessShareLock);
2566 
2567  return buf.data;
2568 }
2569 
2570 
2571 /*
2572  * Convert an int16[] Datum into a comma-separated list of column names
2573  * for the indicated relation; append the list to buf. Returns the number
2574  * of keys.
2575  */
2576 static int
2577 decompile_column_index_array(Datum column_index_array, Oid relId,
2578  StringInfo buf)
2579 {
2580  Datum *keys;
2581  int nKeys;
2582  int j;
2583 
2584  /* Extract data from array of int16 */
2585  deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID,
2586  &keys, NULL, &nKeys);
2587 
2588  for (j = 0; j < nKeys; j++)
2589  {
2590  char *colName;
2591 
2592  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2593 
2594  if (j == 0)
2596  else
2597  appendStringInfo(buf, ", %s", quote_identifier(colName));
2598  }
2599 
2600  return nKeys;
2601 }
2602 
2603 
2604 /* ----------
2605  * pg_get_expr - Decompile an expression tree
2606  *
2607  * Input: an expression tree in nodeToString form, and a relation OID
2608  *
2609  * Output: reverse-listed expression
2610  *
2611  * Currently, the expression can only refer to a single relation, namely
2612  * the one specified by the second parameter. This is sufficient for
2613  * partial indexes, column default expressions, etc. We also support
2614  * Var-free expressions, for which the OID can be InvalidOid.
2615  *
2616  * If the OID is nonzero but not actually valid, don't throw an error,
2617  * just return NULL. This is a bit questionable, but it's what we've
2618  * done historically, and it can help avoid unwanted failures when
2619  * examining catalog entries for just-deleted relations.
2620  *
2621  * We expect this function to work, or throw a reasonably clean error,
2622  * for any node tree that can appear in a catalog pg_node_tree column.
2623  * Query trees, such as those appearing in pg_rewrite.ev_action, are
2624  * not supported. Nor are expressions in more than one relation, which
2625  * can appear in places like pg_rewrite.ev_qual.
2626  * ----------
2627  */
2628 Datum
2630 {
2631  text *expr = PG_GETARG_TEXT_PP(0);
2632  Oid relid = PG_GETARG_OID(1);
2633  text *result;
2634  int prettyFlags;
2635 
2636  prettyFlags = PRETTYFLAG_INDENT;
2637 
2638  result = pg_get_expr_worker(expr, relid, prettyFlags);
2639  if (result)
2640  PG_RETURN_TEXT_P(result);
2641  else
2642  PG_RETURN_NULL();
2643 }
2644 
2645 Datum
2647 {
2648  text *expr = PG_GETARG_TEXT_PP(0);
2649  Oid relid = PG_GETARG_OID(1);
2650  bool pretty = PG_GETARG_BOOL(2);
2651  text *result;
2652  int prettyFlags;
2653 
2654  prettyFlags = GET_PRETTY_FLAGS(pretty);
2655 
2656  result = pg_get_expr_worker(expr, relid, prettyFlags);
2657  if (result)
2658  PG_RETURN_TEXT_P(result);
2659  else
2660  PG_RETURN_NULL();
2661 }
2662 
2663 static text *
2664 pg_get_expr_worker(text *expr, Oid relid, int prettyFlags)
2665 {
2666  Node *node;
2667  Node *tst;
2668  Relids relids;
2669  List *context;
2670  char *exprstr;
2671  Relation rel = NULL;
2672  char *str;
2673 
2674  /* Convert input pg_node_tree (really TEXT) object to C string */
2675  exprstr = text_to_cstring(expr);
2676 
2677  /* Convert expression to node tree */
2678  node = (Node *) stringToNode(exprstr);
2679 
2680  pfree(exprstr);
2681 
2682  /*
2683  * Throw error if the input is a querytree rather than an expression tree.
2684  * While we could support queries here, there seems no very good reason
2685  * to. In most such catalog columns, we'll see a List of Query nodes, or
2686  * even nested Lists, so drill down to a non-List node before checking.
2687  */
2688  tst = node;
2689  while (tst && IsA(tst, List))
2690  tst = linitial((List *) tst);
2691  if (tst && IsA(tst, Query))
2692  ereport(ERROR,
2693  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2694  errmsg("input is a query, not an expression")));
2695 
2696  /*
2697  * Throw error if the expression contains Vars we won't be able to
2698  * deparse.
2699  */
2700  relids = pull_varnos(NULL, node);
2701  if (OidIsValid(relid))
2702  {
2703  if (!bms_is_subset(relids, bms_make_singleton(1)))
2704  ereport(ERROR,
2705  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2706  errmsg("expression contains variables of more than one relation")));
2707  }
2708  else
2709  {
2710  if (!bms_is_empty(relids))
2711  ereport(ERROR,
2712  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2713  errmsg("expression contains variables")));
2714  }
2715 
2716  /*
2717  * Prepare deparse context if needed. If we are deparsing with a relid,
2718  * we need to transiently open and lock the rel, to make sure it won't go
2719  * away underneath us. (set_relation_column_names would lock it anyway,
2720  * so this isn't really introducing any new behavior.)
2721  */
2722  if (OidIsValid(relid))
2723  {
2724  rel = try_relation_open(relid, AccessShareLock);
2725  if (rel == NULL)
2726  return NULL;
2727  context = deparse_context_for(RelationGetRelationName(rel), relid);
2728  }
2729  else
2730  context = NIL;
2731 
2732  /* Deparse */
2733  str = deparse_expression_pretty(node, context, false, false,
2734  prettyFlags, 0);
2735 
2736  if (rel != NULL)
2738 
2739  return string_to_text(str);
2740 }
2741 
2742 
2743 /* ----------
2744  * pg_get_userbyid - Get a user name by roleid and
2745  * fallback to 'unknown (OID=n)'
2746  * ----------
2747  */
2748 Datum
2750 {
2751  Oid roleid = PG_GETARG_OID(0);
2752  Name result;
2753  HeapTuple roletup;
2754  Form_pg_authid role_rec;
2755 
2756  /*
2757  * Allocate space for the result
2758  */
2759  result = (Name) palloc(NAMEDATALEN);
2760  memset(NameStr(*result), 0, NAMEDATALEN);
2761 
2762  /*
2763  * Get the pg_authid entry and print the result
2764  */
2765  roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2766  if (HeapTupleIsValid(roletup))
2767  {
2768  role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2769  *result = role_rec->rolname;
2770  ReleaseSysCache(roletup);
2771  }
2772  else
2773  sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2774 
2775  PG_RETURN_NAME(result);
2776 }
2777 
2778 
2779 /*
2780  * pg_get_serial_sequence
2781  * Get the name of the sequence used by an identity or serial column,
2782  * formatted suitably for passing to setval, nextval or currval.
2783  * First parameter is not treated as double-quoted, second parameter
2784  * is --- see documentation for reason.
2785  */
2786 Datum
2788 {
2789  text *tablename = PG_GETARG_TEXT_PP(0);
2790  text *columnname = PG_GETARG_TEXT_PP(1);
2791  RangeVar *tablerv;
2792  Oid tableOid;
2793  char *column;
2795  Oid sequenceId = InvalidOid;
2796  Relation depRel;
2797  ScanKeyData key[3];
2798  SysScanDesc scan;
2799  HeapTuple tup;
2800 
2801  /* Look up table name. Can't lock it - we might not have privileges. */
2802  tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2803  tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2804 
2805  /* Get the number of the column */
2806  column = text_to_cstring(columnname);
2807 
2808  attnum = get_attnum(tableOid, column);
2809  if (attnum == InvalidAttrNumber)
2810  ereport(ERROR,
2811  (errcode(ERRCODE_UNDEFINED_COLUMN),
2812  errmsg("column \"%s\" of relation \"%s\" does not exist",
2813  column, tablerv->relname)));
2814 
2815  /* Search the dependency table for the dependent sequence */
2816  depRel = table_open(DependRelationId, AccessShareLock);
2817 
2818  ScanKeyInit(&key[0],
2819  Anum_pg_depend_refclassid,
2820  BTEqualStrategyNumber, F_OIDEQ,
2821  ObjectIdGetDatum(RelationRelationId));
2822  ScanKeyInit(&key[1],
2823  Anum_pg_depend_refobjid,
2824  BTEqualStrategyNumber, F_OIDEQ,
2825  ObjectIdGetDatum(tableOid));
2826  ScanKeyInit(&key[2],
2827  Anum_pg_depend_refobjsubid,
2828  BTEqualStrategyNumber, F_INT4EQ,
2830 
2831  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2832  NULL, 3, key);
2833 
2834  while (HeapTupleIsValid(tup = systable_getnext(scan)))
2835  {
2836  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2837 
2838  /*
2839  * Look for an auto dependency (serial column) or internal dependency
2840  * (identity column) of a sequence on a column. (We need the relkind
2841  * test because indexes can also have auto dependencies on columns.)
2842  */
2843  if (deprec->classid == RelationRelationId &&
2844  deprec->objsubid == 0 &&
2845  (deprec->deptype == DEPENDENCY_AUTO ||
2846  deprec->deptype == DEPENDENCY_INTERNAL) &&
2847  get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2848  {
2849  sequenceId = deprec->objid;
2850  break;
2851  }
2852  }
2853 
2854  systable_endscan(scan);
2855  table_close(depRel, AccessShareLock);
2856 
2857  if (OidIsValid(sequenceId))
2858  {
2859  char *result;
2860 
2861  result = generate_qualified_relation_name(sequenceId);
2862 
2864  }
2865 
2866  PG_RETURN_NULL();
2867 }
2868 
2869 
2870 /*
2871  * pg_get_functiondef
2872  * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2873  * the specified function.
2874  *
2875  * Note: if you change the output format of this function, be careful not
2876  * to break psql's rules (in \ef and \sf) for identifying the start of the
2877  * function body. To wit: the function body starts on a line that begins with
2878  * "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
2879  */
2880 Datum
2882 {
2883  Oid funcid = PG_GETARG_OID(0);
2885  StringInfoData dq;
2886  HeapTuple proctup;
2887  Form_pg_proc proc;
2888  bool isfunction;
2889  Datum tmp;
2890  bool isnull;
2891  const char *prosrc;
2892  const char *name;
2893  const char *nsp;
2894  float4 procost;
2895  int oldlen;
2896 
2897  initStringInfo(&buf);
2898 
2899  /* Look up the function */
2900  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2901  if (!HeapTupleIsValid(proctup))
2902  PG_RETURN_NULL();
2903 
2904  proc = (Form_pg_proc) GETSTRUCT(proctup);
2905  name = NameStr(proc->proname);
2906 
2907  if (proc->prokind == PROKIND_AGGREGATE)
2908  ereport(ERROR,
2909  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2910  errmsg("\"%s\" is an aggregate function", name)));
2911 
2912  isfunction = (proc->prokind != PROKIND_PROCEDURE);
2913 
2914  /*
2915  * We always qualify the function name, to ensure the right function gets
2916  * replaced.
2917  */
2918  nsp = get_namespace_name_or_temp(proc->pronamespace);
2919  appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2920  isfunction ? "FUNCTION" : "PROCEDURE",
2922  (void) print_function_arguments(&buf, proctup, false, true);
2923  appendStringInfoString(&buf, ")\n");
2924  if (isfunction)
2925  {
2926  appendStringInfoString(&buf, " RETURNS ");
2927  print_function_rettype(&buf, proctup);
2928  appendStringInfoChar(&buf, '\n');
2929  }
2930 
2931  print_function_trftypes(&buf, proctup);
2932 
2933  appendStringInfo(&buf, " LANGUAGE %s\n",
2934  quote_identifier(get_language_name(proc->prolang, false)));
2935 
2936  /* Emit some miscellaneous options on one line */
2937  oldlen = buf.len;
2938 
2939  if (proc->prokind == PROKIND_WINDOW)
2940  appendStringInfoString(&buf, " WINDOW");
2941  switch (proc->provolatile)
2942  {
2943  case PROVOLATILE_IMMUTABLE:
2944  appendStringInfoString(&buf, " IMMUTABLE");
2945  break;
2946  case PROVOLATILE_STABLE:
2947  appendStringInfoString(&buf, " STABLE");
2948  break;
2949  case PROVOLATILE_VOLATILE:
2950  break;
2951  }
2952 
2953  switch (proc->proparallel)
2954  {
2955  case PROPARALLEL_SAFE:
2956  appendStringInfoString(&buf, " PARALLEL SAFE");
2957  break;
2958  case PROPARALLEL_RESTRICTED:
2959  appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2960  break;
2961  case PROPARALLEL_UNSAFE:
2962  break;
2963  }
2964 
2965  if (proc->proisstrict)
2966  appendStringInfoString(&buf, " STRICT");
2967  if (proc->prosecdef)
2968  appendStringInfoString(&buf, " SECURITY DEFINER");
2969  if (proc->proleakproof)
2970  appendStringInfoString(&buf, " LEAKPROOF");
2971 
2972  /* This code for the default cost and rows should match functioncmds.c */
2973  if (proc->prolang == INTERNALlanguageId ||
2974  proc->prolang == ClanguageId)
2975  procost = 1;
2976  else
2977  procost = 100;
2978  if (proc->procost != procost)
2979  appendStringInfo(&buf, " COST %g", proc->procost);
2980 
2981  if (proc->prorows > 0 && proc->prorows != 1000)
2982  appendStringInfo(&buf, " ROWS %g", proc->prorows);
2983 
2984  if (proc->prosupport)
2985  {
2986  Oid argtypes[1];
2987 
2988  /*
2989  * We should qualify the support function's name if it wouldn't be
2990  * resolved by lookup in the current search path.
2991  */
2992  argtypes[0] = INTERNALOID;
2993  appendStringInfo(&buf, " SUPPORT %s",
2994  generate_function_name(proc->prosupport, 1,
2995  NIL, argtypes,
2996  false, NULL, EXPR_KIND_NONE));
2997  }
2998 
2999  if (oldlen != buf.len)
3000  appendStringInfoChar(&buf, '\n');
3001 
3002  /* Emit any proconfig options, one per line */
3003  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
3004  if (!isnull)
3005  {
3006  ArrayType *a = DatumGetArrayTypeP(tmp);
3007  int i;
3008 
3009  Assert(ARR_ELEMTYPE(a) == TEXTOID);
3010  Assert(ARR_NDIM(a) == 1);
3011  Assert(ARR_LBOUND(a)[0] == 1);
3012 
3013  for (i = 1; i <= ARR_DIMS(a)[0]; i++)
3014  {
3015  Datum d;
3016 
3017  d = array_ref(a, 1, &i,
3018  -1 /* varlenarray */ ,
3019  -1 /* TEXT's typlen */ ,
3020  false /* TEXT's typbyval */ ,
3021  TYPALIGN_INT /* TEXT's typalign */ ,
3022  &isnull);
3023  if (!isnull)
3024  {
3025  char *configitem = TextDatumGetCString(d);
3026  char *pos;
3027 
3028  pos = strchr(configitem, '=');
3029  if (pos == NULL)
3030  continue;
3031  *pos++ = '\0';
3032 
3033  appendStringInfo(&buf, " SET %s TO ",
3034  quote_identifier(configitem));
3035 
3036  /*
3037  * Variables that are marked GUC_LIST_QUOTE were already fully
3038  * quoted by flatten_set_variable_args() before they were put
3039  * into the proconfig array. However, because the quoting
3040  * rules used there aren't exactly like SQL's, we have to
3041  * break the list value apart and then quote the elements as
3042  * string literals. (The elements may be double-quoted as-is,
3043  * but we can't just feed them to the SQL parser; it would do
3044  * the wrong thing with elements that are zero-length or
3045  * longer than NAMEDATALEN.)
3046  *
3047  * Variables that are not so marked should just be emitted as
3048  * simple string literals. If the variable is not known to
3049  * guc.c, we'll do that; this makes it unsafe to use
3050  * GUC_LIST_QUOTE for extension variables.
3051  */
3052  if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
3053  {
3054  List *namelist;
3055  ListCell *lc;
3056 
3057  /* Parse string into list of identifiers */
3058  if (!SplitGUCList(pos, ',', &namelist))
3059  {
3060  /* this shouldn't fail really */
3061  elog(ERROR, "invalid list syntax in proconfig item");
3062  }
3063  foreach(lc, namelist)
3064  {
3065  char *curname = (char *) lfirst(lc);
3066 
3067  simple_quote_literal(&buf, curname);
3068  if (lnext(namelist, lc))
3069  appendStringInfoString(&buf, ", ");
3070  }
3071  }
3072  else
3073  simple_quote_literal(&buf, pos);
3074  appendStringInfoChar(&buf, '\n');
3075  }
3076  }
3077  }
3078 
3079  /* And finally the function definition ... */
3080  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3081  if (proc->prolang == SQLlanguageId && !isnull)
3082  {
3083  print_function_sqlbody(&buf, proctup);
3084  }
3085  else
3086  {
3087  appendStringInfoString(&buf, "AS ");
3088 
3089  tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
3090  if (!isnull)
3091  {
3093  appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
3094  }
3095 
3096  tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosrc);
3097  prosrc = TextDatumGetCString(tmp);
3098 
3099  /*
3100  * We always use dollar quoting. Figure out a suitable delimiter.
3101  *
3102  * Since the user is likely to be editing the function body string, we
3103  * shouldn't use a short delimiter that he might easily create a
3104  * conflict with. Hence prefer "$function$"/"$procedure$", but extend
3105  * if needed.
3106  */
3107  initStringInfo(&dq);
3108  appendStringInfoChar(&dq, '$');
3109  appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
3110  while (strstr(prosrc, dq.data) != NULL)
3111  appendStringInfoChar(&dq, 'x');
3112  appendStringInfoChar(&dq, '$');
3113 
3114  appendBinaryStringInfo(&buf, dq.data, dq.len);
3115  appendStringInfoString(&buf, prosrc);
3116  appendBinaryStringInfo(&buf, dq.data, dq.len);
3117  }
3118 
3119  appendStringInfoChar(&buf, '\n');
3120 
3121  ReleaseSysCache(proctup);
3122 
3124 }
3125 
3126 /*
3127  * pg_get_function_arguments
3128  * Get a nicely-formatted list of arguments for a function.
3129  * This is everything that would go between the parentheses in
3130  * CREATE FUNCTION.
3131  */
3132 Datum
3134 {
3135  Oid funcid = PG_GETARG_OID(0);
3137  HeapTuple proctup;
3138 
3139  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3140  if (!HeapTupleIsValid(proctup))
3141  PG_RETURN_NULL();
3142 
3143  initStringInfo(&buf);
3144 
3145  (void) print_function_arguments(&buf, proctup, false, true);
3146 
3147  ReleaseSysCache(proctup);
3148 
3150 }
3151 
3152 /*
3153  * pg_get_function_identity_arguments
3154  * Get a formatted list of arguments for a function.
3155  * This is everything that would go between the parentheses in
3156  * ALTER FUNCTION, etc. In particular, don't print defaults.
3157  */
3158 Datum
3160 {
3161  Oid funcid = PG_GETARG_OID(0);
3163  HeapTuple proctup;
3164 
3165  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3166  if (!HeapTupleIsValid(proctup))
3167  PG_RETURN_NULL();
3168 
3169  initStringInfo(&buf);
3170 
3171  (void) print_function_arguments(&buf, proctup, false, false);
3172 
3173  ReleaseSysCache(proctup);
3174 
3176 }
3177 
3178 /*
3179  * pg_get_function_result
3180  * Get a nicely-formatted version of the result type of a function.
3181  * This is what would appear after RETURNS in CREATE FUNCTION.
3182  */
3183 Datum
3185 {
3186  Oid funcid = PG_GETARG_OID(0);
3188  HeapTuple proctup;
3189 
3190  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3191  if (!HeapTupleIsValid(proctup))
3192  PG_RETURN_NULL();
3193 
3194  if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
3195  {
3196  ReleaseSysCache(proctup);
3197  PG_RETURN_NULL();
3198  }
3199 
3200  initStringInfo(&buf);
3201 
3202  print_function_rettype(&buf, proctup);
3203 
3204  ReleaseSysCache(proctup);
3205 
3207 }
3208 
3209 /*
3210  * Guts of pg_get_function_result: append the function's return type
3211  * to the specified buffer.
3212  */
3213 static void
3215 {
3216  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3217  int ntabargs = 0;
3218  StringInfoData rbuf;
3219 
3220  initStringInfo(&rbuf);
3221 
3222  if (proc->proretset)
3223  {
3224  /* It might be a table function; try to print the arguments */
3225  appendStringInfoString(&rbuf, "TABLE(");
3226  ntabargs = print_function_arguments(&rbuf, proctup, true, false);
3227  if (ntabargs > 0)
3228  appendStringInfoChar(&rbuf, ')');
3229  else
3230  resetStringInfo(&rbuf);
3231  }
3232 
3233  if (ntabargs == 0)
3234  {
3235  /* Not a table function, so do the normal thing */
3236  if (proc->proretset)
3237  appendStringInfoString(&rbuf, "SETOF ");
3238  appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
3239  }
3240 
3241  appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
3242 }
3243 
3244 /*
3245  * Common code for pg_get_function_arguments and pg_get_function_result:
3246  * append the desired subset of arguments to buf. We print only TABLE
3247  * arguments when print_table_args is true, and all the others when it's false.
3248  * We print argument defaults only if print_defaults is true.
3249  * Function return value is the number of arguments printed.
3250  */
3251 static int
3253  bool print_table_args, bool print_defaults)
3254 {
3255  Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3256  int numargs;
3257  Oid *argtypes;
3258  char **argnames;
3259  char *argmodes;
3260  int insertorderbyat = -1;
3261  int argsprinted;
3262  int inputargno;
3263  int nlackdefaults;
3264  List *argdefaults = NIL;
3265  ListCell *nextargdefault = NULL;
3266  int i;
3267 
3268  numargs = get_func_arg_info(proctup,
3269  &argtypes, &argnames, &argmodes);
3270 
3271  nlackdefaults = numargs;
3272  if (print_defaults && proc->pronargdefaults > 0)
3273  {
3274  Datum proargdefaults;
3275  bool isnull;
3276 
3277  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3278  Anum_pg_proc_proargdefaults,
3279  &isnull);
3280  if (!isnull)
3281  {
3282  char *str;
3283 
3284  str = TextDatumGetCString(proargdefaults);
3285  argdefaults = castNode(List, stringToNode(str));
3286  pfree(str);
3287  nextargdefault = list_head(argdefaults);
3288  /* nlackdefaults counts only *input* arguments lacking defaults */
3289  nlackdefaults = proc->pronargs - list_length(argdefaults);
3290  }
3291  }
3292 
3293  /* Check for special treatment of ordered-set aggregates */
3294  if (proc->prokind == PROKIND_AGGREGATE)
3295  {
3296  HeapTuple aggtup;
3297  Form_pg_aggregate agg;
3298 
3299  aggtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(proc->oid));
3300  if (!HeapTupleIsValid(aggtup))
3301  elog(ERROR, "cache lookup failed for aggregate %u",
3302  proc->oid);
3303  agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3304  if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3305  insertorderbyat = agg->aggnumdirectargs;
3306  ReleaseSysCache(aggtup);
3307  }
3308 
3309  argsprinted = 0;
3310  inputargno = 0;
3311  for (i = 0; i < numargs; i++)
3312  {
3313  Oid argtype = argtypes[i];
3314  char *argname = argnames ? argnames[i] : NULL;
3315  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3316  const char *modename;
3317  bool isinput;
3318 
3319  switch (argmode)
3320  {
3321  case PROARGMODE_IN:
3322 
3323  /*
3324  * For procedures, explicitly mark all argument modes, so as
3325  * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
3326  */
3327  if (proc->prokind == PROKIND_PROCEDURE)
3328  modename = "IN ";
3329  else
3330  modename = "";
3331  isinput = true;
3332  break;
3333  case PROARGMODE_INOUT:
3334  modename = "INOUT ";
3335  isinput = true;
3336  break;
3337  case PROARGMODE_OUT:
3338  modename = "OUT ";
3339  isinput = false;
3340  break;
3341  case PROARGMODE_VARIADIC:
3342  modename = "VARIADIC ";
3343  isinput = true;
3344  break;
3345  case PROARGMODE_TABLE:
3346  modename = "";
3347  isinput = false;
3348  break;
3349  default:
3350  elog(ERROR, "invalid parameter mode '%c'", argmode);
3351  modename = NULL; /* keep compiler quiet */
3352  isinput = false;
3353  break;
3354  }
3355  if (isinput)
3356  inputargno++; /* this is a 1-based counter */
3357 
3358  if (print_table_args != (argmode == PROARGMODE_TABLE))
3359  continue;
3360 
3361  if (argsprinted == insertorderbyat)
3362  {
3363  if (argsprinted)
3364  appendStringInfoChar(buf, ' ');
3365  appendStringInfoString(buf, "ORDER BY ");
3366  }
3367  else if (argsprinted)
3368  appendStringInfoString(buf, ", ");
3369 
3370  appendStringInfoString(buf, modename);
3371  if (argname && argname[0])
3372  appendStringInfo(buf, "%s ", quote_identifier(argname));
3374  if (print_defaults && isinput && inputargno > nlackdefaults)
3375  {
3376  Node *expr;
3377 
3378  Assert(nextargdefault != NULL);
3379  expr = (Node *) lfirst(nextargdefault);
3380  nextargdefault = lnext(argdefaults, nextargdefault);
3381 
3382  appendStringInfo(buf, " DEFAULT %s",
3383  deparse_expression(expr, NIL, false, false));
3384  }
3385  argsprinted++;
3386 
3387  /* nasty hack: print the last arg twice for variadic ordered-set agg */
3388  if (argsprinted == insertorderbyat && i == numargs - 1)
3389  {
3390  i--;
3391  /* aggs shouldn't have defaults anyway, but just to be sure ... */
3392  print_defaults = false;
3393  }
3394  }
3395 
3396  return argsprinted;
3397 }
3398 
3399 static bool
3400 is_input_argument(int nth, const char *argmodes)
3401 {
3402  return (!argmodes
3403  || argmodes[nth] == PROARGMODE_IN
3404  || argmodes[nth] == PROARGMODE_INOUT
3405  || argmodes[nth] == PROARGMODE_VARIADIC);
3406 }
3407 
3408 /*
3409  * Append used transformed types to specified buffer
3410  */
3411 static void
3413 {
3414  Oid *trftypes;
3415  int ntypes;
3416 
3417  ntypes = get_func_trftypes(proctup, &trftypes);
3418  if (ntypes > 0)
3419  {
3420  int i;
3421 
3422  appendStringInfoString(buf, " TRANSFORM ");
3423  for (i = 0; i < ntypes; i++)
3424  {
3425  if (i != 0)
3426  appendStringInfoString(buf, ", ");
3427  appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3428  }
3429  appendStringInfoChar(buf, '\n');
3430  }
3431 }
3432 
3433 /*
3434  * Get textual representation of a function argument's default value. The
3435  * second argument of this function is the argument number among all arguments
3436  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3437  * how information_schema.sql uses it.
3438  */
3439 Datum
3441 {
3442  Oid funcid = PG_GETARG_OID(0);
3443  int32 nth_arg = PG_GETARG_INT32(1);
3444  HeapTuple proctup;
3445  Form_pg_proc proc;
3446  int numargs;
3447  Oid *argtypes;
3448  char **argnames;
3449  char *argmodes;
3450  int i;
3451  List *argdefaults;
3452  Node *node;
3453  char *str;
3454  int nth_inputarg;
3455  Datum proargdefaults;
3456  bool isnull;
3457  int nth_default;
3458 
3459  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3460  if (!HeapTupleIsValid(proctup))
3461  PG_RETURN_NULL();
3462 
3463  numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3464  if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3465  {
3466  ReleaseSysCache(proctup);
3467  PG_RETURN_NULL();
3468  }
3469 
3470  nth_inputarg = 0;
3471  for (i = 0; i < nth_arg; i++)
3472  if (is_input_argument(i, argmodes))
3473  nth_inputarg++;
3474 
3475  proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3476  Anum_pg_proc_proargdefaults,
3477  &isnull);
3478  if (isnull)
3479  {
3480  ReleaseSysCache(proctup);
3481  PG_RETURN_NULL();
3482  }
3483 
3484  str = TextDatumGetCString(proargdefaults);
3485  argdefaults = castNode(List, stringToNode(str));
3486  pfree(str);
3487 
3488  proc = (Form_pg_proc) GETSTRUCT(proctup);
3489 
3490  /*
3491  * Calculate index into proargdefaults: proargdefaults corresponds to the
3492  * last N input arguments, where N = pronargdefaults.
3493  */
3494  nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3495 
3496  if (nth_default < 0 || nth_default >= list_length(argdefaults))
3497  {
3498  ReleaseSysCache(proctup);
3499  PG_RETURN_NULL();
3500  }
3501  node = list_nth(argdefaults, nth_default);
3502  str = deparse_expression(node, NIL, false, false);
3503 
3504  ReleaseSysCache(proctup);
3505 
3507 }
3508 
3509 static void
3511 {
3512  int numargs;
3513  Oid *argtypes;
3514  char **argnames;
3515  char *argmodes;
3516  deparse_namespace dpns = {0};
3517  Datum tmp;
3518  Node *n;
3519 
3520  dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
3521  numargs = get_func_arg_info(proctup,
3522  &argtypes, &argnames, &argmodes);
3523  dpns.numargs = numargs;
3524  dpns.argnames = argnames;
3525 
3526  tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosqlbody);
3528 
3529  if (IsA(n, List))
3530  {
3531  List *stmts;
3532  ListCell *lc;
3533 
3534  stmts = linitial(castNode(List, n));
3535 
3536  appendStringInfoString(buf, "BEGIN ATOMIC\n");
3537 
3538  foreach(lc, stmts)
3539  {
3540  Query *query = lfirst_node(Query, lc);
3541 
3542  /* It seems advisable to get at least AccessShareLock on rels */
3543  AcquireRewriteLocks(query, false, false);
3544  get_query_def(query, buf, list_make1(&dpns), NULL, false,
3546  appendStringInfoChar(buf, ';');
3547  appendStringInfoChar(buf, '\n');
3548  }
3549 
3550  appendStringInfoString(buf, "END");
3551  }
3552  else
3553  {
3554  Query *query = castNode(Query, n);
3555 
3556  /* It seems advisable to get at least AccessShareLock on rels */
3557  AcquireRewriteLocks(query, false, false);
3558  get_query_def(query, buf, list_make1(&dpns), NULL, false,
3559  0, WRAP_COLUMN_DEFAULT, 0);
3560  }
3561 }
3562 
3563 Datum
3565 {
3566  Oid funcid = PG_GETARG_OID(0);
3568  HeapTuple proctup;
3569  bool isnull;
3570 
3571  initStringInfo(&buf);
3572 
3573  /* Look up the function */
3574  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3575  if (!HeapTupleIsValid(proctup))
3576  PG_RETURN_NULL();
3577 
3578  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3579  if (isnull)
3580  {
3581  ReleaseSysCache(proctup);
3582  PG_RETURN_NULL();
3583  }
3584 
3585  print_function_sqlbody(&buf, proctup);
3586 
3587  ReleaseSysCache(proctup);
3588 
3590 }
3591 
3592 
3593 /*
3594  * deparse_expression - General utility for deparsing expressions
3595  *
3596  * calls deparse_expression_pretty with all prettyPrinting disabled
3597  */
3598 char *
3599 deparse_expression(Node *expr, List *dpcontext,
3600  bool forceprefix, bool showimplicit)
3601 {
3602  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3603  showimplicit, 0, 0);
3604 }
3605 
3606 /* ----------
3607  * deparse_expression_pretty - General utility for deparsing expressions
3608  *
3609  * expr is the node tree to be deparsed. It must be a transformed expression
3610  * tree (ie, not the raw output of gram.y).
3611  *
3612  * dpcontext is a list of deparse_namespace nodes representing the context
3613  * for interpreting Vars in the node tree. It can be NIL if no Vars are
3614  * expected.
3615  *
3616  * forceprefix is true to force all Vars to be prefixed with their table names.
3617  *
3618  * showimplicit is true to force all implicit casts to be shown explicitly.
3619  *
3620  * Tries to pretty up the output according to prettyFlags and startIndent.
3621  *
3622  * The result is a palloc'd string.
3623  * ----------
3624  */
3625 static char *
3627  bool forceprefix, bool showimplicit,
3628  int prettyFlags, int startIndent)
3629 {
3631  deparse_context context;
3632 
3633  initStringInfo(&buf);
3634  context.buf = &buf;
3635  context.namespaces = dpcontext;
3636  context.windowClause = NIL;
3637  context.windowTList = NIL;
3638  context.varprefix = forceprefix;
3639  context.prettyFlags = prettyFlags;
3640  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3641  context.indentLevel = startIndent;
3642  context.special_exprkind = EXPR_KIND_NONE;
3643  context.appendparents = NULL;
3644 
3645  get_rule_expr(expr, &context, showimplicit);
3646 
3647  return buf.data;
3648 }
3649 
3650 /* ----------
3651  * deparse_context_for - Build deparse context for a single relation
3652  *
3653  * Given the reference name (alias) and OID of a relation, build deparsing
3654  * context for an expression referencing only that relation (as varno 1,
3655  * varlevelsup 0). This is sufficient for many uses of deparse_expression.
3656  * ----------
3657  */
3658 List *
3659 deparse_context_for(const char *aliasname, Oid relid)
3660 {
3661  deparse_namespace *dpns;
3662  RangeTblEntry *rte;
3663 
3664  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3665 
3666  /* Build a minimal RTE for the rel */
3667  rte = makeNode(RangeTblEntry);
3668  rte->rtekind = RTE_RELATION;
3669  rte->relid = relid;
3670  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3672  rte->alias = makeAlias(aliasname, NIL);
3673  rte->eref = rte->alias;
3674  rte->lateral = false;
3675  rte->inh = false;
3676  rte->inFromCl = true;
3677 
3678  /* Build one-element rtable */
3679  dpns->rtable = list_make1(rte);
3680  dpns->subplans = NIL;
3681  dpns->ctes = NIL;
3682  dpns->appendrels = NULL;
3683  set_rtable_names(dpns, NIL, NULL);
3685 
3686  /* Return a one-deep namespace stack */
3687  return list_make1(dpns);
3688 }
3689 
3690 /*
3691  * deparse_context_for_plan_tree - Build deparse context for a Plan tree
3692  *
3693  * When deparsing an expression in a Plan tree, we use the plan's rangetable
3694  * to resolve names of simple Vars. The initialization of column names for
3695  * this is rather expensive if the rangetable is large, and it'll be the same
3696  * for every expression in the Plan tree; so we do it just once and re-use
3697  * the result of this function for each expression. (Note that the result
3698  * is not usable until set_deparse_context_plan() is applied to it.)
3699  *
3700  * In addition to the PlannedStmt, pass the per-RTE alias names
3701  * assigned by a previous call to select_rtable_names_for_explain.
3702  */
3703 List *
3705 {
3706  deparse_namespace *dpns;
3707 
3708  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3709 
3710  /* Initialize fields that stay the same across the whole plan tree */
3711  dpns->rtable = pstmt->rtable;
3712  dpns->rtable_names = rtable_names;
3713  dpns->subplans = pstmt->subplans;
3714  dpns->ctes = NIL;
3715  if (pstmt->appendRelations)
3716  {
3717  /* Set up the array, indexed by child relid */
3718  int ntables = list_length(dpns->rtable);
3719  ListCell *lc;
3720 
3721  dpns->appendrels = (AppendRelInfo **)
3722  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3723  foreach(lc, pstmt->appendRelations)
3724  {
3725  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3726  Index crelid = appinfo->child_relid;
3727 
3728  Assert(crelid > 0 && crelid <= ntables);
3729  Assert(dpns->appendrels[crelid] == NULL);
3730  dpns->appendrels[crelid] = appinfo;
3731  }
3732  }
3733  else
3734  dpns->appendrels = NULL; /* don't need it */
3735 
3736  /*
3737  * Set up column name aliases. We will get rather bogus results for join
3738  * RTEs, but that doesn't matter because plan trees don't contain any join
3739  * alias Vars.
3740  */
3742 
3743  /* Return a one-deep namespace stack */
3744  return list_make1(dpns);
3745 }
3746 
3747 /*
3748  * set_deparse_context_plan - Specify Plan node containing expression
3749  *
3750  * When deparsing an expression in a Plan tree, we might have to resolve
3751  * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
3752  * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
3753  * can be resolved by drilling down into the left and right child plans.
3754  * Similarly, INDEX_VAR references can be resolved by reference to the
3755  * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
3756  * ForeignScan and CustomScan nodes. (Note that we don't currently support
3757  * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
3758  * for those, we can only deparse the indexqualorig fields, which won't
3759  * contain INDEX_VAR Vars.)
3760  *
3761  * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
3762  * the most-closely-nested first. This is needed to resolve PARAM_EXEC
3763  * Params. Note we assume that all the Plan nodes share the same rtable.
3764  *
3765  * Once this function has been called, deparse_expression() can be called on
3766  * subsidiary expression(s) of the specified Plan node. To deparse
3767  * expressions of a different Plan node in the same Plan tree, re-call this
3768  * function to identify the new parent Plan node.
3769  *
3770  * The result is the same List passed in; this is a notational convenience.
3771  */
3772 List *
3773 set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
3774 {
3775  deparse_namespace *dpns;
3776 
3777  /* Should always have one-entry namespace list for Plan deparsing */
3778  Assert(list_length(dpcontext) == 1);
3779  dpns = (deparse_namespace *) linitial(dpcontext);
3780 
3781  /* Set our attention on the specific plan node passed in */
3782  dpns->ancestors = ancestors;
3783  set_deparse_plan(dpns, plan);
3784 
3785  return dpcontext;
3786 }
3787 
3788 /*
3789  * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
3790  *
3791  * Determine the relation aliases we'll use during an EXPLAIN operation.
3792  * This is just a frontend to set_rtable_names. We have to expose the aliases
3793  * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
3794  */
3795 List *
3797 {
3798  deparse_namespace dpns;
3799 
3800  memset(&dpns, 0, sizeof(dpns));
3801  dpns.rtable = rtable;
3802  dpns.subplans = NIL;
3803  dpns.ctes = NIL;
3804  dpns.appendrels = NULL;
3805  set_rtable_names(&dpns, NIL, rels_used);
3806  /* We needn't bother computing column aliases yet */
3807 
3808  return dpns.rtable_names;
3809 }
3810 
3811 /*
3812  * set_rtable_names: select RTE aliases to be used in printing a query
3813  *
3814  * We fill in dpns->rtable_names with a list of names that is one-for-one with
3815  * the already-filled dpns->rtable list. Each RTE name is unique among those
3816  * in the new namespace plus any ancestor namespaces listed in
3817  * parent_namespaces.
3818  *
3819  * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
3820  *
3821  * Note that this function is only concerned with relation names, not column
3822  * names.
3823  */
3824 static void
3825 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
3826  Bitmapset *rels_used)
3827 {
3828  HASHCTL hash_ctl;
3829  HTAB *names_hash;
3830  NameHashEntry *hentry;
3831  bool found;
3832  int rtindex;
3833  ListCell *lc;
3834 
3835  dpns->rtable_names = NIL;
3836  /* nothing more to do if empty rtable */
3837  if (dpns->rtable == NIL)
3838  return;
3839 
3840  /*
3841  * We use a hash table to hold known names, so that this process is O(N)
3842  * not O(N^2) for N names.
3843  */
3844  hash_ctl.keysize = NAMEDATALEN;
3845  hash_ctl.entrysize = sizeof(NameHashEntry);
3846  hash_ctl.hcxt = CurrentMemoryContext;
3847  names_hash = hash_create("set_rtable_names names",
3848  list_length(dpns->rtable),
3849  &hash_ctl,
3851 
3852  /* Preload the hash table with names appearing in parent_namespaces */
3853  foreach(lc, parent_namespaces)
3854  {
3855  deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
3856  ListCell *lc2;
3857 
3858  foreach(lc2, olddpns->rtable_names)
3859  {
3860  char *oldname = (char *) lfirst(lc2);
3861 
3862  if (oldname == NULL)
3863  continue;
3864  hentry = (NameHashEntry *) hash_search(names_hash,
3865  oldname,
3866  HASH_ENTER,
3867  &found);
3868  /* we do not complain about duplicate names in parent namespaces */
3869  hentry->counter = 0;
3870  }
3871  }
3872 
3873  /* Now we can scan the rtable */
3874  rtindex = 1;
3875  foreach(lc, dpns->rtable)
3876  {
3877  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3878  char *refname;
3879 
3880  /* Just in case this takes an unreasonable amount of time ... */
3882 
3883  if (rels_used && !bms_is_member(rtindex, rels_used))
3884  {
3885  /* Ignore unreferenced RTE */
3886  refname = NULL;
3887  }
3888  else if (rte->alias)
3889  {
3890  /* If RTE has a user-defined alias, prefer that */
3891  refname = rte->alias->aliasname;
3892  }
3893  else if (rte->rtekind == RTE_RELATION)
3894  {
3895  /* Use the current actual name of the relation */
3896  refname = get_rel_name(rte->relid);
3897  }
3898  else if (rte->rtekind == RTE_JOIN)
3899  {
3900  /* Unnamed join has no refname */
3901  refname = NULL;
3902  }
3903  else
3904  {
3905  /* Otherwise use whatever the parser assigned */
3906  refname = rte->eref->aliasname;
3907  }
3908 
3909  /*
3910  * If the selected name isn't unique, append digits to make it so, and
3911  * make a new hash entry for it once we've got a unique name. For a
3912  * very long input name, we might have to truncate to stay within
3913  * NAMEDATALEN.
3914  */
3915  if (refname)
3916  {
3917  hentry = (NameHashEntry *) hash_search(names_hash,
3918  refname,
3919  HASH_ENTER,
3920  &found);
3921  if (found)
3922  {
3923  /* Name already in use, must choose a new one */
3924  int refnamelen = strlen(refname);
3925  char *modname = (char *) palloc(refnamelen + 16);
3926  NameHashEntry *hentry2;
3927 
3928  do
3929  {
3930  hentry->counter++;
3931  for (;;)
3932  {
3933  memcpy(modname, refname, refnamelen);
3934  sprintf(modname + refnamelen, "_%d", hentry->counter);
3935  if (strlen(modname) < NAMEDATALEN)
3936  break;
3937  /* drop chars from refname to keep all the digits */
3938  refnamelen = pg_mbcliplen(refname, refnamelen,
3939  refnamelen - 1);
3940  }
3941  hentry2 = (NameHashEntry *) hash_search(names_hash,
3942  modname,
3943  HASH_ENTER,
3944  &found);
3945  } while (found);
3946  hentry2->counter = 0; /* init new hash entry */
3947  refname = modname;
3948  }
3949  else
3950  {
3951  /* Name not previously used, need only initialize hentry */
3952  hentry->counter = 0;
3953  }
3954  }
3955 
3956  dpns->rtable_names = lappend(dpns->rtable_names, refname);
3957  rtindex++;
3958  }
3959 
3960  hash_destroy(names_hash);
3961 }
3962 
3963 /*
3964  * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
3965  *
3966  * For convenience, this is defined to initialize the deparse_namespace struct
3967  * from scratch.
3968  */
3969 static void
3971  List *parent_namespaces)
3972 {
3973  ListCell *lc;
3974  ListCell *lc2;
3975 
3976  /* Initialize *dpns and fill rtable/ctes links */
3977  memset(dpns, 0, sizeof(deparse_namespace));
3978  dpns->rtable = query->rtable;
3979  dpns->subplans = NIL;
3980  dpns->ctes = query->cteList;
3981  dpns->appendrels = NULL;
3982 
3983  /* Assign a unique relation alias to each RTE */
3984  set_rtable_names(dpns, parent_namespaces, NULL);
3985 
3986  /* Initialize dpns->rtable_columns to contain zeroed structs */
3987  dpns->rtable_columns = NIL;
3988  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3989  dpns->rtable_columns = lappend(dpns->rtable_columns,
3990  palloc0(sizeof(deparse_columns)));
3991 
3992  /* If it's a utility query, it won't have a jointree */
3993  if (query->jointree)
3994  {
3995  /* Detect whether global uniqueness of USING names is needed */
3996  dpns->unique_using =
3997  has_dangerous_join_using(dpns, (Node *) query->jointree);
3998 
3999  /*
4000  * Select names for columns merged by USING, via a recursive pass over
4001  * the query jointree.
4002  */
4003  set_using_names(dpns, (Node *) query->jointree, NIL);
4004  }
4005 
4006  /*
4007  * Now assign remaining column aliases for each RTE. We do this in a
4008  * linear scan of the rtable, so as to process RTEs whether or not they
4009  * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
4010  * etc). JOIN RTEs must be processed after their children, but this is
4011  * okay because they appear later in the rtable list than their children
4012  * (cf Asserts in identify_join_columns()).
4013  */
4014  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4015  {
4016  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4017  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4018 
4019  if (rte->rtekind == RTE_JOIN)
4020  set_join_column_names(dpns, rte, colinfo);
4021  else
4022  set_relation_column_names(dpns, rte, colinfo);
4023  }
4024 }
4025 
4026 /*
4027  * set_simple_column_names: fill in column aliases for non-query situations
4028  *
4029  * This handles EXPLAIN and cases where we only have relation RTEs. Without
4030  * a join tree, we can't do anything smart about join RTEs, but we don't
4031  * need to (note that EXPLAIN should never see join alias Vars anyway).
4032  * If we do hit a join RTE we'll just process it like a non-table base RTE.
4033  */
4034 static void
4036 {
4037  ListCell *lc;
4038  ListCell *lc2;
4039 
4040  /* Initialize dpns->rtable_columns to contain zeroed structs */
4041  dpns->rtable_columns = NIL;
4042  while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
4043  dpns->rtable_columns = lappend(dpns->rtable_columns,
4044  palloc0(sizeof(deparse_columns)));
4045 
4046  /* Assign unique column aliases within each RTE */
4047  forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4048  {
4049  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4050  deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4051 
4052  set_relation_column_names(dpns, rte, colinfo);
4053  }
4054 }
4055 
4056 /*
4057  * has_dangerous_join_using: search jointree for unnamed JOIN USING
4058  *
4059  * Merged columns of a JOIN USING may act differently from either of the input
4060  * columns, either because they are merged with COALESCE (in a FULL JOIN) or
4061  * because an implicit coercion of the underlying input column is required.
4062  * In such a case the column must be referenced as a column of the JOIN not as
4063  * a column of either input. And this is problematic if the join is unnamed
4064  * (alias-less): we cannot qualify the column's name with an RTE name, since
4065  * there is none. (Forcibly assigning an alias to the join is not a solution,
4066  * since that will prevent legal references to tables below the join.)
4067  * To ensure that every column in the query is unambiguously referenceable,
4068  * we must assign such merged columns names that are globally unique across
4069  * the whole query, aliasing other columns out of the way as necessary.
4070  *
4071  * Because the ensuing re-aliasing is fairly damaging to the readability of
4072  * the query, we don't do this unless we have to. So, we must pre-scan
4073  * the join tree to see if we have to, before starting set_using_names().
4074  */
4075 static bool
4077 {
4078  if (IsA(jtnode, RangeTblRef))
4079  {
4080  /* nothing to do here */
4081  }
4082  else if (IsA(jtnode, FromExpr))
4083  {
4084  FromExpr *f = (FromExpr *) jtnode;
4085  ListCell *lc;
4086 
4087  foreach(lc, f->fromlist)
4088  {
4089  if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
4090  return true;
4091  }
4092  }
4093  else if (IsA(jtnode, JoinExpr))
4094  {
4095  JoinExpr *j = (JoinExpr *) jtnode;
4096 
4097  /* Is it an unnamed JOIN with USING? */
4098  if (j->alias == NULL && j->usingClause)
4099  {
4100  /*
4101  * Yes, so check each join alias var to see if any of them are not
4102  * simple references to underlying columns. If so, we have a
4103  * dangerous situation and must pick unique aliases.
4104  */
4105  RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
4106 
4107  /* We need only examine the merged columns */
4108  for (int i = 0; i < jrte->joinmergedcols; i++)
4109  {
4110  Node *aliasvar = list_nth(jrte->joinaliasvars, i);
4111 
4112  if (!IsA(aliasvar, Var))
4113  return true;
4114  }
4115  }
4116 
4117  /* Nope, but inspect children */
4118  if (has_dangerous_join_using(dpns, j->larg))
4119  return true;
4120  if (has_dangerous_join_using(dpns, j->rarg))
4121  return true;
4122  }
4123  else
4124  elog(ERROR, "unrecognized node type: %d",
4125  (int) nodeTag(jtnode));
4126  return false;
4127 }
4128 
4129 /*
4130  * set_using_names: select column aliases to be used for merged USING columns
4131  *
4132  * We do this during a recursive descent of the query jointree.
4133  * dpns->unique_using must already be set to determine the global strategy.
4134  *
4135  * Column alias info is saved in the dpns->rtable_columns list, which is
4136  * assumed to be filled with pre-zeroed deparse_columns structs.
4137  *
4138  * parentUsing is a list of all USING aliases assigned in parent joins of
4139  * the current jointree node. (The passed-in list must not be modified.)
4140  */
4141 static void
4142 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
4143 {
4144  if (IsA(jtnode, RangeTblRef))
4145  {
4146  /* nothing to do now */
4147  }
4148  else if (IsA(jtnode, FromExpr))
4149  {
4150  FromExpr *f = (FromExpr *) jtnode;
4151  ListCell *lc;
4152 
4153  foreach(lc, f->fromlist)
4154  set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
4155  }
4156  else if (IsA(jtnode, JoinExpr))
4157  {
4158  JoinExpr *j = (JoinExpr *) jtnode;
4159  RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
4160  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
4161  int *leftattnos;
4162  int *rightattnos;
4163  deparse_columns *leftcolinfo;
4164  deparse_columns *rightcolinfo;
4165  int i;
4166  ListCell *lc;
4167 
4168  /* Get info about the shape of the join */
4169  identify_join_columns(j, rte, colinfo);
4170  leftattnos = colinfo->leftattnos;
4171  rightattnos = colinfo->rightattnos;
4172 
4173  /* Look up the not-yet-filled-in child deparse_columns structs */
4174  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4175  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4176 
4177  /*
4178  * If this join is unnamed, then we cannot substitute new aliases at
4179  * this level, so any name requirements pushed down to here must be
4180  * pushed down again to the children.
4181  */
4182  if (rte->alias == NULL)
4183  {
4184  for (i = 0; i < colinfo->num_cols; i++)
4185  {
4186  char *colname = colinfo->colnames[i];
4187 
4188  if (colname == NULL)
4189  continue;
4190 
4191  /* Push down to left column, unless it's a system column */
4192  if (leftattnos[i] > 0)
4193  {
4194  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4195  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4196  }
4197 
4198  /* Same on the righthand side */
4199  if (rightattnos[i] > 0)
4200  {
4201  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4202  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4203  }
4204  }
4205  }
4206 
4207  /*
4208  * If there's a USING clause, select the USING column names and push
4209  * those names down to the children. We have two strategies:
4210  *
4211  * If dpns->unique_using is true, we force all USING names to be
4212  * unique across the whole query level. In principle we'd only need
4213  * the names of dangerous USING columns to be globally unique, but to
4214  * safely assign all USING names in a single pass, we have to enforce
4215  * the same uniqueness rule for all of them. However, if a USING
4216  * column's name has been pushed down from the parent, we should use
4217  * it as-is rather than making a uniqueness adjustment. This is
4218  * necessary when we're at an unnamed join, and it creates no risk of
4219  * ambiguity. Also, if there's a user-written output alias for a
4220  * merged column, we prefer to use that rather than the input name;
4221  * this simplifies the logic and seems likely to lead to less aliasing
4222  * overall.
4223  *
4224  * If dpns->unique_using is false, we only need USING names to be
4225  * unique within their own join RTE. We still need to honor
4226  * pushed-down names, though.
4227  *
4228  * Though significantly different in results, these two strategies are
4229  * implemented by the same code, with only the difference of whether
4230  * to put assigned names into dpns->using_names.
4231  */
4232  if (j->usingClause)
4233  {
4234  /* Copy the input parentUsing list so we don't modify it */
4235  parentUsing = list_copy(parentUsing);
4236 
4237  /* USING names must correspond to the first join output columns */
4238  expand_colnames_array_to(colinfo, list_length(j->usingClause));
4239  i = 0;
4240  foreach(lc, j->usingClause)
4241  {
4242  char *colname = strVal(lfirst(lc));
4243 
4244  /* Assert it's a merged column */
4245  Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
4246 
4247  /* Adopt passed-down name if any, else select unique name */
4248  if (colinfo->colnames[i] != NULL)
4249  colname = colinfo->colnames[i];
4250  else
4251  {
4252  /* Prefer user-written output alias if any */
4253  if (rte->alias && i < list_length(rte->alias->colnames))
4254  colname = strVal(list_nth(rte->alias->colnames, i));
4255  /* Make it appropriately unique */
4256  colname = make_colname_unique(colname, dpns, colinfo);
4257  if (dpns->unique_using)
4258  dpns->using_names = lappend(dpns->using_names,
4259  colname);
4260  /* Save it as output column name, too */
4261  colinfo->colnames[i] = colname;
4262  }
4263 
4264  /* Remember selected names for use later */
4265  colinfo->usingNames = lappend(colinfo->usingNames, colname);
4266  parentUsing = lappend(parentUsing, colname);
4267 
4268  /* Push down to left column, unless it's a system column */
4269  if (leftattnos[i] > 0)
4270  {
4271  expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4272  leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4273  }
4274 
4275  /* Same on the righthand side */
4276  if (rightattnos[i] > 0)
4277  {
4278  expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4279  rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4280  }
4281 
4282  i++;
4283  }
4284  }
4285 
4286  /* Mark child deparse_columns structs with correct parentUsing info */
4287  leftcolinfo->parentUsing = parentUsing;
4288  rightcolinfo->parentUsing = parentUsing;
4289 
4290  /* Now recursively assign USING column names in children */
4291  set_using_names(dpns, j->larg, parentUsing);
4292  set_using_names(dpns, j->rarg, parentUsing);
4293  }
4294  else
4295  elog(ERROR, "unrecognized node type: %d",
4296  (int) nodeTag(jtnode));
4297 }
4298 
4299 /*
4300  * set_relation_column_names: select column aliases for a non-join RTE
4301  *
4302  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4303  * If any colnames entries are already filled in, those override local
4304  * choices.
4305  */
4306 static void
4308  deparse_columns *colinfo)
4309 {
4310  int ncolumns;
4311  char **real_colnames;
4312  bool changed_any;
4313  int noldcolumns;
4314  int i;
4315  int j;
4316 
4317  /*
4318  * Construct an array of the current "real" column names of the RTE.
4319  * real_colnames[] will be indexed by physical column number, with NULL
4320  * entries for dropped columns.
4321  */
4322  if (rte->rtekind == RTE_RELATION)
4323  {
4324  /* Relation --- look to the system catalogs for up-to-date info */
4325  Relation rel;
4326  TupleDesc tupdesc;
4327 
4328  rel = relation_open(rte->relid, AccessShareLock);
4329  tupdesc = RelationGetDescr(rel);
4330 
4331  ncolumns = tupdesc->natts;
4332  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4333 
4334  for (i = 0; i < ncolumns; i++)
4335  {
4336  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
4337 
4338  if (attr->attisdropped)
4339  real_colnames[i] = NULL;
4340  else
4341  real_colnames[i] = pstrdup(NameStr(attr->attname));
4342  }
4344  }
4345  else
4346  {
4347  /* Otherwise get the column names from eref or expandRTE() */
4348  List *colnames;
4349  ListCell *lc;
4350 
4351  /*
4352  * Functions returning composites have the annoying property that some
4353  * of the composite type's columns might have been dropped since the
4354  * query was parsed. If possible, use expandRTE() to handle that
4355  * case, since it has the tedious logic needed to find out about
4356  * dropped columns. However, if we're explaining a plan, then we
4357  * don't have rte->functions because the planner thinks that won't be
4358  * needed later, and that breaks expandRTE(). So in that case we have
4359  * to rely on rte->eref, which may lead us to report a dropped
4360  * column's old name; that seems close enough for EXPLAIN's purposes.
4361  *
4362  * For non-RELATION, non-FUNCTION RTEs, we can just look at rte->eref,
4363  * which should be sufficiently up-to-date: no other RTE types can
4364  * have columns get dropped from under them after parsing.
4365  */
4366  if (rte->rtekind == RTE_FUNCTION && rte->functions != NIL)
4367  {
4368  /* Since we're not creating Vars, rtindex etc. don't matter */
4369  expandRTE(rte, 1, 0, -1, true /* include dropped */ ,
4370  &colnames, NULL);
4371  }
4372  else
4373  colnames = rte->eref->colnames;
4374 
4375  ncolumns = list_length(colnames);
4376  real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4377 
4378  i = 0;
4379  foreach(lc, colnames)
4380  {
4381  /*
4382  * If the column name we find here is an empty string, then it's a
4383  * dropped column, so change to NULL.
4384  */
4385  char *cname = strVal(lfirst(lc));
4386 
4387  if (cname[0] == '\0')
4388  cname = NULL;
4389  real_colnames[i] = cname;
4390  i++;
4391  }
4392  }
4393 
4394  /*
4395  * Ensure colinfo->colnames has a slot for each column. (It could be long
4396  * enough already, if we pushed down a name for the last column.) Note:
4397  * it's possible that there are now more columns than there were when the
4398  * query was parsed, ie colnames could be longer than rte->eref->colnames.
4399  * We must assign unique aliases to the new columns too, else there could
4400  * be unresolved conflicts when the view/rule is reloaded.
4401  */
4402  expand_colnames_array_to(colinfo, ncolumns);
4403  Assert(colinfo->num_cols == ncolumns);
4404 
4405  /*
4406  * Make sufficiently large new_colnames and is_new_col arrays, too.
4407  *
4408  * Note: because we leave colinfo->num_new_cols zero until after the loop,
4409  * colname_is_unique will not consult that array, which is fine because it
4410  * would only be duplicate effort.
4411  */
4412  colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
4413  colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
4414 
4415  /*
4416  * Scan the columns, select a unique alias for each one, and store it in
4417  * colinfo->colnames and colinfo->new_colnames. The former array has NULL
4418  * entries for dropped columns, the latter omits them. Also mark
4419  * new_colnames entries as to whether they are new since parse time; this
4420  * is the case for entries beyond the length of rte->eref->colnames.
4421  */
4422  noldcolumns = list_length(rte->eref->colnames);
4423  changed_any = false;
4424  j = 0;
4425  for (i = 0; i < ncolumns; i++)
4426  {
4427  char *real_colname = real_colnames[i];
4428  char *colname = colinfo->colnames[i];
4429 
4430  /* Skip dropped columns */
4431  if (real_colname == NULL)
4432  {
4433  Assert(colname == NULL); /* colnames[i] is already NULL */
4434  continue;
4435  }
4436 
4437  /* If alias already assigned, that's what to use */
4438  if (colname == NULL)
4439  {
4440  /* If user wrote an alias, prefer that over real column name */
4441  if (rte->alias && i < list_length(rte->alias->colnames))
4442  colname = strVal(list_nth(rte->alias->colnames, i));
4443  else
4444  colname = real_colname;
4445 
4446  /* Unique-ify and insert into colinfo */
4447  colname = make_colname_unique(colname, dpns, colinfo);
4448 
4449  colinfo->colnames[i] = colname;
4450  }
4451 
4452  /* Put names of non-dropped columns in new_colnames[] too */
4453  colinfo->new_colnames[j] = colname;
4454  /* And mark them as new or not */
4455  colinfo->is_new_col[j] = (i >= noldcolumns);
4456  j++;
4457 
4458  /* Remember if any assigned aliases differ from "real" name */
4459  if (!changed_any && strcmp(colname, real_colname) != 0)
4460  changed_any = true;
4461  }
4462 
4463  /*
4464  * Set correct length for new_colnames[] array. (Note: if columns have
4465  * been added, colinfo->num_cols includes them, which is not really quite
4466  * right but is harmless, since any new columns must be at the end where
4467  * they won't affect varattnos of pre-existing columns.)
4468  */
4469  colinfo->num_new_cols = j;
4470 
4471  /*
4472  * For a relation RTE, we need only print the alias column names if any
4473  * are different from the underlying "real" names. For a function RTE,
4474  * always emit a complete column alias list; this is to protect against
4475  * possible instability of the default column names (eg, from altering
4476  * parameter names). For tablefunc RTEs, we never print aliases, because
4477  * the column names are part of the clause itself. For other RTE types,
4478  * print if we changed anything OR if there were user-written column
4479  * aliases (since the latter would be part of the underlying "reality").
4480  */
4481  if (rte->rtekind == RTE_RELATION)
4482  colinfo->printaliases = changed_any;
4483  else if (rte->rtekind == RTE_FUNCTION)
4484  colinfo->printaliases = true;
4485  else if (rte->rtekind == RTE_TABLEFUNC)
4486  colinfo->printaliases = false;
4487  else if (rte->alias && rte->alias->colnames != NIL)
4488  colinfo->printaliases = true;
4489  else
4490  colinfo->printaliases = changed_any;
4491 }
4492 
4493 /*
4494  * set_join_column_names: select column aliases for a join RTE
4495  *
4496  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4497  * If any colnames entries are already filled in, those override local
4498  * choices. Also, names for USING columns were already chosen by
4499  * set_using_names(). We further expect that column alias selection has been
4500  * completed for both input RTEs.
4501  */
4502 static void
4504  deparse_columns *colinfo)
4505 {
4506  deparse_columns *leftcolinfo;
4507  deparse_columns *rightcolinfo;
4508  bool changed_any;
4509  int noldcolumns;
4510  int nnewcolumns;
4511  Bitmapset *leftmerged = NULL;
4512  Bitmapset *rightmerged = NULL;
4513  int i;
4514  int j;
4515  int ic;
4516  int jc;
4517 
4518  /* Look up the previously-filled-in child deparse_columns structs */
4519  leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4520  rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4521 
4522  /*
4523  * Ensure colinfo->colnames has a slot for each column. (It could be long
4524  * enough already, if we pushed down a name for the last column.) Note:
4525  * it's possible that one or both inputs now have more columns than there
4526  * were when the query was parsed, but we'll deal with that below. We
4527  * only need entries in colnames for pre-existing columns.
4528  */
4529  noldcolumns = list_length(rte->eref->colnames);
4530  expand_colnames_array_to(colinfo, noldcolumns);
4531  Assert(colinfo->num_cols == noldcolumns);
4532 
4533  /*
4534  * Scan the join output columns, select an alias for each one, and store
4535  * it in colinfo->colnames. If there are USING columns, set_using_names()
4536  * already selected their names, so we can start the loop at the first
4537  * non-merged column.
4538  */
4539  changed_any = false;
4540  for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
4541  {
4542  char *colname = colinfo->colnames[i];
4543  char *real_colname;
4544 
4545  /* Join column must refer to at least one input column */
4546  Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
4547 
4548  /* Get the child column name */
4549  if (colinfo->leftattnos[i] > 0)
4550  real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
4551  else if (colinfo->rightattnos[i] > 0)
4552  real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
4553  else
4554  {
4555  /* We're joining system columns --- use eref name */
4556  real_colname = strVal(list_nth(rte->eref->colnames, i));
4557  }
4558 
4559  /* If child col has been dropped, no need to assign a join colname */
4560  if (real_colname == NULL)
4561  {
4562  colinfo->colnames[i] = NULL;
4563  continue;
4564  }
4565 
4566  /* In an unnamed join, just report child column names as-is */
4567  if (rte->alias == NULL)
4568  {
4569  colinfo->colnames[i] = real_colname;
4570  continue;
4571  }
4572 
4573  /* If alias already assigned, that's what to use */
4574  if (colname == NULL)
4575  {
4576  /* If user wrote an alias, prefer that over real column name */
4577  if (rte->alias && i < list_length(rte->alias->colnames))
4578  colname = strVal(list_nth(rte->alias->colnames, i));
4579  else
4580  colname = real_colname;
4581 
4582  /* Unique-ify and insert into colinfo */
4583  colname = make_colname_unique(colname, dpns, colinfo);
4584 
4585  colinfo->colnames[i] = colname;
4586  }
4587 
4588  /* Remember if any assigned aliases differ from "real" name */
4589  if (!changed_any && strcmp(colname, real_colname) != 0)
4590  changed_any = true;
4591  }
4592 
4593  /*
4594  * Calculate number of columns the join would have if it were re-parsed
4595  * now, and create storage for the new_colnames and is_new_col arrays.
4596  *
4597  * Note: colname_is_unique will be consulting new_colnames[] during the
4598  * loops below, so its not-yet-filled entries must be zeroes.
4599  */
4600  nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
4601  list_length(colinfo->usingNames);
4602  colinfo->num_new_cols = nnewcolumns;
4603  colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
4604  colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
4605 
4606  /*
4607  * Generating the new_colnames array is a bit tricky since any new columns
4608  * added since parse time must be inserted in the right places. This code
4609  * must match the parser, which will order a join's columns as merged
4610  * columns first (in USING-clause order), then non-merged columns from the
4611  * left input (in attnum order), then non-merged columns from the right
4612  * input (ditto). If one of the inputs is itself a join, its columns will
4613  * be ordered according to the same rule, which means newly-added columns
4614  * might not be at the end. We can figure out what's what by consulting
4615  * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
4616  *
4617  * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
4618  * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
4619  * meanings for the current child RTE.
4620  */
4621 
4622  /* Handle merged columns; they are first and can't be new */
4623  i = j = 0;
4624  while (i < noldcolumns &&
4625  colinfo->leftattnos[i] != 0 &&
4626  colinfo->rightattnos[i] != 0)
4627  {
4628  /* column name is already determined and known unique */
4629  colinfo->new_colnames[j] = colinfo->colnames[i];
4630  colinfo->is_new_col[j] = false;
4631 
4632  /* build bitmapsets of child attnums of merged columns */
4633  if (colinfo->leftattnos[i] > 0)
4634  leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
4635  if (colinfo->rightattnos[i] > 0)
4636  rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
4637 
4638  i++, j++;
4639  }
4640 
4641  /* Handle non-merged left-child columns */
4642  ic = 0;
4643  for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
4644  {
4645  char *child_colname = leftcolinfo->new_colnames[jc];
4646 
4647  if (!leftcolinfo->is_new_col[jc])
4648  {
4649  /* Advance ic to next non-dropped old column of left child */
4650  while (ic < leftcolinfo->num_cols &&
4651  leftcolinfo->colnames[ic] == NULL)
4652  ic++;
4653  Assert(ic < leftcolinfo->num_cols);
4654  ic++;
4655  /* If it is a merged column, we already processed it */
4656  if (bms_is_member(ic, leftmerged))
4657  continue;
4658  /* Else, advance i to the corresponding existing join column */
4659  while (i < colinfo->num_cols &&
4660  colinfo->colnames[i] == NULL)
4661  i++;
4662  Assert(i < colinfo->num_cols);
4663  Assert(ic == colinfo->leftattnos[i]);
4664  /* Use the already-assigned name of this column */
4665  colinfo->new_colnames[j] = colinfo->colnames[i];
4666  i++;
4667  }
4668  else
4669  {
4670  /*
4671  * Unique-ify the new child column name and assign, unless we're
4672  * in an unnamed join, in which case just copy
4673  */
4674  if (rte->alias != NULL)
4675  {
4676  colinfo->new_colnames[j] =
4677  make_colname_unique(child_colname, dpns, colinfo);
4678  if (!changed_any &&
4679  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4680  changed_any = true;
4681  }
4682  else
4683  colinfo->new_colnames[j] = child_colname;
4684  }
4685 
4686  colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
4687  j++;
4688  }
4689 
4690  /* Handle non-merged right-child columns in exactly the same way */
4691  ic = 0;
4692  for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
4693  {
4694  char *child_colname = rightcolinfo->new_colnames[jc];
4695 
4696  if (!rightcolinfo->is_new_col[jc])
4697  {
4698  /* Advance ic to next non-dropped old column of right child */
4699  while (ic < rightcolinfo->num_cols &&
4700  rightcolinfo->colnames[ic] == NULL)
4701  ic++;
4702  Assert(ic < rightcolinfo->num_cols);
4703  ic++;
4704  /* If it is a merged column, we already processed it */
4705  if (bms_is_member(ic, rightmerged))
4706  continue;
4707  /* Else, advance i to the corresponding existing join column */
4708  while (i < colinfo->num_cols &&
4709  colinfo->colnames[i] == NULL)
4710  i++;
4711  Assert(i < colinfo->num_cols);
4712  Assert(ic == colinfo->rightattnos[i]);
4713  /* Use the already-assigned name of this column */
4714  colinfo->new_colnames[j] = colinfo->colnames[i];
4715  i++;
4716  }
4717  else
4718  {
4719  /*
4720  * Unique-ify the new child column name and assign, unless we're
4721  * in an unnamed join, in which case just copy
4722  */
4723  if (rte->alias != NULL)
4724  {
4725  colinfo->new_colnames[j] =
4726  make_colname_unique(child_colname, dpns, colinfo);
4727  if (!changed_any &&
4728  strcmp(colinfo->new_colnames[j], child_colname) != 0)
4729  changed_any = true;
4730  }
4731  else
4732  colinfo->new_colnames[j] = child_colname;
4733  }
4734 
4735  colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
4736  j++;
4737  }
4738 
4739  /* Assert we processed the right number of columns */
4740 #ifdef USE_ASSERT_CHECKING
4741  while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
4742  i++;
4743  Assert(i == colinfo->num_cols);
4744  Assert(j == nnewcolumns);
4745 #endif
4746 
4747  /*
4748  * For a named join, print column aliases if we changed any from the child
4749  * names. Unnamed joins cannot print aliases.
4750  */
4751  if (rte->alias != NULL)
4752  colinfo->printaliases = changed_any;
4753  else
4754  colinfo->printaliases = false;
4755 }
4756 
4757 /*
4758  * colname_is_unique: is colname distinct from already-chosen column names?
4759  *
4760  * dpns is query-wide info, colinfo is for the column's RTE
4761  */
4762 static bool
4763 colname_is_unique(const char *colname, deparse_namespace *dpns,
4764  deparse_columns *colinfo)
4765 {
4766  int i;
4767  ListCell *lc;
4768 
4769  /* Check against already-assigned column aliases within RTE */
4770  for (i = 0; i < colinfo->num_cols; i++)
4771  {
4772  char *oldname = colinfo->colnames[i];
4773 
4774  if (oldname && strcmp(oldname, colname) == 0)
4775  return false;
4776  }
4777 
4778  /*
4779  * If we're building a new_colnames array, check that too (this will be
4780  * partially but not completely redundant with the previous checks)
4781  */
4782  for (i = 0; i < colinfo->num_new_cols; i++)
4783  {
4784  char *oldname = colinfo->new_colnames[i];
4785 
4786  if (oldname && strcmp(oldname, colname) == 0)
4787  return false;
4788  }
4789 
4790  /* Also check against USING-column names that must be globally unique */
4791  foreach(lc, dpns->using_names)
4792  {
4793  char *oldname = (char *) lfirst(lc);
4794 
4795  if (strcmp(oldname, colname) == 0)
4796  return false;
4797  }
4798 
4799  /* Also check against names already assigned for parent-join USING cols */
4800  foreach(lc, colinfo->parentUsing)
4801  {
4802  char *oldname = (char *) lfirst(lc);
4803 
4804  if (strcmp(oldname, colname) == 0)
4805  return false;
4806  }
4807 
4808  return true;
4809 }
4810 
4811 /*
4812  * make_colname_unique: modify colname if necessary to make it unique
4813  *
4814  * dpns is query-wide info, colinfo is for the column's RTE
4815  */
4816 static char *
4818  deparse_columns *colinfo)
4819 {
4820  /*
4821  * If the selected name isn't unique, append digits to make it so. For a
4822  * very long input name, we might have to truncate to stay within
4823  * NAMEDATALEN.
4824  */
4825  if (!colname_is_unique(colname, dpns, colinfo))
4826  {
4827  int colnamelen = strlen(colname);
4828  char *modname = (char *) palloc(colnamelen + 16);
4829  int i = 0;
4830 
4831  do
4832  {
4833  i++;
4834  for (;;)
4835  {
4836  memcpy(modname, colname, colnamelen);
4837  sprintf(modname + colnamelen, "_%d", i);
4838  if (strlen(modname) < NAMEDATALEN)
4839  break;
4840  /* drop chars from colname to keep all the digits */
4841  colnamelen = pg_mbcliplen(colname, colnamelen,
4842  colnamelen - 1);
4843  }
4844  } while (!colname_is_unique(modname, dpns, colinfo));
4845  colname = modname;
4846  }
4847  return colname;
4848 }
4849 
4850 /*
4851  * expand_colnames_array_to: make colinfo->colnames at least n items long
4852  *
4853  * Any added array entries are initialized to zero.
4854  */
4855 static void
4857 {
4858  if (n > colinfo->num_cols)
4859  {
4860  if (colinfo->colnames == NULL)
4861  colinfo->colnames = palloc0_array(char *, n);
4862  else
4863  colinfo->colnames = repalloc0_array(colinfo->colnames, char *, colinfo->num_cols, n);
4864  colinfo->num_cols = n;
4865  }
4866 }
4867 
4868 /*
4869  * identify_join_columns: figure out where columns of a join come from
4870  *
4871  * Fills the join-specific fields of the colinfo struct, except for
4872  * usingNames which is filled later.
4873  */
4874 static void
4876  deparse_columns *colinfo)
4877 {
4878  int numjoincols;
4879  int jcolno;
4880  int rcolno;
4881  ListCell *lc;
4882 
4883  /* Extract left/right child RT indexes */
4884  if (IsA(j->larg, RangeTblRef))
4885  colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
4886  else if (IsA(j->larg, JoinExpr))
4887  colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
4888  else
4889  elog(ERROR, "unrecognized node type in jointree: %d",
4890  (int) nodeTag(j->larg));
4891  if (IsA(j->rarg, RangeTblRef))
4892  colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
4893  else if (IsA(j->rarg, JoinExpr))
4894  colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
4895  else
4896  elog(ERROR, "unrecognized node type in jointree: %d",
4897  (int) nodeTag(j->rarg));
4898 
4899  /* Assert children will be processed earlier than join in second pass */
4900  Assert(colinfo->leftrti < j->rtindex);
4901  Assert(colinfo->rightrti < j->rtindex);
4902 
4903  /* Initialize result arrays with zeroes */
4904  numjoincols = list_length(jrte->joinaliasvars);
4905  Assert(numjoincols == list_length(jrte->eref->colnames));
4906  colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
4907  colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
4908 
4909  /*
4910  * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
4911  * Recall that the column(s) merged due to USING are the first column(s)
4912  * of the join output. We need not do anything special while scanning
4913  * joinleftcols, but while scanning joinrightcols we must distinguish
4914  * merged from unmerged columns.
4915  */
4916  jcolno = 0;
4917  foreach(lc, jrte->joinleftcols)
4918  {
4919  int leftattno = lfirst_int(lc);
4920 
4921  colinfo->leftattnos[jcolno++] = leftattno;
4922  }
4923  rcolno = 0;
4924  foreach(lc, jrte->joinrightcols)
4925  {
4926  int rightattno = lfirst_int(lc);
4927 
4928  if (rcolno < jrte->joinmergedcols) /* merged column? */
4929  colinfo->rightattnos[rcolno] = rightattno;
4930  else
4931  colinfo->rightattnos[jcolno++] = rightattno;
4932  rcolno++;
4933  }
4934  Assert(jcolno == numjoincols);
4935 }
4936 
4937 /*
4938  * get_rtable_name: convenience function to get a previously assigned RTE alias
4939  *
4940  * The RTE must belong to the topmost namespace level in "context".
4941  */
4942 static char *
4943 get_rtable_name(int rtindex, deparse_context *context)
4944 {
4946 
4947  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4948  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4949 }
4950 
4951 /*
4952  * set_deparse_plan: set up deparse_namespace to parse subexpressions
4953  * of a given Plan node
4954  *
4955  * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
4956  * and index_tlist fields. Caller must already have adjusted the ancestors
4957  * list if necessary. Note that the rtable, subplans, and ctes fields do
4958  * not need to change when shifting attention to different plan nodes in a
4959  * single plan tree.
4960  */
4961 static void
4963 {
4964  dpns->plan = plan;
4965 
4966  /*
4967  * We special-case Append and MergeAppend to pretend that the first child
4968  * plan is the OUTER referent; we have to interpret OUTER Vars in their
4969  * tlists according to one of the children, and the first one is the most
4970  * natural choice.
4971  */
4972  if (IsA(plan, Append))
4973  dpns->outer_plan = linitial(((Append *) plan)->appendplans);
4974  else if (IsA(plan, MergeAppend))
4975  dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
4976  else
4977  dpns->outer_plan = outerPlan(plan);
4978 
4979  if (dpns->outer_plan)
4980  dpns->outer_tlist = dpns->outer_plan->targetlist;
4981  else
4982  dpns->outer_tlist = NIL;
4983 
4984  /*
4985  * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
4986  * use OUTER because that could someday conflict with the normal meaning.)
4987  * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
4988  * For a WorkTableScan, locate the parent RecursiveUnion plan node and use
4989  * that as INNER referent.
4990  *
4991  * For MERGE, pretend the ModifyTable's source plan (its outer plan) is
4992  * INNER referent. This is the join from the target relation to the data
4993  * source, and all INNER_VAR Vars in other parts of the query refer to its
4994  * targetlist.
4995  *
4996  * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
4997  * excluded expression's tlist. (Similar to the SubqueryScan we don't want
4998  * to reuse OUTER, it's used for RETURNING in some modify table cases,
4999  * although not INSERT .. CONFLICT).
5000  */
5001  if (IsA(plan, SubqueryScan))
5002  dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
5003  else if (IsA(plan, CteScan))
5004  dpns->inner_plan = list_nth(dpns->subplans,
5005  ((CteScan *) plan)->ctePlanId - 1);
5006  else if (IsA(plan, WorkTableScan))
5007  dpns->inner_plan = find_recursive_union(dpns,
5008  (WorkTableScan *) plan);
5009  else if (IsA(plan, ModifyTable))
5010  {
5011  if (((ModifyTable *) plan)->operation == CMD_MERGE)
5012  dpns->inner_plan = outerPlan(plan);
5013  else
5014  dpns->inner_plan = plan;
5015  }
5016  else
5017  dpns->inner_plan = innerPlan(plan);
5018 
5019  if (IsA(plan, ModifyTable) && ((ModifyTable *) plan)->operation == CMD_INSERT)
5020  dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
5021  else if (dpns->inner_plan)
5022  dpns->inner_tlist = dpns->inner_plan->targetlist;
5023  else
5024  dpns->inner_tlist = NIL;
5025 
5026  /* Set up referent for INDEX_VAR Vars, if needed */
5027  if (IsA(plan, IndexOnlyScan))
5028  dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
5029  else if (IsA(plan, ForeignScan))
5030  dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
5031  else if (IsA(plan, CustomScan))
5032  dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
5033  else
5034  dpns->index_tlist = NIL;
5035 }
5036 
5037 /*
5038  * Locate the ancestor plan node that is the RecursiveUnion generating
5039  * the WorkTableScan's work table. We can match on wtParam, since that
5040  * should be unique within the plan tree.
5041  */
5042 static Plan *
5044 {
5045  ListCell *lc;
5046 
5047  foreach(lc, dpns->ancestors)
5048  {
5049  Plan *ancestor = (Plan *) lfirst(lc);
5050 
5051  if (IsA(ancestor, RecursiveUnion) &&
5052  ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
5053  return ancestor;
5054  }
5055  elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
5056  wtscan->wtParam);
5057  return NULL;
5058 }
5059 
5060 /*
5061  * push_child_plan: temporarily transfer deparsing attention to a child plan
5062  *
5063  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
5064  * deparse context in case the referenced expression itself uses
5065  * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
5066  * affecting levelsup issues (although in a Plan tree there really shouldn't
5067  * be any).
5068  *
5069  * Caller must provide a local deparse_namespace variable to save the
5070  * previous state for pop_child_plan.
5071  */
5072 static void
5074  deparse_namespace *save_dpns)
5075 {
5076  /* Save state for restoration later */
5077  *save_dpns = *dpns;
5078 
5079  /* Link current plan node into ancestors list */
5080  dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
5081 
5082  /* Set attention on selected child */
5083  set_deparse_plan(dpns, plan);
5084 }
5085 
5086 /*
5087  * pop_child_plan: undo the effects of push_child_plan
5088  */
5089 static void
5091 {
5092  List *ancestors;
5093 
5094  /* Get rid of ancestors list cell added by push_child_plan */
5095  ancestors = list_delete_first(dpns->ancestors);
5096 
5097  /* Restore fields changed by push_child_plan */
5098  *dpns = *save_dpns;
5099 
5100  /* Make sure dpns->ancestors is right (may be unnecessary) */
5101  dpns->ancestors = ancestors;
5102 }
5103 
5104 /*
5105  * push_ancestor_plan: temporarily transfer deparsing attention to an
5106  * ancestor plan
5107  *
5108  * When expanding a Param reference, we must adjust the deparse context
5109  * to match the plan node that contains the expression being printed;
5110  * otherwise we'd fail if that expression itself contains a Param or
5111  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
5112  *
5113  * The target ancestor is conveniently identified by the ListCell holding it
5114  * in dpns->ancestors.
5115  *
5116  * Caller must provide a local deparse_namespace variable to save the
5117  * previous state for pop_ancestor_plan.
5118  */
5119 static void
5121  deparse_namespace *save_dpns)
5122 {
5123  Plan *plan = (Plan *) lfirst(ancestor_cell);
5124 
5125  /* Save state for restoration later */
5126  *save_dpns = *dpns;
5127 
5128  /* Build a new ancestor list with just this node's ancestors */
5129  dpns->ancestors =
5130  list_copy_tail(dpns->ancestors,
5131  list_cell_number(dpns->ancestors, ancestor_cell) + 1);
5132 
5133  /* Set attention on selected ancestor */
5134  set_deparse_plan(dpns, plan);
5135 }
5136 
5137 /*
5138  * pop_ancestor_plan: undo the effects of push_ancestor_plan
5139  */
5140 static void
5142 {
5143  /* Free the ancestor list made in push_ancestor_plan */
5144  list_free(dpns->ancestors);
5145 
5146  /* Restore fields changed by push_ancestor_plan */
5147  *dpns = *save_dpns;
5148 }
5149 
5150 
5151 /* ----------
5152  * make_ruledef - reconstruct the CREATE RULE command
5153  * for a given pg_rewrite tuple
5154  * ----------
5155  */
5156 static void
5158  int prettyFlags)
5159 {
5160  char *rulename;
5161  char ev_type;
5162  Oid ev_class;
5163  bool is_instead;
5164  char *ev_qual;
5165  char *ev_action;
5166  List *actions;
5167  Relation ev_relation;
5168  TupleDesc viewResultDesc = NULL;
5169  int fno;
5170  Datum dat;
5171  bool isnull;
5172 
5173  /*
5174  * Get the attribute values from the rules tuple
5175  */
5176  fno = SPI_fnumber(rulettc, "rulename");
5177  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5178  Assert(!isnull);
5179  rulename = NameStr(*(DatumGetName(dat)));
5180 
5181  fno = SPI_fnumber(rulettc, "ev_type");
5182  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5183  Assert(!isnull);
5184  ev_type = DatumGetChar(dat);
5185 
5186  fno = SPI_fnumber(rulettc, "ev_class");
5187  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5188  Assert(!isnull);
5189  ev_class = DatumGetObjectId(dat);
5190 
5191  fno = SPI_fnumber(rulettc, "is_instead");
5192  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5193  Assert(!isnull);
5194  is_instead = DatumGetBool(dat);
5195 
5196  fno = SPI_fnumber(rulettc, "ev_qual");
5197  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5198  Assert(ev_qual != NULL);
5199 
5200  fno = SPI_fnumber(rulettc, "ev_action");
5201  ev_action = SPI_getvalue(ruletup, rulettc, fno);
5202  Assert(ev_action != NULL);
5203  actions = (List *) stringToNode(ev_action);
5204  if (actions == NIL)
5205  elog(ERROR, "invalid empty ev_action list");
5206 
5207  ev_relation = table_open(ev_class, AccessShareLock);
5208 
5209  /*
5210  * Build the rules definition text
5211  */
5212  appendStringInfo(buf, "CREATE RULE %s AS",
5213  quote_identifier(rulename));
5214 
5215  if (prettyFlags & PRETTYFLAG_INDENT)
5216  appendStringInfoString(buf, "\n ON ");
5217  else
5218  appendStringInfoString(buf, " ON ");
5219 
5220  /* The event the rule is fired for */
5221  switch (ev_type)
5222  {
5223  case '1':
5224  appendStringInfoString(buf, "SELECT");
5225  viewResultDesc = RelationGetDescr(ev_relation);
5226  break;
5227 
5228  case '2':
5229  appendStringInfoString(buf, "UPDATE");
5230  break;
5231 
5232  case '3':
5233  appendStringInfoString(buf, "INSERT");
5234  break;
5235 
5236  case '4':
5237  appendStringInfoString(buf, "DELETE");
5238  break;
5239 
5240  default:
5241  ereport(ERROR,
5242  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5243  errmsg("rule \"%s\" has unsupported event type %d",
5244  rulename, ev_type)));
5245  break;
5246  }
5247 
5248  /* The relation the rule is fired on */
5249  appendStringInfo(buf, " TO %s",
5250  (prettyFlags & PRETTYFLAG_SCHEMA) ?
5251  generate_relation_name(ev_class, NIL) :
5253 
5254  /* If the rule has an event qualification, add it */
5255  if (strcmp(ev_qual, "<>") != 0)
5256  {
5257  Node *qual;
5258  Query *query;
5259  deparse_context context;
5260  deparse_namespace dpns;
5261 
5262  if (prettyFlags & PRETTYFLAG_INDENT)
5263  appendStringInfoString(buf, "\n ");
5264  appendStringInfoString(buf, " WHERE ");
5265 
5266  qual = stringToNode(ev_qual);
5267 
5268  /*
5269  * We need to make a context for recognizing any Vars in the qual
5270  * (which can only be references to OLD and NEW). Use the rtable of
5271  * the first query in the action list for this purpose.
5272  */
5273  query = (Query *) linitial(actions);
5274 
5275  /*
5276  * If the action is INSERT...SELECT, OLD/NEW have been pushed down
5277  * into the SELECT, and that's what we need to look at. (Ugly kluge
5278  * ... try to fix this when we redesign querytrees.)
5279  */
5280  query = getInsertSelectQuery(query, NULL);
5281 
5282  /* Must acquire locks right away; see notes in get_query_def() */
5283  AcquireRewriteLocks(query, false, false);
5284 
5285  context.buf = buf;
5286  context.namespaces = list_make1(&dpns);
5287  context.windowClause = NIL;
5288  context.windowTList = NIL;
5289  context.varprefix = (list_length(query->rtable) != 1);
5290  context.prettyFlags = prettyFlags;
5291  context.wrapColumn = WRAP_COLUMN_DEFAULT;
5292  context.indentLevel = PRETTYINDENT_STD;
5293  context.special_exprkind = EXPR_KIND_NONE;
5294  context.appendparents = NULL;
5295 
5296  set_deparse_for_query(&dpns, query, NIL);
5297 
5298  get_rule_expr(qual, &context, false);
5299  }
5300 
5301  appendStringInfoString(buf, " DO ");
5302 
5303  /* The INSTEAD keyword (if so) */
5304  if (is_instead)
5305  appendStringInfoString(buf, "INSTEAD ");
5306 
5307  /* Finally the rules actions */
5308  if (list_length(actions) > 1)
5309  {
5310  ListCell *action;
5311  Query *query;
5312 
5313  appendStringInfoChar(buf, '(');
5314  foreach(action, actions)
5315  {
5316  query = (Query *) lfirst(action);
5317  get_query_def(query, buf, NIL, viewResultDesc, true,
5318  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5319  if (prettyFlags)
5320  appendStringInfoString(buf, ";\n");
5321  else
5322  appendStringInfoString(buf, "; ");
5323  }
5324  appendStringInfoString(buf, ");");
5325  }
5326  else
5327  {
5328  Query *query;
5329 
5330  query = (Query *) linitial(actions);
5331  get_query_def(query, buf, NIL, viewResultDesc, true,
5332  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5333  appendStringInfoChar(buf, ';');
5334  }
5335 
5336  table_close(ev_relation, AccessShareLock);
5337 }
5338 
5339 
5340 /* ----------
5341  * make_viewdef - reconstruct the SELECT part of a
5342  * view rewrite rule
5343  * ----------
5344  */
5345 static void
5347  int prettyFlags, int wrapColumn)
5348 {
5349  Query *query;
5350  char ev_type;
5351  Oid ev_class;
5352  bool is_instead;
5353  char *ev_qual;
5354  char *ev_action;
5355  List *actions;
5356  Relation ev_relation;
5357  int fno;
5358  Datum dat;
5359  bool isnull;
5360 
5361  /*
5362  * Get the attribute values from the rules tuple
5363  */
5364  fno = SPI_fnumber(rulettc, "ev_type");
5365  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5366  Assert(!isnull);
5367  ev_type = DatumGetChar(dat);
5368 
5369  fno = SPI_fnumber(rulettc, "ev_class");
5370  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5371  Assert(!isnull);
5372  ev_class = DatumGetObjectId(dat);
5373 
5374  fno = SPI_fnumber(rulettc, "is_instead");
5375  dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5376  Assert(!isnull);
5377  is_instead = DatumGetBool(dat);
5378 
5379  fno = SPI_fnumber(rulettc, "ev_qual");
5380  ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5381  Assert(ev_qual != NULL);
5382 
5383  fno = SPI_fnumber(rulettc, "ev_action");
5384  ev_action = SPI_getvalue(ruletup, rulettc, fno);
5385  Assert(ev_action != NULL);
5386  actions = (List *) stringToNode(ev_action);
5387 
5388  if (list_length(actions) != 1)
5389  {
5390  /* keep output buffer empty and leave */
5391  return;
5392  }
5393 
5394  query = (Query *) linitial(actions);
5395 
5396  if (ev_type != '1' || !is_instead ||
5397  strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
5398  {
5399  /* keep output buffer empty and leave */
5400  return;
5401  }
5402 
5403  ev_relation = table_open(ev_class, AccessShareLock);
5404 
5405  get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
5406  prettyFlags, wrapColumn, 0);
5407  appendStringInfoChar(buf, ';');
5408 
5409  table_close(ev_relation, AccessShareLock);
5410 }
5411 
5412 
5413 /* ----------
5414  * get_query_def - Parse back one query parsetree
5415  *
5416  * query: parsetree to be displayed
5417  * buf: output text is appended to buf
5418  * parentnamespace: list (initially empty) of outer-level deparse_namespace's
5419  * resultDesc: if not NULL, the output tuple descriptor for the view
5420  * represented by a SELECT query. We use the column names from it
5421  * to label SELECT output columns, in preference to names in the query
5422  * colNamesVisible: true if the surrounding context cares about the output
5423  * column names at all (as, for example, an EXISTS() context does not);
5424  * when false, we can suppress dummy column labels such as "?column?"
5425  * prettyFlags: bitmask of PRETTYFLAG_XXX options
5426  * wrapColumn: maximum line length, or -1 to disable wrapping
5427  * startIndent: initial indentation amount
5428  * ----------
5429  */
5430 static void
5431 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
5432  TupleDesc resultDesc, bool colNamesVisible,
5433  int prettyFlags, int wrapColumn, int startIndent)
5434 {
5435  deparse_context context;
5436  deparse_namespace dpns;
5437 
5438  /* Guard against excessively long or deeply-nested queries */
5441 
5442  /*
5443  * Before we begin to examine the query, acquire locks on referenced
5444  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5445  * consistent results. Note we assume it's OK to scribble on the passed
5446  * querytree!
5447  *
5448  * We are only deparsing the query (we are not about to execute it), so we
5449  * only need AccessShareLock on the relations it mentions.
5450  */
5451  AcquireRewriteLocks(query, false, false);
5452 
5453  context.buf = buf;
5454  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5455  context.windowClause = NIL;
5456  context.windowTList = NIL;
5457  context.varprefix = (parentnamespace != NIL ||
5458  list_length(query->rtable) != 1);
5459  context.prettyFlags = prettyFlags;
5460  context.wrapColumn = wrapColumn;
5461  context.indentLevel = startIndent;
5462  context.special_exprkind = EXPR_KIND_NONE;
5463  context.appendparents = NULL;
5464 
5465  set_deparse_for_query(&dpns, query, parentnamespace);
5466 
5467  switch (query->commandType)
5468  {
5469  case CMD_SELECT:
5470  get_select_query_def(query, &context, resultDesc, colNamesVisible);
5471  break;
5472 
5473  case CMD_UPDATE:
5474  get_update_query_def(query, &context, colNamesVisible);
5475  break;
5476 
5477  case CMD_INSERT:
5478  get_insert_query_def(query, &context, colNamesVisible);
5479  break;
5480 
5481  case CMD_DELETE:
5482  get_delete_query_def(query, &context, colNamesVisible);
5483  break;
5484 
5485  case CMD_MERGE:
5486  get_merge_query_def(query, &context, colNamesVisible);
5487  break;
5488 
5489  case CMD_NOTHING:
5490  appendStringInfoString(buf, "NOTHING");
5491  break;
5492 
5493  case CMD_UTILITY:
5494  get_utility_query_def(query, &context);
5495  break;
5496 
5497  default:
5498  elog(ERROR, "unrecognized query command type: %d",
5499  query->commandType);
5500  break;
5501  }
5502 }
5503 
5504 /* ----------
5505  * get_values_def - Parse back a VALUES list
5506  * ----------
5507  */
5508 static void
5509 get_values_def(List *values_lists, deparse_context *context)
5510 {
5511  StringInfo buf = context->buf;
5512  bool first_list = true;
5513  ListCell *vtl;
5514 
5515  appendStringInfoString(buf, "VALUES ");
5516 
5517  foreach(vtl, values_lists)
5518  {
5519  List *sublist = (List *) lfirst(vtl);
5520  bool first_col = true;
5521  ListCell *lc;
5522 
5523  if (first_list)
5524  first_list = false;
5525  else
5526  appendStringInfoString(buf, ", ");
5527 
5528  appendStringInfoChar(buf, '(');
5529  foreach(lc, sublist)
5530  {
5531  Node *col = (Node *) lfirst(lc);
5532 
5533  if (first_col)
5534  first_col = false;
5535  else
5536  appendStringInfoChar(buf, ',');
5537 
5538  /*
5539  * Print the value. Whole-row Vars need special treatment.
5540  */
5541  get_rule_expr_toplevel(col, context, false);
5542  }
5543  appendStringInfoChar(buf, ')');
5544  }
5545 }
5546 
5547 /* ----------
5548  * get_with_clause - Parse back a WITH clause
5549  * ----------
5550  */
5551 static void
5553 {
5554  StringInfo buf = context->buf;
5555  const char *sep;
5556  ListCell *l;
5557 
5558  if (query->cteList == NIL)
5559  return;
5560 
5561  if (PRETTY_INDENT(context))
5562  {
5563  context->indentLevel += PRETTYINDENT_STD;
5564  appendStringInfoChar(buf, ' ');
5565  }
5566 
5567  if (query->hasRecursive)
5568  sep = "WITH RECURSIVE ";
5569  else
5570  sep = "WITH ";
5571  foreach(l, query->cteList)
5572  {
5573  CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
5574 
5577  if (cte->aliascolnames)
5578  {
5579  bool first = true;
5580  ListCell *col;
5581 
5582  appendStringInfoChar(buf, '(');
5583  foreach(col, cte->aliascolnames)
5584  {
5585  if (first)
5586  first = false;
5587  else
5588  appendStringInfoString(buf, ", ");
5590  quote_identifier(strVal(lfirst(col))));
5591  }
5592  appendStringInfoChar(buf, ')');
5593  }
5594  appendStringInfoString(buf, " AS ");
5595  switch (cte->ctematerialized)
5596  {
5597  case CTEMaterializeDefault:
5598  break;
5599  case CTEMaterializeAlways:
5600  appendStringInfoString(buf, "MATERIALIZED ");
5601  break;
5602  case CTEMaterializeNever:
5603  appendStringInfoString(buf, "NOT MATERIALIZED ");
5604  break;
5605  }
5606  appendStringInfoChar(buf, '(');
5607  if (PRETTY_INDENT(context))
5608  appendContextKeyword(context, "", 0, 0, 0);
5609  get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5610  true,
5611  context->prettyFlags, context->wrapColumn,
5612  context->indentLevel);
5613  if (PRETTY_INDENT(context))
5614  appendContextKeyword(context, "", 0, 0, 0);
5615  appendStringInfoChar(buf, ')');
5616 
5617  if (cte->search_clause)
5618  {
5619  bool first = true;
5620  ListCell *lc;
5621 
5622  appendStringInfo(buf, " SEARCH %s FIRST BY ",
5623  cte->search_clause->search_breadth_first ? "BREADTH" : "DEPTH");
5624 
5625  foreach(lc, cte->search_clause->search_col_list)
5626  {
5627  if (first)
5628  first = false;
5629  else
5630  appendStringInfoString(buf, ", ");
5633  }
5634 
5635  appendStringInfo(buf, " SET %s", quote_identifier(cte->search_clause->search_seq_column));
5636  }
5637 
5638  if (cte->cycle_clause)
5639  {
5640  bool first = true;
5641  ListCell *lc;
5642 
5643  appendStringInfoString(buf, " CYCLE ");
5644 
5645  foreach(lc, cte->cycle_clause->cycle_col_list)
5646  {
5647  if (first)
5648  first = false;
5649  else
5650  appendStringInfoString(buf, ", ");
5653  }
5654 
5655  appendStringInfo(buf, " SET %s", quote_identifier(cte->cycle_clause->cycle_mark_column));
5656 
5657  {
5658  Const *cmv = castNode(Const, cte->cycle_clause->cycle_mark_value);
5659  Const *cmd = castNode(Const, cte->cycle_clause->cycle_mark_default);
5660 
5661  if (!(cmv->consttype == BOOLOID && !cmv->constisnull && DatumGetBool(cmv->constvalue) == true &&
5662  cmd->consttype == BOOLOID && !cmd->constisnull && DatumGetBool(cmd->constvalue) == false))
5663  {
5664  appendStringInfoString(buf, " TO ");
5665  get_rule_expr(cte->cycle_clause->cycle_mark_value, context, false);
5666  appendStringInfoString(buf, " DEFAULT ");
5667  get_rule_expr(cte->cycle_clause->cycle_mark_default, context, false);
5668  }
5669  }
5670 
5671  appendStringInfo(buf, " USING %s", quote_identifier(cte->cycle_clause->cycle_path_column));
5672  }
5673 
5674  sep = ", ";
5675  }
5676 
5677  if (PRETTY_INDENT(context))
5678  {
5679  context->indentLevel -= PRETTYINDENT_STD;
5680  appendContextKeyword(context, "", 0, 0, 0);
5681  }
5682  else
5683  appendStringInfoChar(buf, ' ');
5684 }
5685 
5686 /* ----------
5687  * get_select_query_def - Parse back a SELECT parsetree
5688  * ----------
5689  */
5690 static void
5692  TupleDesc resultDesc, bool colNamesVisible)
5693 {
5694  StringInfo buf = context->buf;
5695  List *save_windowclause;
5696  List *save_windowtlist;
5697  bool force_colno;
5698  ListCell *l;
5699 
5700  /* Insert the WITH clause if given */
5701  get_with_clause(query, context);
5702 
5703  /* Set up context for possible window functions */
5704  save_windowclause = context->windowClause;
5705  context->windowClause = query->windowClause;
5706  save_windowtlist = context->windowTList;
5707  context->windowTList = query->targetList;
5708 
5709  /*
5710  * If the Query node has a setOperations tree, then it's the top level of
5711  * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
5712  * fields are interesting in the top query itself.
5713  */
5714  if (query->setOperations)
5715  {
5716  get_setop_query(query->setOperations, query, context, resultDesc,
5717  colNamesVisible);
5718  /* ORDER BY clauses must be simple in this case */
5719  force_colno = true;
5720  }
5721  else
5722  {
5723  get_basic_select_query(query, context, resultDesc, colNamesVisible);
5724  force_colno = false;
5725  }
5726 
5727  /* Add the ORDER BY clause if given */
5728  if (query->sortClause != NIL)
5729  {
5730  appendContextKeyword(context, " ORDER BY ",
5732  get_rule_orderby(query->sortClause, query->targetList,
5733  force_colno, context);
5734  }
5735 
5736  /*
5737  * Add the LIMIT/OFFSET clauses if given. If non-default options, use the
5738  * standard spelling of LIMIT.
5739  */
5740  if (query->limitOffset != NULL)
5741  {
5742  appendContextKeyword(context, " OFFSET ",
5744  get_rule_expr(query->limitOffset, context, false);
5745  }
5746  if (query->limitCount != NULL)
5747  {
5748  if (query->limitOption == LIMIT_OPTION_WITH_TIES)
5749  {
5750  appendContextKeyword(context, " FETCH FIRST ",
5752  get_rule_expr(query->limitCount, context, false);
5753  appendStringInfoString(buf, " ROWS WITH TIES");
5754  }
5755  else
5756  {
5757  appendContextKeyword(context, " LIMIT ",
5759  if (IsA(query->limitCount, Const) &&
5760  ((Const *) query->limitCount)->constisnull)
5761  appendStringInfoString(buf, "ALL");
5762  else
5763  get_rule_expr(query->limitCount, context, false);
5764  }
5765  }
5766 
5767  /* Add FOR [KEY] UPDATE/SHARE clauses if present */
5768  if (query->hasForUpdate)
5769  {
5770  foreach(l, query->rowMarks)
5771  {
5772  RowMarkClause *rc = (RowMarkClause *) lfirst(l);
5773 
5774  /* don't print implicit clauses */
5775  if (rc->pushedDown)
5776  continue;
5777 
5778  switch (rc->strength)
5779  {
5780  case LCS_NONE:
5781  /* we intentionally throw an error for LCS_NONE */
5782  elog(ERROR, "unrecognized LockClauseStrength %d",
5783  (int) rc->strength);
5784  break;
5785  case LCS_FORKEYSHARE:
5786  appendContextKeyword(context, " FOR KEY SHARE",
5788  break;
5789  case LCS_FORSHARE:
5790  appendContextKeyword(context, " FOR SHARE",
5792  break;
5793  case LCS_FORNOKEYUPDATE:
5794  appendContextKeyword(context, " FOR NO KEY UPDATE",
5796  break;
5797  case LCS_FORUPDATE:
5798  appendContextKeyword(context, " FOR UPDATE",
5800  break;
5801  }
5802 
5803  appendStringInfo(buf, " OF %s",
5805  context)));
5806  if (rc->waitPolicy == LockWaitError)
5807  appendStringInfoString(buf, " NOWAIT");
5808  else if (rc->waitPolicy == LockWaitSkip)
5809  appendStringInfoString(buf, " SKIP LOCKED");
5810  }
5811  }
5812 
5813  context->windowClause = save_windowclause;
5814  context->windowTList = save_windowtlist;
5815 }
5816 
5817 /*
5818  * Detect whether query looks like SELECT ... FROM VALUES(),
5819  * with no need to rename the output columns of the VALUES RTE.
5820  * If so, return the VALUES RTE. Otherwise return NULL.
5821  */
5822 static RangeTblEntry *
5824 {
5825  RangeTblEntry *result = NULL;
5826  ListCell *lc;
5827 
5828  /*
5829  * We want to detect a match even if the Query also contains OLD or NEW
5830  * rule RTEs. So the idea is to scan the rtable and see if there is only
5831  * one inFromCl RTE that is a VALUES RTE.
5832  */
5833  foreach(lc, query->rtable)
5834  {
5835  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
5836 
5837  if (rte->rtekind == RTE_VALUES && rte->inFromCl)
5838  {
5839  if (result)
5840  return NULL; /* multiple VALUES (probably not possible) */
5841  result = rte;
5842  }
5843  else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
5844  continue; /* ignore rule entries */
5845  else
5846  return NULL; /* something else -> not simple VALUES */
5847  }
5848 
5849  /*
5850  * We don't need to check the targetlist in any great detail, because
5851  * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
5852  * appear inside auto-generated sub-queries with very restricted
5853  * structure. However, DefineView might have modified the tlist by
5854  * injecting new column aliases, or we might have some other column
5855  * aliases forced by a resultDesc. We can only simplify if the RTE's
5856  * column names match the names that get_target_list() would select.
5857  */
5858  if (result)
5859  {
5860  ListCell *lcn;
5861  int colno;
5862 
5863  if (list_length(query->targetList) != list_length(result->eref->colnames))
5864  return NULL; /* this probably cannot happen */
5865  colno = 0;
5866  forboth(lc, query->targetList, lcn, result->eref->colnames)
5867  {
5868  TargetEntry *tle = (TargetEntry *) lfirst(lc);
5869  char *cname = strVal(lfirst(lcn));
5870  char *colname;
5871 
5872  if (tle->resjunk)
5873  return NULL; /* this probably cannot happen */
5874 
5875  /* compute name that get_target_list would use for column */
5876  colno++;
5877  if (resultDesc && colno <= resultDesc->natts)
5878  colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5879  else
5880  colname = tle->resname;
5881 
5882  /* does it match the VALUES RTE? */
5883  if (colname == NULL || strcmp(colname, cname) != 0)
5884  return NULL; /* column name has been changed */
5885  }
5886  }
5887 
5888  return result;
5889 }
5890 
5891 static void
5893  TupleDesc resultDesc, bool colNamesVisible)
5894 {
5895  StringInfo buf = context->buf;
5896  RangeTblEntry *values_rte;
5897  char *sep;
5898  ListCell *l;
5899 
5900  if (PRETTY_INDENT(context))
5901  {
5902  context->indentLevel += PRETTYINDENT_STD;
5903  appendStringInfoChar(buf, ' ');
5904  }
5905 
5906  /*
5907  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5908  * VALUES part. This reverses what transformValuesClause() did at parse
5909  * time.
5910  */
5911  values_rte = get_simple_values_rte(query, resultDesc);
5912  if (values_rte)
5913  {
5914  get_values_def(values_rte->values_lists, context);
5915  return;
5916  }
5917 
5918  /*
5919  * Build up the query string - first we say SELECT
5920  */
5921  if (query->isReturn)
5922  appendStringInfoString(buf, "RETURN");
5923  else
5924  appendStringInfoString(buf, "SELECT");
5925 
5926  /* Add the DISTINCT clause if given */
5927  if (query->distinctClause != NIL)
5928  {
5929  if (query->hasDistinctOn)
5930  {
5931  appendStringInfoString(buf, " DISTINCT ON (");
5932  sep = "";
5933  foreach(l, query->distinctClause)
5934  {
5935  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5936 
5939  false, context);
5940  sep = ", ";
5941  }
5942  appendStringInfoChar(buf, ')');
5943  }
5944  else
5945  appendStringInfoString(buf, " DISTINCT");
5946  }
5947 
5948  /* Then we tell what to select (the targetlist) */
5949  get_target_list(query->targetList, context, resultDesc, colNamesVisible);
5950 
5951  /* Add the FROM clause if needed */
5952  get_from_clause(query, " FROM ", context);
5953 
5954  /* Add the WHERE clause if given */
5955  if (query->jointree->quals != NULL)
5956  {
5957  appendContextKeyword(context, " WHERE ",
5959  get_rule_expr(query->jointree->quals, context, false);
5960  }
5961 
5962  /* Add the GROUP BY clause if given */
5963  if (query->groupClause != NULL || query->groupingSets != NULL)
5964  {
5965  ParseExprKind save_exprkind;
5966 
5967  appendContextKeyword(context, " GROUP BY ",
5969  if (query->groupDistinct)
5970  appendStringInfoString(buf, "DISTINCT ");
5971 
5972  save_exprkind = context->special_exprkind;
5974 
5975  if (query->groupingSets == NIL)
5976  {
5977  sep = "";
5978  foreach(l, query->groupClause)
5979  {
5980  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5981 
5984  false, context);
5985  sep = ", ";
5986  }
5987  }
5988  else
5989  {
5990  sep = "";
5991  foreach(l, query->groupingSets)
5992  {
5993  GroupingSet *grp = lfirst(l);
5994 
5996  get_rule_groupingset(grp, query->targetList, true, context);
5997  sep = ", ";
5998  }
5999  }
6000 
6001  context->special_exprkind = save_exprkind;
6002  }
6003 
6004  /* Add the HAVING clause if given */
6005  if (query->havingQual != NULL)
6006  {
6007  appendContextKeyword(context, " HAVING ",
6009  get_rule_expr(query->havingQual, context, false);
6010  }
6011 
6012  /* Add the WINDOW clause if needed */
6013  if (query->windowClause != NIL)
6014  get_rule_windowclause(query, context);
6015 }
6016 
6017 /* ----------
6018  * get_target_list - Parse back a SELECT target list
6019  *
6020  * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
6021  *
6022  * resultDesc and colNamesVisible are as for get_query_def()
6023  * ----------
6024  */
6025 static void
6026 get_target_list(List *targetList, deparse_context *context,
6027  TupleDesc resultDesc, bool colNamesVisible)
6028 {
6029  StringInfo buf = context->buf;
6030  StringInfoData targetbuf;
6031  bool last_was_multiline = false;
6032  char *sep;
6033  int colno;
6034  ListCell *l;
6035 
6036  /* we use targetbuf to hold each TLE's text temporarily */
6037  initStringInfo(&targetbuf);
6038 
6039  sep = " ";
6040  colno = 0;
6041  foreach(l, targetList)
6042  {
6043  TargetEntry *tle = (TargetEntry *) lfirst(l);
6044  char *colname;
6045  char *attname;
6046 
6047  if (tle->resjunk)
6048  continue; /* ignore junk entries */
6049 
6051  sep = ", ";
6052  colno++;
6053 
6054  /*
6055  * Put the new field text into targetbuf so we can decide after we've
6056  * got it whether or not it needs to go on a new line.
6057  */
6058  resetStringInfo(&targetbuf);
6059  context->buf = &targetbuf;
6060 
6061  /*
6062  * We special-case Var nodes rather than using get_rule_expr. This is
6063  * needed because get_rule_expr will display a whole-row Var as
6064  * "foo.*", which is the preferred notation in most contexts, but at
6065  * the top level of a SELECT list it's not right (the parser will
6066  * expand that notation into multiple columns, yielding behavior
6067  * different from a whole-row Var). We need to call get_variable
6068  * directly so that we can tell it to do the right thing, and so that
6069  * we can get the attribute name which is the default AS label.
6070  */
6071  if (tle->expr && (IsA(tle->expr, Var)))
6072  {
6073  attname = get_variable((Var *) tle->expr, 0, true, context);
6074  }
6075  else
6076  {
6077  get_rule_expr((Node *) tle->expr, context, true);
6078 
6079  /*
6080  * When colNamesVisible is true, we should always show the
6081  * assigned column name explicitly. Otherwise, show it only if
6082  * it's not FigureColname's fallback.
6083  */
6084  attname = colNamesVisible ? NULL : "?column?";
6085  }
6086 
6087  /*
6088  * Figure out what the result column should be called. In the context
6089  * of a view, use the view's tuple descriptor (so as to pick up the
6090  * effects of any column RENAME that's been done on the view).
6091  * Otherwise, just use what we can find in the TLE.
6092  */
6093  if (resultDesc && colno <= resultDesc->natts)
6094  colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
6095  else
6096  colname = tle->resname;
6097 
6098  /* Show AS unless the column's name is correct as-is */
6099  if (colname) /* resname could be NULL */
6100  {
6101  if (attname == NULL || strcmp(attname, colname) != 0)
6102  appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
6103  }
6104 
6105  /* Restore context's output buffer */
6106  context->buf = buf;
6107 
6108  /* Consider line-wrapping if enabled */
6109  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
6110  {
6111  int leading_nl_pos;
6112 
6113  /* Does the new field start with a new line? */
6114  if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
6115  leading_nl_pos = 0;
6116  else
6117  leading_nl_pos = -1;
6118 
6119  /* If so, we shouldn't add anything */
6120  if (leading_nl_pos >= 0)
6121  {
6122  /* instead, remove any trailing spaces currently in buf */
6124  }
6125  else
6126  {
6127  char *trailing_nl;
6128 
6129  /* Locate the start of the current line in the output buffer */
6130  trailing_nl = strrchr(buf->data, '\n');
6131  if (trailing_nl == NULL)
6132  trailing_nl = buf->data;
6133  else
6134  trailing_nl++;
6135 
6136  /*
6137  * Add a newline, plus some indentation, if the new field is
6138  * not the first and either the new field would cause an
6139  * overflow or the last field used more than one line.
6140  */
6141  if (colno > 1 &&
6142  ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
6143  last_was_multiline))
6144  appendContextKeyword(context, "", -PRETTYINDENT_STD,
6146  }
6147 
6148  /* Remember this field's multiline status for next iteration */
6149  last_was_multiline =
6150  (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
6151  }
6152 
6153  /* Add the new field */
6154  appendBinaryStringInfo(buf, targetbuf.data, targetbuf.len);
6155  }
6156 
6157  /* clean up */
6158  pfree(targetbuf.data);
6159 }
6160 
6161 static void
6162 get_setop_query(Node *setOp, Query *query, deparse_context *context,
6163  TupleDesc resultDesc, bool colNamesVisible)
6164 {
6165  StringInfo buf = context->buf;
6166  bool need_paren;
6167 
6168  /* Guard against excessively long or deeply-nested queries */
6171 
6172  if (IsA(setOp, RangeTblRef))
6173  {
6174  RangeTblRef *rtr = (RangeTblRef *) setOp;
6175  RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
6176  Query *subquery = rte->subquery;
6177 
6178  Assert(subquery != NULL);
6179  Assert(subquery->setOperations == NULL);
6180  /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
6181  need_paren = (subquery->cteList ||
6182  subquery->sortClause ||
6183  subquery->rowMarks ||
6184  subquery->limitOffset ||
6185  subquery->limitCount);
6186  if (need_paren)
6187  appendStringInfoChar(buf, '(');
6188  get_query_def(subquery, buf, context->namespaces, resultDesc,
6189  colNamesVisible,
6190  context->prettyFlags, context->wrapColumn,
6191  context->indentLevel);
6192  if (need_paren)
6193  appendStringInfoChar(buf, ')');
6194  }
6195  else if (IsA(setOp, SetOperationStmt))
6196  {
6197  SetOperationStmt *op = (SetOperationStmt *) setOp;
6198  int subindent;
6199 
6200  /*
6201  * We force parens when nesting two SetOperationStmts, except when the
6202  * lefthand input is another setop of the same kind. Syntactically,
6203  * we could omit parens in rather more cases, but it seems best to use
6204  * parens to flag cases where the setop operator changes. If we use
6205  * parens, we also increase the indentation level for the child query.
6206  *
6207  * There are some cases in which parens are needed around a leaf query
6208  * too, but those are more easily handled at the next level down (see
6209  * code above).
6210  */
6211  if (IsA(op->larg, SetOperationStmt))
6212  {
6213  SetOperationStmt *lop = (SetOperationStmt *) op->larg;
6214 
6215  if (op->op == lop->op && op->all == lop->all)
6216  need_paren = false;
6217  else
6218  need_paren = true;
6219  }
6220  else
6221  need_paren = false;
6222 
6223  if (need_paren)
6224  {
6225  appendStringInfoChar(buf, '(');
6226  subindent = PRETTYINDENT_STD;
6227  appendContextKeyword(context, "", subindent, 0, 0);
6228  }
6229  else
6230  subindent = 0;
6231 
6232  get_setop_query(op->larg, query, context, resultDesc, colNamesVisible);
6233 
6234  if (need_paren)
6235  appendContextKeyword(context, ") ", -subindent, 0, 0);
6236  else if (PRETTY_INDENT(context))
6237  appendContextKeyword(context, "", -subindent, 0, 0);
6238  else
6239  appendStringInfoChar(buf, ' ');
6240 
6241  switch (op->op)
6242  {
6243  case SETOP_UNION:
6244  appendStringInfoString(buf, "UNION ");
6245  break;
6246  case SETOP_INTERSECT:
6247  appendStringInfoString(buf, "INTERSECT ");
6248  break;
6249  case SETOP_EXCEPT:
6250  appendStringInfoString(buf, "EXCEPT ");
6251  break;
6252  default:
6253  elog(ERROR, "unrecognized set op: %d",
6254  (int) op->op);
6255  }
6256  if (op->all)
6257  appendStringInfoString(buf, "ALL ");
6258 
6259  /* Always parenthesize if RHS is another setop */
6260  need_paren = IsA(op->rarg, SetOperationStmt);
6261 
6262  /*
6263  * The indentation code here is deliberately a bit different from that
6264  * for the lefthand input, because we want the line breaks in
6265  * different places.
6266  */
6267  if (need_paren)
6268  {
6269  appendStringInfoChar(buf, '(');
6270  subindent = PRETTYINDENT_STD;
6271  }
6272  else
6273  subindent = 0;
6274  appendContextKeyword(context, "", subindent, 0, 0);
6275 
6276  get_setop_query(op->rarg, query, context, resultDesc, false);
6277 
6278  if (PRETTY_INDENT(context))
6279  context->indentLevel -= subindent;
6280  if (need_paren)
6281  appendContextKeyword(context, ")", 0, 0, 0);
6282  }
6283  else
6284  {
6285  elog(ERROR, "unrecognized node type: %d",
6286  (int) nodeTag(setOp));
6287  }
6288 }
6289 
6290 /*
6291  * Display a sort/group clause.
6292  *
6293  * Also returns the expression tree, so caller need not find it again.
6294  */
6295 static Node *
6296 get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
6297  deparse_context *context)
6298 {
6299  StringInfo buf = context->buf;
6300  TargetEntry *tle;
6301  Node *expr;
6302 
6303  tle = get_sortgroupref_tle(ref, tlist);
6304  expr = (Node *) tle->expr;
6305 
6306  /*
6307  * Use column-number form if requested by caller. Otherwise, if
6308  * expression is a constant, force it to be dumped with an explicit cast
6309  * as decoration --- this is because a simple integer constant is
6310  * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
6311  * dump it without any decoration. If it's anything more complex than a
6312  * simple Var, then force extra parens around it, to ensure it can't be
6313  * misinterpreted as a cube() or rollup() construct.
6314  */
6315  if (force_colno)
6316  {
6317  Assert(!tle->resjunk);
6318  appendStringInfo(buf, "%d", tle->resno);
6319  }
6320  else if (expr && IsA(expr, Const))
6321  get_const_expr((Const *) expr, context, 1);
6322  else if (!expr || IsA(expr, Var))
6323  get_rule_expr(expr, context, true);
6324  else
6325  {
6326  /*
6327  * We must force parens for function-like expressions even if
6328  * PRETTY_PAREN is off, since those are the ones in danger of
6329  * misparsing. For other expressions we need to force them only if
6330  * PRETTY_PAREN is on, since otherwise the expression will output them
6331  * itself. (We can't skip the parens.)
6332  */
6333  bool need_paren = (PRETTY_PAREN(context)
6334  || IsA(expr, FuncExpr)
6335  || IsA(expr, Aggref)
6336  || IsA(expr, WindowFunc)
6337  || IsA(expr, JsonConstructorExpr));
6338 
6339  if (need_paren)
6340  appendStringInfoChar(context->buf, '(');
6341  get_rule_expr(expr, context, true);
6342  if (need_paren)
6343  appendStringInfoChar(context->buf, ')');
6344  }
6345 
6346  return expr;
6347 }
6348 
6349 /*
6350  * Display a GroupingSet
6351  */
6352 static void
6354  bool omit_parens, deparse_context *context)
6355 {
6356  ListCell *l;
6357  StringInfo buf = context->buf;
6358  bool omit_child_parens = true;
6359  char *sep = "";
6360 
6361  switch (gset->kind)
6362  {
6363  case GROUPING_SET_EMPTY:
6364  appendStringInfoString(buf, "()");
6365  return;
6366 
6367  case GROUPING_SET_SIMPLE:
6368  {
6369  if (!omit_parens || list_length(gset->content) != 1)
6370  appendStringInfoChar(buf, '(');
6371 
6372  foreach(l, gset->content)
6373  {
6374  Index ref = lfirst_int(l);
6375 
6377  get_rule_sortgroupclause(ref, targetlist,
6378  false, context);
6379  sep = ", ";
6380  }
6381 
6382  if (!omit_parens || list_length(gset->content) != 1)
6383  appendStringInfoChar(buf, ')');
6384  }
6385  return;
6386 
6387  case GROUPING_SET_ROLLUP:
6388  appendStringInfoString(buf, "ROLLUP(");
6389  break;
6390  case GROUPING_SET_CUBE:
6391  appendStringInfoString(buf, "CUBE(");
6392  break;
6393  case GROUPING_SET_SETS:
6394  appendStringInfoString(buf, "GROUPING SETS (");
6395  omit_child_parens = false;
6396  break;
6397  }
6398 
6399  foreach(l, gset->content)
6400  {
6402  get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context);
6403  sep = ", ";
6404  }
6405 
6406  appendStringInfoChar(buf, ')');
6407 }
6408 
6409 /*
6410  * Display an ORDER BY list.
6411  */
6412 static void
6413 get_rule_orderby(List *orderList, List *targetList,
6414  bool force_colno, deparse_context *context)
6415 {
6416  StringInfo buf = context->buf;
6417  const char *sep;
6418  ListCell *l;
6419 
6420  sep = "";
6421  foreach(l, orderList)
6422  {
6423  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
6424  Node *sortexpr;
6425  Oid sortcoltype;
6426  TypeCacheEntry *typentry;
6427 
6429  sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList,
6430  force_colno, context);
6431  sortcoltype = exprType(sortexpr);
6432  /* See whether operator is default < or > for datatype */
6433  typentry = lookup_type_cache(sortcoltype,
6435  if (srt->sortop == typentry->lt_opr)
6436  {
6437  /* ASC is default, so emit nothing for it */
6438  if (srt->nulls_first)
6439  appendStringInfoString(buf, " NULLS FIRST");
6440  }
6441  else if (srt->sortop == typentry->gt_opr)
6442  {
6443  appendStringInfoString(buf, " DESC");
6444  /* DESC defaults to NULLS FIRST */
6445  if (!srt->nulls_first)
6446  appendStringInfoString(buf, " NULLS LAST");
6447  }
6448  else
6449  {
6450  appendStringInfo(buf, " USING %s",
6452  sortcoltype,
6453  sortcoltype));
6454  /* be specific to eliminate ambiguity */
6455  if (srt->nulls_first)
6456  appendStringInfoString(buf, " NULLS FIRST");
6457  else
6458  appendStringInfoString(buf, " NULLS LAST");
6459  }
6460  sep = ", ";
6461  }
6462 }
6463 
6464 /*
6465  * Display a WINDOW clause.
6466  *
6467  * Note that the windowClause list might contain only anonymous window
6468  * specifications, in which case we should print nothing here.
6469  */
6470 static void
6472 {
6473  StringInfo buf = context->buf;
6474  const char *sep;
6475  ListCell *l;
6476 
6477  sep = NULL;
6478  foreach(l, query->windowClause)
6479  {
6480  WindowClause *wc = (WindowClause *) lfirst(l);
6481 
6482  if (wc->name == NULL)
6483  continue; /* ignore anonymous windows */
6484 
6485  if (sep == NULL)
6486  appendContextKeyword(context, " WINDOW ",
6488  else
6490 
6491  appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
6492 
6493  get_rule_windowspec(wc, query->targetList, context);
6494 
6495  sep = ", ";
6496  }
6497 }
6498 
6499 /*
6500  * Display a window definition
6501  */
6502 static void
6504  deparse_context *context)
6505 {
6506  StringInfo buf = context->buf;
6507  bool needspace = false;
6508  const char *sep;
6509  ListCell *l;
6510 
6511  appendStringInfoChar(buf, '(');
6512  if (wc->refname)
6513  {
6515  needspace = true;
6516  }
6517  /* partition clauses are always inherited, so only print if no refname */
6518  if (wc->partitionClause && !wc->refname)
6519  {
6520  if (needspace)
6521  appendStringInfoChar(buf, ' ');
6522  appendStringInfoString(buf, "PARTITION BY ");
6523  sep = "";
6524  foreach(l, wc->partitionClause)
6525  {
6526  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
6527 
6529  get_rule_sortgroupclause(grp->tleSortGroupRef, targetList,
6530  false, context);
6531  sep = ", ";
6532  }
6533  needspace = true;
6534  }
6535  /* print ordering clause only if not inherited */
6536  if (wc->orderClause && !wc->copiedOrder)
6537  {
6538  if (needspace)
6539  appendStringInfoChar(buf, ' ');
6540  appendStringInfoString(buf, "ORDER BY ");
6541  get_rule_orderby(wc->orderClause, targetList, false, context);
6542  needspace = true;
6543  }
6544  /* framing clause is never inherited, so print unless it's default */
6546  {
6547  if (needspace)
6548  appendStringInfoChar(buf, ' ');
6549  if (wc->frameOptions & FRAMEOPTION_RANGE)
6550  appendStringInfoString(buf, "RANGE ");
6551  else if (wc->frameOptions & FRAMEOPTION_ROWS)
6552  appendStringInfoString(buf, "ROWS ");
6553  else if (wc->frameOptions & FRAMEOPTION_GROUPS)
6554  appendStringInfoString(buf, "GROUPS ");
6555  else
6556  Assert(false);
6558  appendStringInfoString(buf, "BETWEEN ");
6560  appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
6562  appendStringInfoString(buf, "CURRENT ROW ");
6563  else if (wc->frameOptions & FRAMEOPTION_START_OFFSET)
6564  {
6565  get_rule_expr(wc->startOffset, context, false);
6567  appendStringInfoString(buf, " PRECEDING ");
6569  appendStringInfoString(buf, " FOLLOWING ");
6570  else
6571  Assert(false);
6572  }
6573  else
6574  Assert(false);
6576  {
6577  appendStringInfoString(buf, "AND ");
6579  appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
6581  appendStringInfoString(buf, "CURRENT ROW ");
6582  else if (wc->frameOptions & FRAMEOPTION_END_OFFSET)
6583  {
6584  get_rule_expr(wc->endOffset, context, false);
6586  appendStringInfoString(buf, " PRECEDING ");
6588  appendStringInfoString(buf, " FOLLOWING ");
6589  else
6590  Assert(false);
6591  }
6592  else
6593  Assert(false);
6594  }
6596  appendStringInfoString(buf, "EXCLUDE CURRENT ROW ");
6597  else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
6598  appendStringInfoString(buf, "EXCLUDE GROUP ");
6599  else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
6600  appendStringInfoString(buf, "EXCLUDE TIES ");
6601  /* we will now have a trailing space; remove it */
6602  buf->len--;
6603  }
6604  appendStringInfoChar(buf, ')');
6605 }
6606 
6607 /* ----------
6608  * get_insert_query_def - Parse back an INSERT parsetree
6609  * ----------
6610  */
6611 static void
6613  bool colNamesVisible)
6614 {
6615  StringInfo buf = context->buf;
6616  RangeTblEntry *select_rte = NULL;
6617  RangeTblEntry *values_rte = NULL;
6618  RangeTblEntry *rte;
6619  char *sep;
6620  ListCell *l;
6621  List *strippedexprs;
6622 
6623  /* Insert the WITH clause if given */
6624  get_with_clause(query, context);
6625 
6626  /*
6627  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6628  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6629  */
6630  foreach(l, query->rtable)
6631  {
6632  rte = (RangeTblEntry *) lfirst(l);
6633 
6634  if (rte->rtekind == RTE_SUBQUERY)
6635  {
6636  if (select_rte)
6637  elog(ERROR, "too many subquery RTEs in INSERT");
6638  select_rte = rte;
6639  }
6640 
6641  if (rte->rtekind == RTE_VALUES)
6642  {
6643  if (values_rte)
6644  elog(ERROR, "too many values RTEs in INSERT");
6645  values_rte = rte;
6646  }
6647  }
6648  if (select_rte && values_rte)
6649  elog(ERROR, "both subquery and values RTEs in INSERT");
6650 
6651  /*
6652  * Start the query with INSERT INTO relname
6653  */
6654  rte = rt_fetch(query->resultRelation, query->rtable);
6655  Assert(rte->rtekind == RTE_RELATION);
6656 
6657  if (PRETTY_INDENT(context))
6658  {
6659  context->indentLevel += PRETTYINDENT_STD;
6660  appendStringInfoChar(buf, ' ');
6661  }
6662  appendStringInfo(buf, "INSERT INTO %s",
6664 
6665  /* Print the relation alias, if needed; INSERT requires explicit AS */
6666  get_rte_alias(rte, query->resultRelation, true, context);
6667 
6668  /* always want a space here */
6669  appendStringInfoChar(buf, ' ');
6670 
6671  /*
6672  * Add the insert-column-names list. Any indirection decoration needed on
6673  * the column names can be inferred from the top targetlist.
6674  */
6675  strippedexprs = NIL;
6676  sep = "";
6677  if (query->targetList)
6678  appendStringInfoChar(buf, '(');
6679  foreach(l, query->targetList)
6680  {
6681  TargetEntry *tle = (TargetEntry *) lfirst(l);
6682 
6683  if (tle->resjunk)
6684  continue; /* ignore junk entries */
6685 
6687  sep = ", ";
6688 
6689  /*
6690  * Put out name of target column; look in the catalogs, not at
6691  * tle->resname, since resname will fail to track RENAME.
6692  */
6695  tle->resno,
6696  false)));
6697 
6698  /*
6699  * Print any indirection needed (subfields or subscripts), and strip
6700  * off the top-level nodes representing the indirection assignments.
6701  * Add the stripped expressions to strippedexprs. (If it's a
6702  * single-VALUES statement, the stripped expressions are the VALUES to
6703  * print below. Otherwise they're just Vars and not really
6704  * interesting.)
6705  */
6706  strippedexprs = lappend(strippedexprs,
6707  processIndirection((Node *) tle->expr,
6708  context));
6709  }
6710  if (query->targetList)
6711  appendStringInfoString(buf, ") ");
6712 
6713  if (query->override)
6714  {
6715  if (query->override == OVERRIDING_SYSTEM_VALUE)
6716  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6717  else if (query->override == OVERRIDING_USER_VALUE)
6718  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6719  }
6720 
6721  if (select_rte)
6722  {
6723  /* Add the SELECT */
6724  get_query_def(select_rte->subquery, buf, context->namespaces, NULL,
6725  false,
6726  context->prettyFlags, context->wrapColumn,
6727  context->indentLevel);
6728  }
6729  else if (values_rte)
6730  {
6731  /* Add the multi-VALUES expression lists */
6732  get_values_def(values_rte->values_lists, context);
6733  }
6734  else if (strippedexprs)
6735  {
6736  /* Add the single-VALUES expression list */
6737  appendContextKeyword(context, "VALUES (",
6739  get_rule_list_toplevel(strippedexprs, context, false);
6740  appendStringInfoChar(buf, ')');
6741  }
6742  else
6743  {
6744  /* No expressions, so it must be DEFAULT VALUES */
6745  appendStringInfoString(buf, "DEFAULT VALUES");
6746  }
6747 
6748  /* Add ON CONFLICT if present */
6749  if (query->onConflict)
6750  {
6751  OnConflictExpr *confl = query->onConflict;
6752 
6753  appendStringInfoString(buf, " ON CONFLICT");
6754 
6755  if (confl->arbiterElems)
6756  {
6757  /* Add the single-VALUES expression list */
6758  appendStringInfoChar(buf, '(');
6759  get_rule_expr((Node *) confl->arbiterElems, context, false);
6760  appendStringInfoChar(buf, ')');
6761 
6762  /* Add a WHERE clause (for partial indexes) if given */
6763  if (confl->arbiterWhere != NULL)
6764  {
6765  bool save_varprefix;
6766 
6767  /*
6768  * Force non-prefixing of Vars, since parser assumes that they
6769  * belong to target relation. WHERE clause does not use
6770  * InferenceElem, so this is separately required.
6771  */
6772  save_varprefix = context->varprefix;
6773  context->varprefix = false;
6774 
6775  appendContextKeyword(context, " WHERE ",
6777  get_rule_expr(confl->arbiterWhere, context, false);
6778 
6779  context->varprefix = save_varprefix;
6780  }
6781  }
6782  else if (OidIsValid(confl->constraint))
6783  {
6784  char *constraint = get_constraint_name(confl->constraint);
6785 
6786  if (!constraint)
6787  elog(ERROR, "cache lookup failed for constraint %u",
6788  confl->constraint);
6789  appendStringInfo(buf, " ON CONSTRAINT %s",
6790  quote_identifier(constraint));
6791  }
6792 
6793  if (confl->action == ONCONFLICT_NOTHING)
6794  {
6795  appendStringInfoString(buf, " DO NOTHING");
6796  }
6797  else
6798  {
6799  appendStringInfoString(buf, " DO UPDATE SET ");
6800  /* Deparse targetlist */
6802  context, rte);
6803 
6804  /* Add a WHERE clause if given */
6805  if (confl->onConflictWhere != NULL)
6806  {
6807  appendContextKeyword(context, " WHERE ",
6809  get_rule_expr(confl->onConflictWhere, context, false);
6810  }
6811  }
6812  }
6813 
6814  /* Add RETURNING if present */
6815  if (query->returningList)
6816  {
6817  appendContextKeyword(context, " RETURNING",
6819  get_target_list(query->returningList, context, NULL, colNamesVisible);
6820  }
6821 }
6822 
6823 
6824 /* ----------
6825  * get_update_query_def - Parse back an UPDATE parsetree
6826  * ----------
6827  */
6828 static void
6830  bool colNamesVisible)
6831 {
6832  StringInfo buf = context->buf;
6833  RangeTblEntry *rte;
6834 
6835  /* Insert the WITH clause if given */
6836  get_with_clause(query, context);
6837 
6838  /*
6839  * Start the query with UPDATE relname SET
6840  */
6841  rte = rt_fetch(query->resultRelation, query->rtable);
6842  Assert(rte->rtekind == RTE_RELATION);
6843  if (PRETTY_INDENT(context))
6844  {
6845  appendStringInfoChar(buf, ' ');
6846  context->indentLevel += PRETTYINDENT_STD;
6847  }
6848  appendStringInfo(buf, "UPDATE %s%s",
6849  only_marker(rte),
6851 
6852  /* Print the relation alias, if needed */
6853  get_rte_alias(rte, query->resultRelation, false, context);
6854 
6855  appendStringInfoString(buf, " SET ");
6856 
6857  /* Deparse targetlist */
6858  get_update_query_targetlist_def(query, query->targetList, context, rte);
6859 
6860  /* Add the FROM clause if needed */
6861  get_from_clause(query, " FROM ", context);
6862 
6863  /* Add a WHERE clause if given */
6864  if (query->jointree->quals != NULL)
6865  {
6866  appendContextKeyword(context, " WHERE ",
6868  get_rule_expr(query->jointree->quals, context, false);
6869  }
6870 
6871  /* Add RETURNING if present */
6872  if (query->returningList)
6873  {
6874  appendContextKeyword(context, " RETURNING",
6876  get_target_list(query->returningList, context, NULL, colNamesVisible);
6877  }
6878 }
6879 
6880 
6881 /* ----------
6882  * get_update_query_targetlist_def - Parse back an UPDATE targetlist
6883  * ----------
6884  */
6885 static void
6887  deparse_context *context, RangeTblEntry *rte)
6888 {
6889  StringInfo buf = context->buf;
6890  ListCell *l;
6891  ListCell *next_ma_cell;
6892  int remaining_ma_columns;
6893  const char *sep;
6894  SubLink *cur_ma_sublink;
6895  List *ma_sublinks;
6896 
6897  /*
6898  * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks
6899  * into a list. We expect them to appear, in ID order, in resjunk tlist
6900  * entries.
6901  */
6902  ma_sublinks = NIL;
6903  if (query->hasSubLinks) /* else there can't be any */
6904  {
6905  foreach(l, targetList)
6906  {
6907  TargetEntry *tle = (TargetEntry *) lfirst(l);
6908 
6909  if (tle->resjunk && IsA(tle->expr, SubLink))
6910  {
6911  SubLink *sl = (SubLink *) tle->expr;
6912 
6914  {
6915  ma_sublinks = lappend(ma_sublinks, sl);
6916  Assert(sl->subLinkId == list_length(ma_sublinks));
6917  }
6918  }
6919  }
6920  }
6921  next_ma_cell = list_head(ma_sublinks);
6922  cur_ma_sublink = NULL;
6923  remaining_ma_columns = 0;
6924 
6925  /* Add the comma separated list of 'attname = value' */
6926  sep = "";
6927  foreach(l, targetList)
6928  {
6929  TargetEntry *tle = (TargetEntry *) lfirst(l);
6930  Node *expr;
6931 
6932  if (tle->resjunk)
6933  continue; /* ignore junk entries */
6934 
6935  /* Emit separator (OK whether we're in multiassignment or not) */
6937  sep = ", ";
6938 
6939  /*
6940  * Check to see if we're starting a multiassignment group: if so,
6941  * output a left paren.
6942  */
6943  if (next_ma_cell != NULL && cur_ma_sublink == NULL)
6944  {
6945  /*
6946  * We must dig down into the expr to see if it's a PARAM_MULTIEXPR
6947  * Param. That could be buried under FieldStores and
6948  * SubscriptingRefs and CoerceToDomains (cf processIndirection()),
6949  * and underneath those there could be an implicit type coercion.
6950  * Because we would ignore implicit type coercions anyway, we
6951  * don't need to be as careful as processIndirection() is about
6952  * descending past implicit CoerceToDomains.
6953  */
6954  expr = (Node *) tle->expr;
6955  while (expr)
6956  {
6957  if (IsA(expr, FieldStore))
6958  {
6959  FieldStore *fstore = (FieldStore *) expr;
6960 
6961  expr = (Node *) linitial(fstore->newvals);
6962  }
6963  else if (IsA(expr, SubscriptingRef))
6964  {
6965  SubscriptingRef *sbsref = (SubscriptingRef *) expr;
6966 
6967  if (sbsref->refassgnexpr == NULL)
6968  break;
6969 
6970  expr = (Node *) sbsref->refassgnexpr;
6971  }
6972  else if (IsA(expr, CoerceToDomain))
6973  {
6974  CoerceToDomain *cdomain = (CoerceToDomain *) expr;
6975 
6976  if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
6977  break;
6978  expr = (Node *) cdomain->arg;
6979  }
6980  else
6981  break;
6982  }
6983  expr = strip_implicit_coercions(expr);
6984 
6985  if (expr && IsA(expr, Param) &&
6986  ((Param *) expr)->paramkind == PARAM_MULTIEXPR)
6987  {
6988  cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
6989  next_ma_cell = lnext(ma_sublinks, next_ma_cell);
6990  remaining_ma_columns = count_nonjunk_tlist_entries(((Query *) cur_ma_sublink->subselect)->targetList);
6991  Assert(((Param *) expr)->paramid ==
6992  ((cur_ma_sublink->subLinkId << 16) | 1));
6993  appendStringInfoChar(buf, '(');
6994  }
6995  }
6996 
6997  /*
6998  * Put out name of target column; look in the catalogs, not at
6999  * tle->resname, since resname will fail to track RENAME.
7000  */
7003  tle->resno,
7004  false)));
7005 
7006  /*
7007  * Print any indirection needed (subfields or subscripts), and strip
7008  * off the top-level nodes representing the indirection assignments.
7009  */
7010  expr = processIndirection((Node *) tle->expr, context);
7011 
7012  /*
7013  * If we're in a multiassignment, skip printing anything more, unless
7014  * this is the last column; in which case, what we print should be the
7015  * sublink, not the Param.
7016  */
7017  if (cur_ma_sublink != NULL)
7018  {
7019  if (--remaining_ma_columns > 0)
7020  continue; /* not the last column of multiassignment */
7021  appendStringInfoChar(buf, ')');
7022  expr = (Node *) cur_ma_sublink;
7023  cur_ma_sublink = NULL;
7024  }
7025 
7026  appendStringInfoString(buf, " = ");
7027 
7028  get_rule_expr(expr, context, false);
7029  }
7030 }
7031 
7032 
7033 /* ----------
7034  * get_delete_query_def - Parse back a DELETE parsetree
7035  * ----------
7036  */
7037 static void
7039  bool colNamesVisible)
7040 {
7041  StringInfo buf = context->buf;
7042  RangeTblEntry *rte;
7043 
7044  /* Insert the WITH clause if given */
7045  get_with_clause(query, context);
7046 
7047  /*
7048  * Start the query with DELETE FROM relname
7049  */
7050  rte = rt_fetch(query->resultRelation, query->rtable);
7051  Assert(rte->rtekind == RTE_RELATION);
7052  if (PRETTY_INDENT(context))
7053  {
7054  appendStringInfoChar(buf, ' ');
7055  context->indentLevel += PRETTYINDENT_STD;
7056  }
7057  appendStringInfo(buf, "DELETE FROM %s%s",
7058  only_marker(rte),
7060 
7061  /* Print the relation alias, if needed */
7062  get_rte_alias(rte, query->resultRelation, false, context);
7063 
7064  /* Add the USING clause if given */
7065  get_from_clause(query, " USING ", context);
7066 
7067  /* Add a WHERE clause if given */
7068  if (query->jointree->quals != NULL)
7069  {
7070  appendContextKeyword(context, " WHERE ",
7072  get_rule_expr(query->jointree->quals, context, false);
7073  }
7074 
7075  /* Add RETURNING if present */
7076  if (query->returningList)
7077  {
7078  appendContextKeyword(context, " RETURNING",
7080  get_target_list(query->returningList, context, NULL, colNamesVisible);
7081  }
7082 }
7083 
7084 
7085 /* ----------
7086  * get_merge_query_def - Parse back a MERGE parsetree
7087  * ----------
7088  */
7089 static void
7091  bool colNamesVisible)
7092 {
7093  StringInfo buf = context->buf;
7094  RangeTblEntry *rte;
7095  ListCell *lc;
7096 
7097  /* Insert the WITH clause if given */
7098  get_with_clause(query, context);
7099 
7100  /*
7101  * Start the query with MERGE INTO relname
7102  */
7103  rte = rt_fetch(query->resultRelation, query->rtable);
7104  Assert(rte->rtekind == RTE_RELATION);
7105  if (PRETTY_INDENT(context))
7106  {
7107  appendStringInfoChar(buf, ' ');
7108  context->indentLevel += PRETTYINDENT_STD;
7109  }
7110  appendStringInfo(buf, "MERGE INTO %s%s",
7111  only_marker(rte),
7113 
7114  /* Print the relation alias, if needed */
7115  get_rte_alias(rte, query->resultRelation, false, context);
7116 
7117  /* Print the source relation and join clause */
7118  get_from_clause(query, " USING ", context);
7119  appendContextKeyword(context, " ON ",
7121  get_rule_expr(query->jointree->quals, context, false);
7122 
7123  /* Print each merge action */
7124  foreach(lc, query->mergeActionList)
7125  {
7127 
7128  appendContextKeyword(context, " WHEN ",
7130  appendStringInfo(buf, "%sMATCHED", action->matched ? "" : "NOT ");
7131 
7132  if (action->qual)
7133  {
7134  appendContextKeyword(context, " AND ",
7136  get_rule_expr(action->qual, context, false);
7137  }
7138  appendContextKeyword(context, " THEN ",
7140 
7141  if (action->commandType == CMD_INSERT)
7142  {
7143  /* This generally matches get_insert_query_def() */
7144  List *strippedexprs = NIL;
7145  const char *sep = "";
7146  ListCell *lc2;
7147 
7148  appendStringInfoString(buf, "INSERT");
7149 
7150  if (action->targetList)
7151  appendStringInfoString(buf, " (");
7152  foreach(lc2, action->targetList)
7153  {
7154  TargetEntry *tle = (TargetEntry *) lfirst(lc2);
7155 
7156  Assert(!tle->resjunk);
7157 
7159  sep = ", ";
7160 
7163  tle->resno,
7164  false)));
7165  strippedexprs = lappend(strippedexprs,
7166  processIndirection((Node *) tle->expr,
7167  context));
7168  }
7169  if (action->targetList)
7170  appendStringInfoChar(buf, ')');
7171 
7172  if (action->override)
7173  {
7174  if (action->override == OVERRIDING_SYSTEM_VALUE)
7175  appendStringInfoString(buf, " OVERRIDING SYSTEM VALUE");
7176  else if (action->override == OVERRIDING_USER_VALUE)
7177  appendStringInfoString(buf, " OVERRIDING USER VALUE");
7178  }
7179 
7180  if (strippedexprs)
7181  {
7182  appendContextKeyword(context, " VALUES (",
7184  get_rule_list_toplevel(strippedexprs, context, false);
7185  appendStringInfoChar(buf, ')');
7186  }
7187  else
7188  appendStringInfoString(buf, " DEFAULT VALUES");
7189  }
7190  else if (action->commandType == CMD_UPDATE)
7191  {
7192  appendStringInfoString(buf, "UPDATE SET ");
7193  get_update_query_targetlist_def(query, action->targetList,
7194  context, rte);
7195  }
7196  else if (action->commandType == CMD_DELETE)
7197  appendStringInfoString(buf, "DELETE");
7198  else if (action->commandType == CMD_NOTHING)
7199  appendStringInfoString(buf, "DO NOTHING");
7200  }
7201 
7202  /* Add RETURNING if present */
7203  if (query->returningList)
7204  {
7205  appendContextKeyword(context, " RETURNING",
7207  get_target_list(query->returningList, context, NULL, colNamesVisible);
7208  }
7209 }
7210 
7211 
7212 /* ----------
7213  * get_utility_query_def - Parse back a UTILITY parsetree
7214  * ----------
7215  */
7216 static void
7218 {
7219  StringInfo buf = context->buf;
7220 
7221  if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
7222  {
7223  NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
7224 
7225  appendContextKeyword(context, "",
7226  0, PRETTYINDENT_STD, 1);
7227  appendStringInfo(buf, "NOTIFY %s",
7228  quote_identifier(stmt->conditionname));
7229  if (stmt->payload)
7230  {
7231  appendStringInfoString(buf, ", ");
7232  simple_quote_literal(buf, stmt->payload);
7233  }
7234  }
7235  else
7236  {
7237  /* Currently only NOTIFY utility commands can appear in rules */
7238  elog(ERROR, "unexpected utility statement type");
7239  }
7240 }
7241 
7242 /*
7243  * Display a Var appropriately.
7244  *
7245  * In some cases (currently only when recursing into an unnamed join)
7246  * the Var's varlevelsup has to be interpreted with respect to a context
7247  * above the current one; levelsup indicates the offset.
7248  *
7249  * If istoplevel is true, the Var is at the top level of a SELECT's
7250  * targetlist, which means we need special treatment of whole-row Vars.
7251  * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a
7252  * dirty hack to prevent "tab.*" from being expanded into multiple columns.
7253  * (The parser will strip the useless coercion, so no inefficiency is added in
7254  * dump and reload.) We used to print just "tab" in such cases, but that is
7255  * ambiguous and will yield the wrong result if "tab" is also a plain column
7256  * name in the query.
7257  *
7258  * Returns the attname of the Var, or NULL if the Var has no attname (because
7259  * it is a whole-row Var or a subplan output reference).
7260  */
7261 static char *
7262 get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
7263 {
7264  StringInfo buf = context->buf;
7265  RangeTblEntry *rte;
7267  int netlevelsup;
7268  deparse_namespace *dpns;
7269  int varno;
7270  AttrNumber varattno;
7271  deparse_columns *colinfo;
7272  char *refname;
7273  char *attname;
7274 
7275  /* Find appropriate nesting depth */
7276  netlevelsup = var->varlevelsup + levelsup;
7277  if (netlevelsup >= list_length(context->namespaces))
7278  elog(ERROR, "bogus varlevelsup: %d offset %d",
7279  var->varlevelsup, levelsup);
7280  dpns = (deparse_namespace *) list_nth(context->namespaces,
7281  netlevelsup);
7282 
7283  /*
7284  * If we have a syntactic referent for the Var, and we're working from a
7285  * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7286  * on the semantic referent. (Forcing use of the semantic referent when
7287  * printing plan trees is a design choice that's perhaps more motivated by
7288  * backwards compatibility than anything else. But it does have the
7289  * advantage of making plans more explicit.)
7290  */
7291  if (var->varnosyn > 0 && dpns->plan == NULL)
7292  {
7293  varno = var->varnosyn;
7294  varattno = var->varattnosyn;
7295  }
7296  else
7297  {
7298  varno = var->varno;
7299  varattno = var->varattno;
7300  }
7301 
7302  /*
7303  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7304  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7305  * down into the subplans, or INDEX_VAR, which is resolved similarly. Also
7306  * find the aliases previously assigned for this RTE.
7307  */
7308  if (varno >= 1 && varno <= list_length(dpns->rtable))
7309  {
7310  /*
7311  * We might have been asked to map child Vars to some parent relation.
7312  */
7313  if (context->appendparents && dpns->appendrels)
7314  {
7315  int pvarno = varno;
7316  AttrNumber pvarattno = varattno;
7317  AppendRelInfo *appinfo = dpns->appendrels[pvarno];
7318  bool found = false;
7319 
7320  /* Only map up to inheritance parents, not UNION ALL appendrels */
7321  while (appinfo &&
7322  rt_fetch(appinfo->parent_relid,
7323  dpns->rtable)->rtekind == RTE_RELATION)
7324  {
7325  found = false;
7326  if (pvarattno > 0) /* system columns stay as-is */
7327  {
7328  if (pvarattno > appinfo->num_child_cols)
7329  break; /* safety check */
7330  pvarattno = appinfo->parent_colnos[pvarattno - 1];
7331  if (pvarattno == 0)
7332  break; /* Var is local to child */
7333  }
7334 
7335  pvarno = appinfo->parent_relid;
7336  found = true;
7337 
7338  /* If the parent is itself a child, continue up. */
7339  Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable));
7340  appinfo = dpns->appendrels[pvarno];
7341  }
7342 
7343  /*
7344  * If we found an ancestral rel, and that rel is included in
7345  * appendparents, print that column not the original one.
7346  */
7347  if (found && bms_is_member(pvarno, context->appendparents))
7348  {
7349  varno = pvarno;
7350  varattno = pvarattno;
7351  }
7352  }
7353 
7354  rte = rt_fetch(varno, dpns->rtable);
7355  refname = (char *) list_nth(dpns->rtable_names, varno - 1);
7356  colinfo = deparse_columns_fetch(varno, dpns);
7357  attnum = varattno;
7358  }
7359  else
7360  {
7361  resolve_special_varno((Node *) var, context,
7362  get_special_variable, NULL);
7363  return NULL;
7364  }
7365 
7366  /*
7367  * The planner will sometimes emit Vars referencing resjunk elements of a
7368  * subquery's target list (this is currently only possible if it chooses
7369  * to generate a "physical tlist" for a SubqueryScan or CteScan node).
7370  * Although we prefer to print subquery-referencing Vars using the
7371  * subquery's alias, that's not possible for resjunk items since they have
7372  * no alias. So in that case, drill down to the subplan and print the
7373  * contents of the referenced tlist item. This works because in a plan
7374  * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
7375  * we'll have set dpns->inner_plan to reference the child plan node.
7376  */
7377  if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
7378  attnum > list_length(rte->eref->colnames) &&
7379  dpns->inner_plan)
7380  {
7381  TargetEntry *tle;
7382  deparse_namespace save_dpns;
7383 
7384  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7385  if (!tle)
7386  elog(ERROR, "invalid attnum %d for relation \"%s\"",
7387  attnum, rte->eref->aliasname);
7388 
7389  Assert(netlevelsup == 0);
7390  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7391 
7392  /*
7393  * Force parentheses because our caller probably assumed a Var is a
7394  * simple expression.
7395  */
7396  if (!IsA(tle->expr, Var))
7397  appendStringInfoChar(buf, '(');
7398  get_rule_expr((Node *) tle->expr, context, true);
7399  if (!IsA(tle->expr, Var))
7400  appendStringInfoChar(buf, ')');
7401 
7402  pop_child_plan(dpns, &save_dpns);
7403  return NULL;
7404  }
7405 
7406  /*
7407  * If it's an unnamed join, look at the expansion of the alias variable.
7408  * If it's a simple reference to one of the input vars, then recursively
7409  * print the name of that var instead. When it's not a simple reference,
7410  * we have to just print the unqualified join column name. (This can only
7411  * happen with "dangerous" merged columns in a JOIN USING; we took pains
7412  * previously to make the unqualified column name unique in such cases.)
7413  *
7414  * This wouldn't work in decompiling plan trees, because we don't store
7415  * joinaliasvars lists after planning; but a plan tree should never
7416  * contain a join alias variable.
7417  */
7418  if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
7419  {
7420  if (rte->joinaliasvars == NIL)
7421  elog(ERROR, "cannot decompile join alias var in plan tree");
7422  if (attnum > 0)
7423  {
7424  Var *aliasvar;
7425 
7426  aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
7427  /* we intentionally don't strip implicit coercions here */
7428  if (aliasvar && IsA(aliasvar, Var))
7429  {
7430  return get_variable(aliasvar, var->varlevelsup + levelsup,
7431  istoplevel, context);
7432  }
7433  }
7434 
7435  /*
7436  * Unnamed join has no refname. (Note: since it's unnamed, there is
7437  * no way the user could have referenced it to create a whole-row Var
7438  * for it. So we don't have to cover that case below.)
7439  */
7440  Assert(refname == NULL);
7441  }
7442 
7443  if (attnum == InvalidAttrNumber)
7444  attname = NULL;
7445  else if (attnum > 0)
7446  {
7447  /* Get column name to use from the colinfo struct */
7448  if (attnum > colinfo->num_cols)
7449  elog(ERROR, "invalid attnum %d for relation \"%s\"",
7450  attnum, rte->eref->aliasname);
7451  attname = colinfo->colnames[attnum - 1];
7452 
7453  /*
7454  * If we find a Var referencing a dropped column, it seems better to
7455  * print something (anything) than to fail. In general this should
7456  * not happen, but it used to be possible for some cases involving
7457  * functions returning named composite types, and perhaps there are
7458  * still bugs out there.
7459  */
7460  if (attname == NULL)
7461  attname = "?dropped?column?";
7462  }
7463  else
7464  {
7465  /* System column - name is fixed, get it from the catalog */
7467  }
7468 
7469  if (refname && (context->varprefix || attname == NULL))
7470  {
7472  appendStringInfoChar(buf, '.');
7473  }
7474  if (attname)
7476  else
7477  {
7478  appendStringInfoChar(buf, '*');
7479  if (istoplevel)
7480  appendStringInfo(buf, "::%s",
7481  format_type_with_typemod(var->vartype,
7482  var->vartypmod));
7483  }
7484 
7485  return attname;
7486 }
7487 
7488 /*
7489  * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR. This
7490  * routine is actually a callback for resolve_special_varno, which handles
7491  * finding the correct TargetEntry. We get the expression contained in that
7492  * TargetEntry and just need to deparse it, a job we can throw back on
7493  * get_rule_expr.
7494  */
7495 static void
7496 get_special_variable(Node *node, deparse_context *context, void *callback_arg)
7497 {
7498  StringInfo buf = context->buf;
7499 
7500  /*
7501  * For a non-Var referent, force parentheses because our caller probably
7502  * assumed a Var is a simple expression.
7503  */
7504  if (!IsA(node, Var))
7505  appendStringInfoChar(buf, '(');
7506  get_rule_expr(node, context, true);
7507  if (!IsA(node, Var))
7508  appendStringInfoChar(buf, ')');
7509 }
7510 
7511 /*
7512  * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR,
7513  * INDEX_VAR) until we find a real Var or some kind of non-Var node; then,
7514  * invoke the callback provided.
7515  */
7516 static void
7518  rsv_callback callback, void *callback_arg)
7519 {
7520  Var *var;
7521  deparse_namespace *dpns;
7522 
7523  /* This function is recursive, so let's be paranoid. */
7525 
7526  /* If it's not a Var, invoke the callback. */
7527  if (!IsA(node, Var))
7528  {
7529  (*callback) (node, context, callback_arg);
7530  return;
7531  }
7532 
7533  /* Find appropriate nesting depth */
7534  var = (Var *) node;
7535  dpns = (deparse_namespace *) list_nth(context->namespaces,
7536  var->varlevelsup);
7537 
7538  /*
7539  * If varno is special, recurse. (Don't worry about varnosyn; if we're
7540  * here, we already decided not to use that.)
7541  */
7542  if (var->varno == OUTER_VAR && dpns->outer_tlist)
7543  {
7544  TargetEntry *tle;
7545  deparse_namespace save_dpns;
7546  Bitmapset *save_appendparents;
7547 
7548  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
7549  if (!tle)
7550  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
7551 
7552  /*
7553  * If we're descending to the first child of an Append or MergeAppend,
7554  * update appendparents. This will affect deparsing of all Vars
7555  * appearing within the eventually-resolved subexpression.
7556  */
7557  save_appendparents = context->appendparents;
7558 
7559  if (IsA(dpns->plan, Append))
7560  context->appendparents = bms_union(context->appendparents,
7561  ((Append *) dpns->plan)->apprelids);
7562  else if (IsA(dpns->plan, MergeAppend))
7563  context->appendparents = bms_union(context->appendparents,
7564  ((MergeAppend *) dpns->plan)->apprelids);
7565 
7566  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7567  resolve_special_varno((Node *) tle->expr, context,
7568  callback, callback_arg);
7569  pop_child_plan(dpns, &save_dpns);
7570  context->appendparents = save_appendparents;
7571  return;
7572  }
7573  else if (var->varno == INNER_VAR && dpns->inner_tlist)
7574  {
7575  TargetEntry *tle;
7576  deparse_namespace save_dpns;
7577 
7578  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
7579  if (!tle)
7580  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
7581 
7582  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7583  resolve_special_varno((Node *) tle->expr, context,
7584  callback, callback_arg);
7585  pop_child_plan(dpns, &save_dpns);
7586  return;
7587  }
7588  else if (var->varno == INDEX_VAR && dpns->index_tlist)
7589  {
7590  TargetEntry *tle;
7591 
7592  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
7593  if (!tle)
7594  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
7595 
7596  resolve_special_varno((Node *) tle->expr, context,
7597  callback, callback_arg);
7598  return;
7599  }
7600  else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
7601  elog(ERROR, "bogus varno: %d", var->varno);
7602 
7603  /* Not special. Just invoke the callback. */
7604  (*callback) (node, context, callback_arg);
7605 }
7606 
7607 /*
7608  * Get the name of a field of an expression of composite type. The
7609  * expression is usually a Var, but we handle other cases too.
7610  *
7611  * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
7612  *
7613  * This is fairly straightforward when the expression has a named composite
7614  * type; we need only look up the type in the catalogs. However, the type
7615  * could also be RECORD. Since no actual table or view column is allowed to
7616  * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
7617  * or to a subquery output. We drill down to find the ultimate defining
7618  * expression and attempt to infer the field name from it. We ereport if we
7619  * can't determine the name.
7620  *
7621  * Similarly, a PARAM of type RECORD has to refer to some expression of
7622  * a determinable composite type.
7623  */
7624 static const char *
7625 get_name_for_var_field(Var *var, int fieldno,
7626  int levelsup, deparse_context *context)
7627 {
7628  RangeTblEntry *rte;
7630  int netlevelsup;
7631  deparse_namespace *dpns;
7632  int varno;
7633  AttrNumber varattno;
7634  TupleDesc tupleDesc;
7635  Node *expr;
7636 
7637  /*
7638  * If it's a RowExpr that was expanded from a whole-row Var, use the
7639  * column names attached to it. (We could let get_expr_result_tupdesc()
7640  * handle this, but it's much cheaper to just pull out the name we need.)
7641  */
7642  if (IsA(var, RowExpr))
7643  {
7644  RowExpr *r = (RowExpr *) var;
7645 
7646  if (fieldno > 0 && fieldno <= list_length(r->colnames))
7647  return strVal(list_nth(r->colnames, fieldno - 1));
7648  }
7649 
7650  /*
7651  * If it's a Param of type RECORD, try to find what the Param refers to.
7652  */
7653  if (IsA(var, Param))
7654  {
7655  Param *param = (Param *) var;
7656  ListCell *ancestor_cell;
7657 
7658  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7659  if (expr)
7660  {
7661  /* Found a match, so recurse to decipher the field name */
7662  deparse_namespace save_dpns;
7663  const char *result;
7664 
7665  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7666  result = get_name_for_var_field((Var *) expr, fieldno,
7667  0, context);
7668  pop_ancestor_plan(dpns, &save_dpns);
7669  return result;
7670  }
7671  }
7672 
7673  /*
7674  * If it's a Var of type RECORD, we have to find what the Var refers to;
7675  * if not, we can use get_expr_result_tupdesc().
7676  */
7677  if (!IsA(var, Var) ||
7678  var->vartype != RECORDOID)
7679  {
7680  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7681  /* Got the tupdesc, so we can extract the field name */
7682  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7683  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7684  }
7685 
7686  /* Find appropriate nesting depth */
7687  netlevelsup = var->varlevelsup + levelsup;
7688  if (netlevelsup >= list_length(context->namespaces))
7689  elog(ERROR, "bogus varlevelsup: %d offset %d",
7690  var->varlevelsup, levelsup);
7691  dpns = (deparse_namespace *) list_nth(context->namespaces,
7692  netlevelsup);
7693 
7694  /*
7695  * If we have a syntactic referent for the Var, and we're working from a
7696  * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7697  * on the semantic referent. (See comments in get_variable().)
7698  */
7699  if (var->varnosyn > 0 && dpns->plan == NULL)
7700  {
7701  varno = var->varnosyn;
7702  varattno = var->varattnosyn;
7703  }
7704  else
7705  {
7706  varno = var->varno;
7707  varattno = var->varattno;
7708  }
7709 
7710  /*
7711  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7712  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7713  * down into the subplans, or INDEX_VAR, which is resolved similarly.
7714  *
7715  * Note: unlike get_variable and resolve_special_varno, we need not worry
7716  * about inheritance mapping: a child Var should have the same datatype as
7717  * its parent, and here we're really only interested in the Var's type.
7718  */
7719  if (varno >= 1 && varno <= list_length(dpns->rtable))
7720  {
7721  rte = rt_fetch(varno, dpns->rtable);
7722  attnum = varattno;
7723  }
7724  else if (varno == OUTER_VAR && dpns->outer_tlist)
7725  {
7726  TargetEntry *tle;
7727  deparse_namespace save_dpns;
7728  const char *result;
7729 
7730  tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7731  if (!tle)
7732  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7733 
7734  Assert(netlevelsup == 0);
7735  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7736 
7737  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7738  levelsup, context);
7739 
7740  pop_child_plan(dpns, &save_dpns);
7741  return result;
7742  }
7743  else if (varno == INNER_VAR && dpns->inner_tlist)
7744  {
7745  TargetEntry *tle;
7746  deparse_namespace save_dpns;
7747  const char *result;
7748 
7749  tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7750  if (!tle)
7751  elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7752 
7753  Assert(netlevelsup == 0);
7754  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7755 
7756  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7757  levelsup, context);
7758 
7759  pop_child_plan(dpns, &save_dpns);
7760  return result;
7761  }
7762  else if (varno == INDEX_VAR && dpns->index_tlist)
7763  {
7764  TargetEntry *tle;
7765  const char *result;
7766 
7767  tle = get_tle_by_resno(dpns->index_tlist, varattno);
7768  if (!tle)
7769  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7770 
7771  Assert(netlevelsup == 0);
7772 
7773  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7774  levelsup, context);
7775 
7776  return result;
7777  }
7778  else
7779  {
7780  elog(ERROR, "bogus varno: %d", varno);
7781  return NULL; /* keep compiler quiet */
7782  }
7783 
7784  if (attnum == InvalidAttrNumber)
7785  {
7786  /* Var is whole-row reference to RTE, so select the right field */
7787  return get_rte_attribute_name(rte, fieldno);
7788  }
7789 
7790  /*
7791  * This part has essentially the same logic as the parser's
7792  * expandRecordVariable() function, but we are dealing with a different
7793  * representation of the input context, and we only need one field name
7794  * not a TupleDesc. Also, we need special cases for finding subquery and
7795  * CTE subplans when deparsing Plan trees.
7796  */
7797  expr = (Node *) var; /* default if we can't drill down */
7798 
7799  switch (rte->rtekind)
7800  {
7801  case RTE_RELATION:
7802  case RTE_VALUES:
7803  case RTE_NAMEDTUPLESTORE:
7804  case RTE_RESULT:
7805 
7806  /*
7807  * This case should not occur: a column of a table, values list,
7808  * or ENR shouldn't have type RECORD. Fall through and fail (most
7809  * likely) at the bottom.
7810  */
7811  break;
7812  case RTE_SUBQUERY:
7813  /* Subselect-in-FROM: examine sub-select's output expr */
7814  {
7815  if (rte->subquery)
7816  {
7818  attnum);
7819 
7820  if (ste == NULL || ste->resjunk)
7821  elog(ERROR, "subquery %s does not have attribute %d",
7822  rte->eref->aliasname, attnum);
7823  expr = (Node *) ste->expr;
7824  if (IsA(expr, Var))
7825  {
7826  /*
7827  * Recurse into the sub-select to see what its Var
7828  * refers to. We have to build an additional level of
7829  * namespace to keep in step with varlevelsup in the
7830  * subselect; furthermore, the subquery RTE might be
7831  * from an outer query level, in which case the
7832  * namespace for the subselect must have that outer
7833  * level as parent namespace.
7834  */
7835  List *save_nslist = context->namespaces;
7836  List *parent_namespaces;
7837  deparse_namespace mydpns;
7838  const char *result;
7839 
7840  parent_namespaces = list_copy_tail(context->namespaces,
7841  netlevelsup);
7842 
7843  set_deparse_for_query(&mydpns, rte->subquery,
7844  parent_namespaces);
7845 
7846  context->namespaces = lcons(&mydpns, parent_namespaces);
7847 
7848  result = get_name_for_var_field((Var *) expr, fieldno,
7849  0, context);
7850 
7851  context->namespaces = save_nslist;
7852 
7853  return result;
7854  }
7855  /* else fall through to inspect the expression */
7856  }
7857  else
7858  {
7859  /*
7860  * We're deparsing a Plan tree so we don't have complete
7861  * RTE entries (in particular, rte->subquery is NULL). But
7862  * the only place we'd see a Var directly referencing a
7863  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7864  * look into the child plan's tlist instead.
7865  */
7866  TargetEntry *tle;
7867  deparse_namespace save_dpns;
7868  const char *result;
7869 
7870  if (!dpns->inner_plan)
7871  elog(ERROR, "failed to find plan for subquery %s",
7872  rte->eref->aliasname);
7873  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7874  if (!tle)
7875  elog(ERROR, "bogus varattno for subquery var: %d",
7876  attnum);
7877  Assert(netlevelsup == 0);
7878  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7879 
7880  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7881  levelsup, context);
7882 
7883  pop_child_plan(dpns, &save_dpns);
7884  return result;
7885  }
7886  }
7887  break;
7888  case RTE_JOIN:
7889  /* Join RTE --- recursively inspect the alias variable */
7890  if (rte->joinaliasvars == NIL)
7891  elog(ERROR, "cannot decompile join alias var in plan tree");
7892  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7893  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7894  Assert(expr != NULL);
7895  /* we intentionally don't strip implicit coercions here */
7896  if (IsA(expr, Var))
7897  return get_name_for_var_field((Var *) expr, fieldno,
7898  var->varlevelsup + levelsup,
7899  context);
7900  /* else fall through to inspect the expression */
7901  break;
7902  case RTE_FUNCTION:
7903  case RTE_TABLEFUNC:
7904 
7905  /*
7906  * We couldn't get here unless a function is declared with one of
7907  * its result columns as RECORD, which is not allowed.
7908  */
7909  break;
7910  case RTE_CTE:
7911  /* CTE reference: examine subquery's output expr */
7912  {
7913  CommonTableExpr *cte = NULL;
7914  Index ctelevelsup;
7915  ListCell *lc;
7916 
7917  /*
7918  * Try to find the referenced CTE using the namespace stack.
7919  */
7920  ctelevelsup = rte->ctelevelsup + netlevelsup;
7921  if (ctelevelsup >= list_length(context->namespaces))
7922  lc = NULL;
7923  else
7924  {
7925  deparse_namespace *ctedpns;
7926 
7927  ctedpns = (deparse_namespace *)
7928  list_nth(context->namespaces, ctelevelsup);
7929  foreach(lc, ctedpns->ctes)
7930  {
7931  cte = (CommonTableExpr *) lfirst(lc);
7932  if (strcmp(cte->ctename, rte->ctename) == 0)
7933  break;
7934  }
7935  }
7936  if (lc != NULL)
7937  {
7938  Query *ctequery = (Query *) cte->ctequery;
7940  attnum);
7941 
7942  if (ste == NULL || ste->resjunk)
7943  elog(ERROR, "CTE %s does not have attribute %d",
7944  rte->eref->aliasname, attnum);
7945  expr = (Node *) ste->expr;
7946  if (IsA(expr, Var))
7947  {
7948  /*
7949  * Recurse into the CTE to see what its Var refers to.
7950  * We have to build an additional level of namespace
7951  * to keep in step with varlevelsup in the CTE;
7952  * furthermore it could be an outer CTE (compare
7953  * SUBQUERY case above).
7954  */
7955  List *save_nslist = context->namespaces;
7956  List *parent_namespaces;
7957  deparse_namespace mydpns;
7958  const char *result;
7959 
7960  parent_namespaces = list_copy_tail(context->namespaces,
7961  ctelevelsup);
7962 
7963  set_deparse_for_query(&mydpns, ctequery,
7964  parent_namespaces);
7965 
7966  context->namespaces = lcons(&mydpns, parent_namespaces);
7967 
7968  result = get_name_for_var_field((Var *) expr, fieldno,
7969  0, context);
7970 
7971  context->namespaces = save_nslist;
7972 
7973  return result;
7974  }
7975  /* else fall through to inspect the expression */
7976  }
7977  else
7978  {
7979  /*
7980  * We're deparsing a Plan tree so we don't have a CTE
7981  * list. But the only places we'd see a Var directly
7982  * referencing a CTE RTE are in CteScan or WorkTableScan
7983  * plan nodes. For those cases, set_deparse_plan arranged
7984  * for dpns->inner_plan to be the plan node that emits the
7985  * CTE or RecursiveUnion result, and we can look at its
7986  * tlist instead.
7987  */
7988  TargetEntry *tle;
7989  deparse_namespace save_dpns;
7990  const char *result;
7991 
7992  if (!dpns->inner_plan)
7993  elog(ERROR, "failed to find plan for CTE %s",
7994  rte->eref->aliasname);
7995  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7996  if (!tle)
7997  elog(ERROR, "bogus varattno for subquery var: %d",
7998  attnum);
7999  Assert(netlevelsup == 0);
8000  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
8001 
8002  result = get_name_for_var_field((Var *) tle->expr, fieldno,
8003  levelsup, context);
8004 
8005  pop_child_plan(dpns, &save_dpns);
8006  return result;
8007  }
8008  }
8009  break;
8010  }
8011 
8012  /*
8013  * We now have an expression we can't expand any more, so see if
8014  * get_expr_result_tupdesc() can do anything with it.
8015  */
8016  tupleDesc = get_expr_result_tupdesc(expr, false);
8017  /* Got the tupdesc, so we can extract the field name */
8018  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
8019  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
8020 }
8021 
8022 /*
8023  * Try to find the referenced expression for a PARAM_EXEC Param that might
8024  * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
8025  *
8026  * If successful, return the expression and set *dpns_p and *ancestor_cell_p
8027  * appropriately for calling push_ancestor_plan(). If no referent can be
8028  * found, return NULL.
8029  */
8030 static Node *
8032  deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
8033 {
8034  /* Initialize output parameters to prevent compiler warnings */
8035  *dpns_p = NULL;
8036  *ancestor_cell_p = NULL;
8037 
8038  /*
8039  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
8040  * SubPlan argument. This will necessarily be in some ancestor of the
8041  * current expression's Plan node.
8042  */
8043  if (param->paramkind == PARAM_EXEC)
8044  {
8045  deparse_namespace *dpns;
8046  Plan *child_plan;
8047  ListCell *lc;
8048 
8049  dpns = (deparse_namespace *) linitial(context->namespaces);
8050  child_plan = dpns->plan;
8051 
8052  foreach(lc, dpns->ancestors)
8053  {
8054  Node *ancestor = (Node *) lfirst(lc);
8055  ListCell *lc2;
8056 
8057  /*
8058  * NestLoops transmit params to their inner child only.
8059  */
8060  if (IsA(ancestor, NestLoop) &&
8061  child_plan == innerPlan(ancestor))
8062  {
8063  NestLoop *nl = (NestLoop *) ancestor;
8064 
8065  foreach(lc2, nl->nestParams)
8066  {
8067  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
8068 
8069  if (nlp->paramno == param->paramid)
8070  {
8071  /* Found a match, so return it */
8072  *dpns_p = dpns;
8073  *ancestor_cell_p = lc;
8074  return (Node *) nlp->paramval;
8075  }
8076  }
8077  }
8078 
8079  /*
8080  * If ancestor is a SubPlan, check the arguments it provides.
8081  */
8082  if (IsA(ancestor, SubPlan))
8083  {
8084  SubPlan *subplan = (SubPlan *) ancestor;
8085  ListCell *lc3;
8086  ListCell *lc4;
8087 
8088  forboth(lc3, subplan->parParam, lc4, subplan->args)
8089  {
8090  int paramid = lfirst_int(lc3);
8091  Node *arg = (Node *) lfirst(lc4);
8092 
8093  if (paramid == param->paramid)
8094  {
8095  /*
8096  * Found a match, so return it. But, since Vars in
8097  * the arg are to be evaluated in the surrounding
8098  * context, we have to point to the next ancestor item
8099  * that is *not* a SubPlan.
8100  */
8101  ListCell *rest;
8102 
8103  for_each_cell(rest, dpns->ancestors,
8104  lnext(dpns->ancestors, lc))
8105  {
8106  Node *ancestor2 = (Node *) lfirst(rest);
8107 
8108  if (!IsA(ancestor2, SubPlan))
8109  {
8110  *dpns_p = dpns;
8111  *ancestor_cell_p = rest;
8112  return arg;
8113  }
8114  }
8115  elog(ERROR, "SubPlan cannot be outermost ancestor");
8116  }
8117  }
8118 
8119  /* SubPlan isn't a kind of Plan, so skip the rest */
8120  continue;
8121  }
8122 
8123  /*
8124  * We need not consider the ancestor's initPlan list, since
8125  * initplans never have any parParams.
8126  */
8127 
8128  /* No luck, crawl up to next ancestor */
8129  child_plan = (Plan *) ancestor;
8130  }
8131  }
8132 
8133  /* No referent found */
8134  return NULL;
8135 }
8136 
8137 /*
8138  * Display a Param appropriately.
8139  */
8140 static void
8142 {
8143  Node *expr;
8144  deparse_namespace *dpns;
8145  ListCell *ancestor_cell;
8146 
8147  /*
8148  * If it's a PARAM_EXEC parameter, try to locate the expression from which
8149  * the parameter was computed. Note that failing to find a referent isn't
8150  * an error, since the Param might well be a subplan output rather than an
8151  * input.
8152  */
8153  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
8154  if (expr)
8155  {
8156  /* Found a match, so print it */
8157  deparse_namespace save_dpns;
8158  bool save_varprefix;
8159  bool need_paren;
8160 
8161  /* Switch attention to the ancestor plan node */
8162  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
8163 
8164  /*
8165  * Force prefixing of Vars, since they won't belong to the relation
8166  * being scanned in the original plan node.
8167  */
8168  save_varprefix = context->varprefix;
8169  context->varprefix = true;
8170 
8171  /*
8172  * A Param's expansion is typically a Var, Aggref, GroupingFunc, or
8173  * upper-level Param, which wouldn't need extra parentheses.
8174  * Otherwise, insert parens to ensure the expression looks atomic.
8175  */
8176  need_paren = !(IsA(expr, Var) ||
8177  IsA(expr, Aggref) ||
8178  IsA(expr, GroupingFunc) ||
8179  IsA(expr, Param));
8180  if (need_paren)
8181  appendStringInfoChar(context->buf, '(');
8182 
8183  get_rule_expr(expr, context, false);
8184 
8185  if (need_paren)
8186  appendStringInfoChar(context->buf, ')');
8187 
8188  context->varprefix = save_varprefix;
8189 
8190  pop_ancestor_plan(dpns, &save_dpns);
8191 
8192  return;
8193  }
8194 
8195  /*
8196  * If it's an external parameter, see if the outermost namespace provides
8197  * function argument names.
8198  */
8199  if (param->paramkind == PARAM_EXTERN && context->namespaces != NIL)
8200  {
8201  dpns = llast(context->namespaces);
8202  if (dpns->argnames &&
8203  param->paramid > 0 &&
8204  param->paramid <= dpns->numargs)
8205  {
8206  char *argname = dpns->argnames[param->paramid - 1];
8207 
8208  if (argname)
8209  {
8210  bool should_qualify = false;
8211  ListCell *lc;
8212 
8213  /*
8214  * Qualify the parameter name if there are any other deparse
8215  * namespaces with range tables. This avoids qualifying in
8216  * trivial cases like "RETURN a + b", but makes it safe in all
8217  * other cases.
8218  */
8219  foreach(lc, context->namespaces)
8220  {
8221  deparse_namespace *depns = lfirst(lc);
8222 
8223  if (depns->rtable_names != NIL)
8224  {
8225  should_qualify = true;
8226  break;
8227  }
8228  }
8229  if (should_qualify)
8230  {
8232  appendStringInfoChar(context->buf, '.');
8233  }
8234 
8235  appendStringInfoString(context->buf, quote_identifier(argname));
8236  return;
8237  }
8238  }
8239  }
8240 
8241  /*
8242  * Not PARAM_EXEC, or couldn't find referent: just print $N.
8243  */
8244  appendStringInfo(context->buf, "$%d", param->paramid);
8245 }
8246 
8247 /*
8248  * get_simple_binary_op_name
8249  *
8250  * helper function for isSimpleNode
8251  * will return single char binary operator name, or NULL if it's not
8252  */
8253 static const char *
8255 {
8256  List *args = expr->args;
8257 
8258  if (list_length(args) == 2)
8259  {
8260  /* binary operator */
8261  Node *arg1 = (Node *) linitial(args);
8262  Node *arg2 = (Node *) lsecond(args);
8263  const char *op;
8264 
8265  op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
8266  if (strlen(op) == 1)
8267  return op;
8268  }
8269  return NULL;
8270 }
8271 
8272 
8273 /*
8274  * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
8275  *
8276  * true : simple in the context of parent node's type
8277  * false : not simple
8278  */
8279 static bool
8280 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
8281 {
8282  if (!node)
8283  return false;
8284 
8285  switch (nodeTag(node))
8286  {
8287  case T_Var:
8288  case T_Const:
8289  case T_Param:
8290  case T_CoerceToDomainValue:
8291  case T_SetToDefault:
8292  case T_CurrentOfExpr:
8293  /* single words: always simple */
8294  return true;
8295 
8296  case T_SubscriptingRef:
8297  case T_ArrayExpr:
8298  case T_RowExpr:
8299  case T_CoalesceExpr:
8300  case T_MinMaxExpr:
8301  case T_SQLValueFunction:
8302  case T_XmlExpr:
8303  case T_NextValueExpr:
8304  case T_NullIfExpr:
8305  case T_Aggref:
8306  case T_GroupingFunc:
8307  case T_WindowFunc:
8308  case T_MergeSupportFunc:
8309  case T_FuncExpr:
8310  case T_JsonConstructorExpr:
8311  /* function-like: name(..) or name[..] */
8312  return true;
8313 
8314  /* CASE keywords act as parentheses */
8315  case T_CaseExpr:
8316  return true;
8317 
8318  case T_FieldSelect:
8319 
8320  /*
8321  * appears simple since . has top precedence, unless parent is
8322  * T_FieldSelect itself!
8323  */
8324  return !IsA(parentNode, FieldSelect);
8325 
8326  case T_FieldStore:
8327 
8328  /*
8329  * treat like FieldSelect (probably doesn't matter)
8330  */
8331  return !IsA(parentNode, FieldStore);
8332 
8333  case T_CoerceToDomain:
8334  /* maybe simple, check args */
8335  return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
8336  node, prettyFlags);
8337  case T_RelabelType:
8338  return isSimpleNode((Node *) ((RelabelType *) node)->arg,
8339  node, prettyFlags);
8340  case T_CoerceViaIO:
8341  return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
8342  node, prettyFlags);
8343  case T_ArrayCoerceExpr:
8344  return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
8345  node, prettyFlags);
8346  case T_ConvertRowtypeExpr:
8347  return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
8348  node, prettyFlags);
8349 
8350  case T_OpExpr:
8351  {
8352  /* depends on parent node type; needs further checking */
8353  if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
8354  {
8355  const char *op;
8356  const char *parentOp;
8357  bool is_lopriop;
8358  bool is_hipriop;
8359  bool is_lopriparent;
8360  bool is_hipriparent;
8361 
8362  op = get_simple_binary_op_name((OpExpr *) node);
8363  if (!op)
8364  return false;
8365 
8366  /* We know only the basic operators + - and * / % */
8367  is_lopriop = (strchr("+-", *op) != NULL);
8368  is_hipriop = (strchr("*/%", *op) != NULL);
8369  if (!(is_lopriop || is_hipriop))
8370  return false;
8371 
8372  parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
8373  if (!parentOp)
8374  return false;
8375 
8376  is_lopriparent = (strchr("+-", *parentOp) != NULL);
8377  is_hipriparent = (strchr("*/%", *parentOp) != NULL);
8378  if (!(is_lopriparent || is_hipriparent))
8379  return false;
8380 
8381  if (is_hipriop && is_lopriparent)
8382  return true; /* op binds tighter than parent */
8383 
8384  if (is_lopriop && is_hipriparent)
8385  return false;
8386 
8387  /*
8388  * Operators are same priority --- can skip parens only if
8389  * we have (a - b) - c, not a - (b - c).
8390  */
8391  if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
8392  return true;
8393 
8394  return false;
8395  }
8396  /* else do the same stuff as for T_SubLink et al. */
8397  }
8398  /* FALLTHROUGH */
8399 
8400  case T_SubLink:
8401  case T_NullTest:
8402  case T_BooleanTest:
8403  case T_DistinctExpr:
8404  case T_JsonIsPredicate:
8405  switch (nodeTag(parentNode))
8406  {
8407  case T_FuncExpr:
8408  {
8409  /* special handling for casts and COERCE_SQL_SYNTAX */
8410  CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8411 
8412  if (type == COERCE_EXPLICIT_CAST ||
8415  return false;
8416  return true; /* own parentheses */
8417  }
8418  case T_BoolExpr: /* lower precedence */
8419  case T_SubscriptingRef: /* other separators */
8420  case T_ArrayExpr: /* other separators */
8421  case T_RowExpr: /* other separators */
8422  case T_CoalesceExpr: /* own parentheses */
8423  case T_MinMaxExpr: /* own parentheses */
8424  case T_XmlExpr: /* own parentheses */
8425  case T_NullIfExpr: /* other separators */
8426  case T_Aggref: /* own parentheses */
8427  case T_GroupingFunc: /* own parentheses */
8428  case T_WindowFunc: /* own parentheses */
8429  case T_CaseExpr: /* other separators */
8430  return true;
8431  default:
8432  return false;
8433  }
8434 
8435  case T_BoolExpr:
8436  switch (nodeTag(parentNode))
8437  {
8438  case T_BoolExpr:
8439  if (prettyFlags & PRETTYFLAG_PAREN)
8440  {
8442  BoolExprType parentType;
8443 
8444  type = ((BoolExpr *) node)->boolop;
8445  parentType = ((BoolExpr *) parentNode)->boolop;
8446  switch (type)
8447  {
8448  case NOT_EXPR:
8449  case AND_EXPR:
8450  if (parentType == AND_EXPR || parentType == OR_EXPR)
8451  return true;
8452  break;
8453  case OR_EXPR:
8454  if (parentType == OR_EXPR)
8455  return true;
8456  break;
8457  }
8458  }
8459  return false;
8460  case T_FuncExpr:
8461  {
8462  /* special handling for casts and COERCE_SQL_SYNTAX */
8463  CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8464 
8465  if (type == COERCE_EXPLICIT_CAST ||
8468  return false;
8469  return true; /* own parentheses */
8470  }
8471  case T_SubscriptingRef: /* other separators */
8472  case T_ArrayExpr: /* other separators */
8473  case T_RowExpr: /* other separators */
8474  case T_CoalesceExpr: /* own parentheses */
8475  case T_MinMaxExpr: /* own parentheses */
8476  case T_XmlExpr: /* own parentheses */
8477  case T_NullIfExpr: /* other separators */
8478  case T_Aggref: /* own parentheses */
8479  case T_GroupingFunc: /* own parentheses */
8480  case T_WindowFunc: /* own parentheses */
8481  case T_CaseExpr: /* other separators */
8482  return true;
8483  default:
8484  return false;
8485  }
8486 
8487  case T_JsonValueExpr:
8488  /* maybe simple, check args */
8489  return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
8490  node, prettyFlags);
8491 
8492  default:
8493  break;
8494  }
8495  /* those we don't know: in dubio complexo */
8496  return false;
8497 }
8498 
8499 
8500 /*
8501  * appendContextKeyword - append a keyword to buffer
8502  *
8503  * If prettyPrint is enabled, perform a line break, and adjust indentation.
8504  * Otherwise, just append the keyword.
8505  */
8506 static void
8508  int indentBefore, int indentAfter, int indentPlus)
8509 {
8510  StringInfo buf = context->buf;
8511 
8512  if (PRETTY_INDENT(context))
8513  {
8514  int indentAmount;
8515 
8516  context->indentLevel += indentBefore;
8517 
8518  /* remove any trailing spaces currently in the buffer ... */
8520  /* ... then add a newline and some spaces */
8521  appendStringInfoChar(buf, '\n');
8522 
8523  if (context->indentLevel < PRETTYINDENT_LIMIT)
8524  indentAmount = Max(context->indentLevel, 0) + indentPlus;
8525  else
8526  {
8527  /*
8528  * If we're indented more than PRETTYINDENT_LIMIT characters, try
8529  * to conserve horizontal space by reducing the per-level
8530  * indentation. For best results the scale factor here should
8531  * divide all the indent amounts that get added to indentLevel
8532  * (PRETTYINDENT_STD, etc). It's important that the indentation
8533  * not grow unboundedly, else deeply-nested trees use O(N^2)
8534  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
8535  */
8536  indentAmount = PRETTYINDENT_LIMIT +
8537  (context->indentLevel - PRETTYINDENT_LIMIT) /
8538  (PRETTYINDENT_STD / 2);
8539  indentAmount %= PRETTYINDENT_LIMIT;
8540  /* scale/wrap logic affects indentLevel, but not indentPlus */
8541  indentAmount += indentPlus;
8542  }
8543  appendStringInfoSpaces(buf, indentAmount);
8544 
8546 
8547  context->indentLevel += indentAfter;
8548  if (context->indentLevel < 0)
8549  context->indentLevel = 0;
8550  }
8551  else
8553 }
8554 
8555 /*
8556  * removeStringInfoSpaces - delete trailing spaces from a buffer.
8557  *
8558  * Possibly this should move to stringinfo.c at some point.
8559  */
8560 static void
8562 {
8563  while (str->len > 0 && str->data[str->len - 1] == ' ')
8564  str->data[--(str->len)] = '\0';
8565 }
8566 
8567 
8568 /*
8569  * get_rule_expr_paren - deparse expr using get_rule_expr,
8570  * embracing the string with parentheses if necessary for prettyPrint.
8571  *
8572  * Never embrace if prettyFlags=0, because it's done in the calling node.
8573  *
8574  * Any node that does *not* embrace its argument node by sql syntax (with
8575  * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
8576  * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
8577  * added.
8578  */
8579 static void
8581  bool showimplicit, Node *parentNode)
8582 {
8583  bool need_paren;
8584 
8585  need_paren = PRETTY_PAREN(context) &&
8586  !isSimpleNode(node, parentNode, context->prettyFlags);
8587 
8588  if (need_paren)
8589  appendStringInfoChar(context->buf, '(');
8590 
8591  get_rule_expr(node, context, showimplicit);
8592 
8593  if (need_paren)
8594  appendStringInfoChar(context->buf, ')');
8595 }
8596 
8597 
8598 /* ----------
8599  * get_rule_expr - Parse back an expression
8600  *
8601  * Note: showimplicit determines whether we display any implicit cast that
8602  * is present at the top of the expression tree. It is a passed argument,
8603  * not a field of the context struct, because we change the value as we
8604  * recurse down into the expression. In general we suppress implicit casts
8605  * when the result type is known with certainty (eg, the arguments of an
8606  * OR must be boolean). We display implicit casts for arguments of functions
8607  * and operators, since this is needed to be certain that the same function
8608  * or operator will be chosen when the expression is re-parsed.
8609  * ----------
8610  */
8611 static void
8613  bool showimplicit)
8614 {
8615  StringInfo buf = context->buf;
8616 
8617  if (node == NULL)
8618  return;
8619 
8620  /* Guard against excessively long or deeply-nested queries */
8623 
8624  /*
8625  * Each level of get_rule_expr must emit an indivisible term
8626  * (parenthesized if necessary) to ensure result is reparsed into the same
8627  * expression tree. The only exception is that when the input is a List,
8628  * we emit the component items comma-separated with no surrounding
8629  * decoration; this is convenient for most callers.
8630  */
8631  switch (nodeTag(node))
8632  {
8633  case T_Var:
8634  (void) get_variable((Var *) node, 0, false, context);
8635  break;
8636 
8637  case T_Const:
8638  get_const_expr((Const *) node, context, 0);
8639  break;
8640 
8641  case T_Param:
8642  get_parameter((Param *) node, context);
8643  break;
8644 
8645  case T_Aggref:
8646  get_agg_expr((Aggref *) node, context, (Aggref *) node);
8647  break;
8648 
8649  case T_GroupingFunc:
8650  {
8651  GroupingFunc *gexpr = (GroupingFunc *) node;
8652 
8653  appendStringInfoString(buf, "GROUPING(");
8654  get_rule_expr((Node *) gexpr->args, context, true);
8655  appendStringInfoChar(buf, ')');
8656  }
8657  break;
8658 
8659  case T_WindowFunc:
8660  get_windowfunc_expr((WindowFunc *) node, context);
8661  break;
8662 
8663  case T_MergeSupportFunc:
8664  appendStringInfoString(buf, "MERGE_ACTION()");
8665  break;
8666 
8667  case T_SubscriptingRef:
8668  {
8669  SubscriptingRef *sbsref = (SubscriptingRef *) node;
8670  bool need_parens;
8671 
8672  /*
8673  * If the argument is a CaseTestExpr, we must be inside a
8674  * FieldStore, ie, we are assigning to an element of an array
8675  * within a composite column. Since we already punted on
8676  * displaying the FieldStore's target information, just punt
8677  * here too, and display only the assignment source
8678  * expression.
8679  */
8680  if (IsA(sbsref->refexpr, CaseTestExpr))
8681  {
8682  Assert(sbsref->refassgnexpr);
8683  get_rule_expr((Node *) sbsref->refassgnexpr,
8684  context, showimplicit);
8685  break;
8686  }
8687 
8688  /*
8689  * Parenthesize the argument unless it's a simple Var or a
8690  * FieldSelect. (In particular, if it's another
8691  * SubscriptingRef, we *must* parenthesize to avoid
8692  * confusion.)
8693  */
8694  need_parens = !IsA(sbsref->refexpr, Var) &&
8695  !IsA(sbsref->refexpr, FieldSelect);
8696  if (need_parens)
8697  appendStringInfoChar(buf, '(');
8698  get_rule_expr((Node *) sbsref->refexpr, context, showimplicit);
8699  if (need_parens)
8700  appendStringInfoChar(buf, ')');
8701 
8702  /*
8703  * If there's a refassgnexpr, we want to print the node in the
8704  * format "container[subscripts] := refassgnexpr". This is
8705  * not legal SQL, so decompilation of INSERT or UPDATE
8706  * statements should always use processIndirection as part of
8707  * the statement-level syntax. We should only see this when
8708  * EXPLAIN tries to print the targetlist of a plan resulting
8709  * from such a statement.
8710  */
8711  if (sbsref->refassgnexpr)
8712  {
8713  Node *refassgnexpr;
8714 
8715  /*
8716  * Use processIndirection to print this node's subscripts
8717  * as well as any additional field selections or
8718  * subscripting in immediate descendants. It returns the
8719  * RHS expr that is actually being "assigned".
8720  */
8721  refassgnexpr = processIndirection(node, context);
8722  appendStringInfoString(buf, " := ");
8723  get_rule_expr(refassgnexpr, context, showimplicit);
8724  }
8725  else
8726  {
8727  /* Just an ordinary container fetch, so print subscripts */
8728  printSubscripts(sbsref, context);
8729  }
8730  }
8731  break;
8732 
8733  case T_FuncExpr:
8734  get_func_expr((FuncExpr *) node, context, showimplicit);
8735  break;
8736 
8737  case T_NamedArgExpr:
8738  {
8739  NamedArgExpr *na = (NamedArgExpr *) node;
8740 
8741  appendStringInfo(buf, "%s => ", quote_identifier(na->name));
8742  get_rule_expr((Node *) na->arg, context, showimplicit);
8743  }
8744  break;
8745 
8746  case T_OpExpr:
8747  get_oper_expr((OpExpr *) node, context);
8748  break;
8749 
8750  case T_DistinctExpr:
8751  {
8752  DistinctExpr *expr = (DistinctExpr *) node;
8753  List *args = expr->args;
8754  Node *arg1 = (Node *) linitial(args);
8755  Node *arg2 = (Node *) lsecond(args);
8756 
8757  if (!PRETTY_PAREN(context))
8758  appendStringInfoChar(buf, '(');
8759  get_rule_expr_paren(arg1, context, true, node);
8760  appendStringInfoString(buf, " IS DISTINCT FROM ");
8761  get_rule_expr_paren(arg2, context, true, node);
8762  if (!PRETTY_PAREN(context))
8763  appendStringInfoChar(buf, ')');
8764  }
8765  break;
8766 
8767  case T_NullIfExpr:
8768  {
8769  NullIfExpr *nullifexpr = (NullIfExpr *) node;
8770 
8771  appendStringInfoString(buf, "NULLIF(");
8772  get_rule_expr((Node *) nullifexpr->args, context, true);
8773  appendStringInfoChar(buf, ')');
8774  }
8775  break;
8776 
8777  case T_ScalarArrayOpExpr:
8778  {
8779  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
8780  List *args = expr->args;
8781  Node *arg1 = (Node *) linitial(args);
8782  Node *arg2 = (Node *) lsecond(args);
8783 
8784  if (!PRETTY_PAREN(context))
8785  appendStringInfoChar(buf, '(');
8786  get_rule_expr_paren(arg1, context, true, node);
8787  appendStringInfo(buf, " %s %s (",
8789  exprType(arg1),
8791  expr->useOr ? "ANY" : "ALL");
8792  get_rule_expr_paren(arg2, context, true, node);
8793 
8794  /*
8795  * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
8796  * a bare sub-SELECT. Since we're here, the sub-SELECT must
8797  * be meant as a scalar sub-SELECT yielding an array value to
8798  * be used in ScalarArrayOpExpr; but the grammar will
8799  * preferentially interpret such a construct as an ANY/ALL
8800  * SubLink. To prevent misparsing the output that way, insert
8801  * a dummy coercion (which will be stripped by parse analysis,
8802  * so no inefficiency is added in dump and reload). This is
8803  * indeed most likely what the user wrote to get the construct
8804  * accepted in the first place.
8805  */
8806  if (IsA(arg2, SubLink) &&
8807  ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
8808  appendStringInfo(buf, "::%s",
8810  exprTypmod(arg2)));
8811  appendStringInfoChar(buf, ')');
8812  if (!PRETTY_PAREN(context))
8813  appendStringInfoChar(buf, ')');
8814  }
8815  break;
8816 
8817  case T_BoolExpr:
8818  {
8819  BoolExpr *expr = (BoolExpr *) node;
8820  Node *first_arg = linitial(expr->args);
8821  ListCell *arg;
8822 
8823  switch (expr->boolop)
8824  {
8825  case AND_EXPR:
8826  if (!PRETTY_PAREN(context))
8827  appendStringInfoChar(buf, '(');
8828  get_rule_expr_paren(first_arg, context,
8829  false, node);
8830  for_each_from(arg, expr->args, 1)
8831  {
8832  appendStringInfoString(buf, " AND ");
8833  get_rule_expr_paren((Node *) lfirst(arg), context,
8834  false, node);
8835  }
8836  if (!PRETTY_PAREN(context))
8837  appendStringInfoChar(buf, ')');
8838  break;
8839 
8840  case OR_EXPR:
8841  if (!PRETTY_PAREN(context))
8842  appendStringInfoChar(buf, '(');
8843  get_rule_expr_paren(first_arg, context,
8844  false, node);
8845  for_each_from(arg, expr->args, 1)
8846  {
8847  appendStringInfoString(buf, " OR ");
8848  get_rule_expr_paren((Node *) lfirst(arg), context,
8849  false, node);
8850  }
8851  if (!PRETTY_PAREN(context))
8852  appendStringInfoChar(buf, ')');
8853  break;
8854 
8855  case NOT_EXPR:
8856  if (!PRETTY_PAREN(context))
8857  appendStringInfoChar(buf, '(');
8858  appendStringInfoString(buf, "NOT ");
8859  get_rule_expr_paren(first_arg, context,
8860  false, node);
8861  if (!PRETTY_PAREN(context))
8862  appendStringInfoChar(buf, ')');
8863  break;
8864 
8865  default:
8866  elog(ERROR, "unrecognized boolop: %d",
8867  (int) expr->boolop);
8868  }
8869  }
8870  break;
8871 
8872  case T_SubLink:
8873  get_sublink_expr((SubLink *) node, context);
8874  break;
8875 
8876  case T_SubPlan:
8877  {
8878  SubPlan *subplan = (SubPlan *) node;
8879 
8880  /*
8881  * We cannot see an already-planned subplan in rule deparsing,
8882  * only while EXPLAINing a query plan. We don't try to
8883  * reconstruct the original SQL, just reference the subplan
8884  * that appears elsewhere in EXPLAIN's result.
8885  */
8886  if (subplan->useHashTable)
8887  appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
8888  else
8889  appendStringInfo(buf, "(%s)", subplan->plan_name);
8890  }
8891  break;
8892 
8893  case T_AlternativeSubPlan:
8894  {
8895  AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
8896  ListCell *lc;
8897 
8898  /*
8899  * This case cannot be reached in normal usage, since no
8900  * AlternativeSubPlan can appear either in parsetrees or
8901  * finished plan trees. We keep it just in case somebody
8902  * wants to use this code to print planner data structures.
8903  */
8904  appendStringInfoString(buf, "(alternatives: ");
8905  foreach(lc, asplan->subplans)
8906  {
8907  SubPlan *splan = lfirst_node(SubPlan, lc);
8908 
8909  if (splan->useHashTable)
8910  appendStringInfo(buf, "hashed %s", splan->plan_name);
8911  else
8912  appendStringInfoString(buf, splan->plan_name);
8913  if (lnext(asplan->subplans, lc))
8914  appendStringInfoString(buf, " or ");
8915  }
8916  appendStringInfoChar(buf, ')');
8917  }
8918  break;
8919 
8920  case T_FieldSelect:
8921  {
8922  FieldSelect *fselect = (FieldSelect *) node;
8923  Node *arg = (Node *) fselect->arg;
8924  int fno = fselect->fieldnum;
8925  const char *fieldname;
8926  bool need_parens;
8927 
8928  /*
8929  * Parenthesize the argument unless it's an SubscriptingRef or
8930  * another FieldSelect. Note in particular that it would be
8931  * WRONG to not parenthesize a Var argument; simplicity is not
8932  * the issue here, having the right number of names is.
8933  */
8934  need_parens = !IsA(arg, SubscriptingRef) &&
8935  !IsA(arg, FieldSelect);
8936  if (need_parens)
8937  appendStringInfoChar(buf, '(');
8938  get_rule_expr(arg, context, true);
8939  if (need_parens)
8940  appendStringInfoChar(buf, ')');
8941 
8942  /*
8943  * Get and print the field name.
8944  */
8945  fieldname = get_name_for_var_field((Var *) arg, fno,
8946  0, context);
8947  appendStringInfo(buf, ".%s", quote_identifier(fieldname));
8948  }
8949  break;
8950 
8951  case T_FieldStore:
8952  {
8953  FieldStore *fstore = (FieldStore *) node;
8954  bool need_parens;
8955 
8956  /*
8957  * There is no good way to represent a FieldStore as real SQL,
8958  * so decompilation of INSERT or UPDATE statements should
8959  * always use processIndirection as part of the
8960  * statement-level syntax. We should only get here when
8961  * EXPLAIN tries to print the targetlist of a plan resulting
8962  * from such a statement. The plan case is even harder than
8963  * ordinary rules would be, because the planner tries to
8964  * collapse multiple assignments to the same field or subfield
8965  * into one FieldStore; so we can see a list of target fields
8966  * not just one, and the arguments could be FieldStores
8967  * themselves. We don't bother to try to print the target
8968  * field names; we just print the source arguments, with a
8969  * ROW() around them if there's more than one. This isn't
8970  * terribly complete, but it's probably good enough for
8971  * EXPLAIN's purposes; especially since anything more would be
8972  * either hopelessly confusing or an even poorer
8973  * representation of what the plan is actually doing.
8974  */
8975  need_parens = (list_length(fstore->newvals) != 1);
8976  if (need_parens)
8977  appendStringInfoString(buf, "ROW(");
8978  get_rule_expr((Node *) fstore->newvals, context, showimplicit);
8979  if (need_parens)
8980  appendStringInfoChar(buf, ')');
8981  }
8982  break;
8983 
8984  case T_RelabelType:
8985  {
8986  RelabelType *relabel = (RelabelType *) node;
8987  Node *arg = (Node *) relabel->arg;
8988 
8989  if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
8990  !showimplicit)
8991  {
8992  /* don't show the implicit cast */
8993  get_rule_expr_paren(arg, context, false, node);
8994  }
8995  else
8996  {
8997  get_coercion_expr(arg, context,
8998  relabel->resulttype,
8999  relabel->resulttypmod,
9000  node);
9001  }
9002  }
9003  break;
9004 
9005  case T_CoerceViaIO:
9006  {
9007  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
9008  Node *arg = (Node *) iocoerce->arg;
9009 
9010  if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
9011  !showimplicit)
9012  {
9013  /* don't show the implicit cast */
9014  get_rule_expr_paren(arg, context, false, node);
9015  }
9016  else
9017  {
9018  get_coercion_expr(arg, context,
9019  iocoerce->resulttype,
9020  -1,
9021  node);
9022  }
9023  }
9024  break;
9025 
9026  case T_ArrayCoerceExpr:
9027  {
9028  ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
9029  Node *arg = (Node *) acoerce->arg;
9030 
9031  if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
9032  !showimplicit)
9033  {
9034  /* don't show the implicit cast */
9035  get_rule_expr_paren(arg, context, false, node);
9036  }
9037  else
9038  {
9039  get_coercion_expr(arg, context,
9040  acoerce->resulttype,
9041  acoerce->resulttypmod,
9042  node);
9043  }
9044  }
9045  break;
9046 
9047  case T_ConvertRowtypeExpr:
9048  {
9050  Node *arg = (Node *) convert->arg;
9051 
9052  if (convert->convertformat == COERCE_IMPLICIT_CAST &&
9053  !showimplicit)
9054  {
9055  /* don't show the implicit cast */
9056  get_rule_expr_paren(arg, context, false, node);
9057  }
9058  else
9059  {
9060  get_coercion_expr(arg, context,
9061  convert->resulttype, -1,
9062  node);
9063  }
9064  }
9065  break;
9066 
9067  case T_CollateExpr:
9068  {
9069  CollateExpr *collate = (CollateExpr *) node;
9070  Node *arg = (Node *) collate->arg;
9071 
9072  if (!PRETTY_PAREN(context))
9073  appendStringInfoChar(buf, '(');
9074  get_rule_expr_paren(arg, context, showimplicit, node);
9075  appendStringInfo(buf, " COLLATE %s",
9076  generate_collation_name(collate->collOid));
9077  if (!PRETTY_PAREN(context))
9078  appendStringInfoChar(buf, ')');
9079  }
9080  break;
9081 
9082  case T_CaseExpr:
9083  {
9084  CaseExpr *caseexpr = (CaseExpr *) node;
9085  ListCell *temp;
9086 
9087  appendContextKeyword(context, "CASE",
9088  0, PRETTYINDENT_VAR, 0);
9089  if (caseexpr->arg)
9090  {
9091  appendStringInfoChar(buf, ' ');
9092  get_rule_expr((Node *) caseexpr->arg, context, true);
9093  }
9094  foreach(temp, caseexpr->args)
9095  {
9096  CaseWhen *when = (CaseWhen *) lfirst(temp);
9097  Node *w = (Node *) when->expr;
9098 
9099  if (caseexpr->arg)
9100  {
9101  /*
9102  * The parser should have produced WHEN clauses of the
9103  * form "CaseTestExpr = RHS", possibly with an
9104  * implicit coercion inserted above the CaseTestExpr.
9105  * For accurate decompilation of rules it's essential
9106  * that we show just the RHS. However in an
9107  * expression that's been through the optimizer, the
9108  * WHEN clause could be almost anything (since the
9109  * equality operator could have been expanded into an
9110  * inline function). If we don't recognize the form
9111  * of the WHEN clause, just punt and display it as-is.
9112  */
9113  if (IsA(w, OpExpr))
9114  {
9115  List *args = ((OpExpr *) w)->args;
9116 
9117  if (list_length(args) == 2 &&
9119  CaseTestExpr))
9120  w = (Node *) lsecond(args);
9121  }
9122  }
9123 
9124  if (!PRETTY_INDENT(context))
9125  appendStringInfoChar(buf, ' ');
9126  appendContextKeyword(context, "WHEN ",
9127  0, 0, 0);
9128  get_rule_expr(w, context, false);
9129  appendStringInfoString(buf, " THEN ");
9130  get_rule_expr((Node *) when->result, context, true);
9131  }
9132  if (!PRETTY_INDENT(context))
9133  appendStringInfoChar(buf, ' ');
9134  appendContextKeyword(context, "ELSE ",
9135  0, 0, 0);
9136  get_rule_expr((Node *) caseexpr->defresult, context, true);
9137  if (!PRETTY_INDENT(context))
9138  appendStringInfoChar(buf, ' ');
9139  appendContextKeyword(context, "END",
9140  -PRETTYINDENT_VAR, 0, 0);
9141  }
9142  break;
9143 
9144  case T_CaseTestExpr:
9145  {
9146  /*
9147  * Normally we should never get here, since for expressions
9148  * that can contain this node type we attempt to avoid
9149  * recursing to it. But in an optimized expression we might
9150  * be unable to avoid that (see comments for CaseExpr). If we
9151  * do see one, print it as CASE_TEST_EXPR.
9152  */
9153  appendStringInfoString(buf, "CASE_TEST_EXPR");
9154  }
9155  break;
9156 
9157  case T_ArrayExpr:
9158  {
9159  ArrayExpr *arrayexpr = (ArrayExpr *) node;
9160 
9161  appendStringInfoString(buf, "ARRAY[");
9162  get_rule_expr((Node *) arrayexpr->elements, context, true);
9163  appendStringInfoChar(buf, ']');
9164 
9165  /*
9166  * If the array isn't empty, we assume its elements are
9167  * coerced to the desired type. If it's empty, though, we
9168  * need an explicit coercion to the array type.
9169  */
9170  if (arrayexpr->elements == NIL)
9171  appendStringInfo(buf, "::%s",
9172  format_type_with_typemod(arrayexpr->array_typeid, -1));
9173  }
9174  break;
9175 
9176  case T_RowExpr:
9177  {
9178  RowExpr *rowexpr = (RowExpr *) node;
9179  TupleDesc tupdesc = NULL;
9180  ListCell *arg;
9181  int i;
9182  char *sep;
9183 
9184  /*
9185  * If it's a named type and not RECORD, we may have to skip
9186  * dropped columns and/or claim there are NULLs for added
9187  * columns.
9188  */
9189  if (rowexpr->row_typeid != RECORDOID)
9190  {
9191  tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
9192  Assert(list_length(rowexpr->args) <= tupdesc->natts);
9193  }
9194 
9195  /*
9196  * SQL99 allows "ROW" to be omitted when there is more than
9197  * one column, but for simplicity we always print it.
9198  */
9199  appendStringInfoString(buf, "ROW(");
9200  sep = "";
9201  i = 0;
9202  foreach(arg, rowexpr->args)
9203  {
9204  Node *e = (Node *) lfirst(arg);
9205 
9206  if (tupdesc == NULL ||
9207  !TupleDescAttr(tupdesc, i)->attisdropped)
9208  {
9210  /* Whole-row Vars need special treatment here */
9211  get_rule_expr_toplevel(e, context, true);
9212  sep = ", ";
9213  }
9214  i++;
9215  }
9216  if (tupdesc != NULL)
9217  {
9218  while (i < tupdesc->natts)
9219  {
9220  if (!TupleDescAttr(tupdesc, i)->attisdropped)
9221  {
9223  appendStringInfoString(buf, "NULL");
9224  sep = ", ";
9225  }
9226  i++;
9227  }
9228 
9229  ReleaseTupleDesc(tupdesc);
9230  }
9231  appendStringInfoChar(buf, ')');
9232  if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
9233  appendStringInfo(buf, "::%s",
9234  format_type_with_typemod(rowexpr->row_typeid, -1));
9235  }
9236  break;
9237 
9238  case T_RowCompareExpr:
9239  {
9240  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
9241 
9242  /*
9243  * SQL99 allows "ROW" to be omitted when there is more than
9244  * one column, but for simplicity we always print it. Within
9245  * a ROW expression, whole-row Vars need special treatment, so
9246  * use get_rule_list_toplevel.
9247  */
9248  appendStringInfoString(buf, "(ROW(");
9249  get_rule_list_toplevel(rcexpr->largs, context, true);
9250 
9251  /*
9252  * We assume that the name of the first-column operator will
9253  * do for all the rest too. This is definitely open to
9254  * failure, eg if some but not all operators were renamed
9255  * since the construct was parsed, but there seems no way to
9256  * be perfect.
9257  */
9258  appendStringInfo(buf, ") %s ROW(",
9259  generate_operator_name(linitial_oid(rcexpr->opnos),
9260  exprType(linitial(rcexpr->largs)),
9261  exprType(linitial(rcexpr->rargs))));
9262  get_rule_list_toplevel(rcexpr->rargs, context, true);
9263  appendStringInfoString(buf, "))");
9264  }
9265  break;
9266 
9267  case T_CoalesceExpr:
9268  {
9269  CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
9270 
9271  appendStringInfoString(buf, "COALESCE(");
9272  get_rule_expr((Node *) coalesceexpr->args, context, true);
9273  appendStringInfoChar(buf, ')');
9274  }
9275  break;
9276 
9277  case T_MinMaxExpr:
9278  {
9279  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
9280 
9281  switch (minmaxexpr->op)
9282  {
9283  case IS_GREATEST:
9284  appendStringInfoString(buf, "GREATEST(");
9285  break;
9286  case IS_LEAST:
9287  appendStringInfoString(buf, "LEAST(");
9288  break;
9289  }
9290  get_rule_expr((Node *) minmaxexpr->args, context, true);
9291  appendStringInfoChar(buf, ')');
9292  }
9293  break;
9294 
9295  case T_SQLValueFunction:
9296  {
9297  SQLValueFunction *svf = (SQLValueFunction *) node;
9298 
9299  /*
9300  * Note: this code knows that typmod for time, timestamp, and
9301  * timestamptz just prints as integer.
9302  */
9303  switch (svf->op)
9304  {
9305  case SVFOP_CURRENT_DATE:
9306  appendStringInfoString(buf, "CURRENT_DATE");
9307  break;
9308  case SVFOP_CURRENT_TIME:
9309  appendStringInfoString(buf, "CURRENT_TIME");
9310  break;
9311  case SVFOP_CURRENT_TIME_N:
9312  appendStringInfo(buf, "CURRENT_TIME(%d)", svf->typmod);
9313  break;
9315  appendStringInfoString(buf, "CURRENT_TIMESTAMP");
9316  break;
9318  appendStringInfo(buf, "CURRENT_TIMESTAMP(%d)",
9319  svf->typmod);
9320  break;
9321  case SVFOP_LOCALTIME:
9322  appendStringInfoString(buf, "LOCALTIME");
9323  break;
9324  case SVFOP_LOCALTIME_N:
9325  appendStringInfo(buf, "LOCALTIME(%d)", svf->typmod);
9326  break;
9327  case SVFOP_LOCALTIMESTAMP:
9328  appendStringInfoString(buf, "LOCALTIMESTAMP");
9329  break;
9331  appendStringInfo(buf, "LOCALTIMESTAMP(%d)",
9332  svf->typmod);
9333  break;
9334  case SVFOP_CURRENT_ROLE:
9335  appendStringInfoString(buf, "CURRENT_ROLE");
9336  break;
9337  case SVFOP_CURRENT_USER:
9338  appendStringInfoString(buf, "CURRENT_USER");
9339  break;
9340  case SVFOP_USER:
9341  appendStringInfoString(buf, "USER");
9342  break;
9343  case SVFOP_SESSION_USER:
9344  appendStringInfoString(buf, "SESSION_USER");
9345  break;
9346  case SVFOP_CURRENT_CATALOG:
9347  appendStringInfoString(buf, "CURRENT_CATALOG");
9348  break;
9349  case SVFOP_CURRENT_SCHEMA:
9350  appendStringInfoString(buf, "CURRENT_SCHEMA");
9351  break;
9352  }
9353  }
9354  break;
9355 
9356  case T_XmlExpr:
9357  {
9358  XmlExpr *xexpr = (XmlExpr *) node;
9359  bool needcomma = false;
9360  ListCell *arg;
9361  ListCell *narg;
9362  Const *con;
9363 
9364  switch (xexpr->op)
9365  {
9366  case IS_XMLCONCAT:
9367  appendStringInfoString(buf, "XMLCONCAT(");
9368  break;
9369  case IS_XMLELEMENT:
9370  appendStringInfoString(buf, "XMLELEMENT(");
9371  break;
9372  case IS_XMLFOREST:
9373  appendStringInfoString(buf, "XMLFOREST(");
9374  break;
9375  case IS_XMLPARSE:
9376  appendStringInfoString(buf, "XMLPARSE(");
9377  break;
9378  case IS_XMLPI:
9379  appendStringInfoString(buf, "XMLPI(");
9380  break;
9381  case IS_XMLROOT:
9382  appendStringInfoString(buf, "XMLROOT(");
9383  break;
9384  case IS_XMLSERIALIZE:
9385  appendStringInfoString(buf, "XMLSERIALIZE(");
9386  break;
9387  case IS_DOCUMENT:
9388  break;
9389  }
9390  if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
9391  {
9392  if (xexpr->xmloption == XMLOPTION_DOCUMENT)
9393  appendStringInfoString(buf, "DOCUMENT ");
9394  else
9395  appendStringInfoString(buf, "CONTENT ");
9396  }
9397  if (xexpr->name)
9398  {
9399  appendStringInfo(buf, "NAME %s",
9401  needcomma = true;
9402  }
9403  if (xexpr->named_args)
9404  {
9405  if (xexpr->op != IS_XMLFOREST)
9406  {
9407  if (needcomma)
9408  appendStringInfoString(buf, ", ");
9409  appendStringInfoString(buf, "XMLATTRIBUTES(");
9410  needcomma = false;
9411  }
9412  forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
9413  {
9414  Node *e = (Node *) lfirst(arg);
9415  char *argname = strVal(lfirst(narg));
9416 
9417  if (needcomma)
9418  appendStringInfoString(buf, ", ");
9419  get_rule_expr((Node *) e, context, true);
9420  appendStringInfo(buf, " AS %s",
9422  needcomma = true;
9423  }
9424  if (xexpr->op != IS_XMLFOREST)
9425  appendStringInfoChar(buf, ')');
9426  }
9427  if (xexpr->args)
9428  {
9429  if (needcomma)
9430  appendStringInfoString(buf, ", ");
9431  switch (xexpr->op)
9432  {
9433  case IS_XMLCONCAT:
9434  case IS_XMLELEMENT:
9435  case IS_XMLFOREST:
9436  case IS_XMLPI:
9437  case IS_XMLSERIALIZE:
9438  /* no extra decoration needed */
9439  get_rule_expr((Node *) xexpr->args, context, true);
9440  break;
9441  case IS_XMLPARSE:
9442  Assert(list_length(xexpr->args) == 2);
9443 
9444  get_rule_expr((Node *) linitial(xexpr->args),
9445  context, true);
9446 
9447  con = lsecond_node(Const, xexpr->args);
9448  Assert(!con->constisnull);
9449  if (DatumGetBool(con->constvalue))
9451  " PRESERVE WHITESPACE");
9452  else
9454  " STRIP WHITESPACE");
9455  break;
9456  case IS_XMLROOT:
9457  Assert(list_length(xexpr->args) == 3);
9458 
9459  get_rule_expr((Node *) linitial(xexpr->args),
9460  context, true);
9461 
9462  appendStringInfoString(buf, ", VERSION ");
9463  con = (Const *) lsecond(xexpr->args);
9464  if (IsA(con, Const) &&
9465  con->constisnull)
9466  appendStringInfoString(buf, "NO VALUE");
9467  else
9468  get_rule_expr((Node *) con, context, false);
9469 
9470  con = lthird_node(Const, xexpr->args);
9471  if (con->constisnull)
9472  /* suppress STANDALONE NO VALUE */ ;
9473  else
9474  {
9475  switch (DatumGetInt32(con->constvalue))
9476  {
9477  case XML_STANDALONE_YES:
9479  ", STANDALONE YES");
9480  break;
9481  case XML_STANDALONE_NO:
9483  ", STANDALONE NO");
9484  break;
9487  ", STANDALONE NO VALUE");
9488  break;
9489  default:
9490  break;
9491  }
9492  }
9493  break;
9494  case IS_DOCUMENT:
9495  get_rule_expr_paren((Node *) xexpr->args, context, false, node);
9496  break;
9497  }
9498  }
9499  if (xexpr->op == IS_XMLSERIALIZE)
9500  appendStringInfo(buf, " AS %s",
9501  format_type_with_typemod(xexpr->type,
9502  xexpr->typmod));
9503  if (xexpr->op == IS_DOCUMENT)
9504  appendStringInfoString(buf, " IS DOCUMENT");
9505  else
9506  appendStringInfoChar(buf, ')');
9507  }
9508  break;
9509 
9510  case T_NullTest:
9511  {
9512  NullTest *ntest = (NullTest *) node;
9513 
9514  if (!PRETTY_PAREN(context))
9515  appendStringInfoChar(buf, '(');
9516  get_rule_expr_paren((Node *) ntest->arg, context, true, node);
9517 
9518  /*
9519  * For scalar inputs, we prefer to print as IS [NOT] NULL,
9520  * which is shorter and traditional. If it's a rowtype input
9521  * but we're applying a scalar test, must print IS [NOT]
9522  * DISTINCT FROM NULL to be semantically correct.
9523  */
9524  if (ntest->argisrow ||
9525  !type_is_rowtype(exprType((Node *) ntest->arg)))
9526  {
9527  switch (ntest->nulltesttype)
9528  {
9529  case IS_NULL:
9530  appendStringInfoString(buf, " IS NULL");
9531  break;
9532  case IS_NOT_NULL:
9533  appendStringInfoString(buf, " IS NOT NULL");
9534  break;
9535  default:
9536  elog(ERROR, "unrecognized nulltesttype: %d",
9537  (int) ntest->nulltesttype);
9538  }
9539  }
9540  else
9541  {
9542  switch (ntest->nulltesttype)
9543  {
9544  case IS_NULL:
9545  appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL");
9546  break;
9547  case IS_NOT_NULL:
9548  appendStringInfoString(buf, " IS DISTINCT FROM NULL");
9549  break;
9550  default:
9551  elog(ERROR, "unrecognized nulltesttype: %d",
9552  (int) ntest->nulltesttype);
9553  }
9554  }
9555  if (!PRETTY_PAREN(context))
9556  appendStringInfoChar(buf, ')');
9557  }
9558  break;
9559 
9560  case T_BooleanTest:
9561  {
9562  BooleanTest *btest = (BooleanTest *) node;
9563 
9564  if (!PRETTY_PAREN(context))
9565  appendStringInfoChar(buf, '(');
9566  get_rule_expr_paren((Node *) btest->arg, context, false, node);
9567  switch (btest->booltesttype)
9568  {
9569  case IS_TRUE:
9570  appendStringInfoString(buf, " IS TRUE");
9571  break;
9572  case IS_NOT_TRUE:
9573  appendStringInfoString(buf, " IS NOT TRUE");
9574  break;
9575  case IS_FALSE:
9576  appendStringInfoString(buf, " IS FALSE");
9577  break;
9578  case IS_NOT_FALSE:
9579  appendStringInfoString(buf, " IS NOT FALSE");
9580  break;
9581  case IS_UNKNOWN:
9582  appendStringInfoString(buf, " IS UNKNOWN");
9583  break;
9584  case IS_NOT_UNKNOWN:
9585  appendStringInfoString(buf, " IS NOT UNKNOWN");
9586  break;
9587  default:
9588  elog(ERROR, "unrecognized booltesttype: %d",
9589  (int) btest->booltesttype);
9590  }
9591  if (!PRETTY_PAREN(context))
9592  appendStringInfoChar(buf, ')');
9593  }
9594  break;
9595 
9596  case T_CoerceToDomain:
9597  {
9598  CoerceToDomain *ctest = (CoerceToDomain *) node;
9599  Node *arg = (Node *) ctest->arg;
9600 
9601  if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
9602  !showimplicit)
9603  {
9604  /* don't show the implicit cast */
9605  get_rule_expr(arg, context, false);
9606  }
9607  else
9608  {
9609  get_coercion_expr(arg, context,
9610  ctest->resulttype,
9611  ctest->resulttypmod,
9612  node);
9613  }
9614  }
9615  break;
9616 
9617  case T_CoerceToDomainValue:
9618  appendStringInfoString(buf, "VALUE");
9619  break;
9620 
9621  case T_SetToDefault:
9622  appendStringInfoString(buf, "DEFAULT");
9623  break;
9624 
9625  case T_CurrentOfExpr:
9626  {
9627  CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
9628 
9629  if (cexpr->cursor_name)
9630  appendStringInfo(buf, "CURRENT OF %s",
9631  quote_identifier(cexpr->cursor_name));
9632  else
9633  appendStringInfo(buf, "CURRENT OF $%d",
9634  cexpr->cursor_param);
9635  }
9636  break;
9637 
9638  case T_NextValueExpr:
9639  {
9640  NextValueExpr *nvexpr = (NextValueExpr *) node;
9641 
9642  /*
9643  * This isn't exactly nextval(), but that seems close enough
9644  * for EXPLAIN's purposes.
9645  */
9646  appendStringInfoString(buf, "nextval(");
9648  generate_relation_name(nvexpr->seqid,
9649  NIL));
9650  appendStringInfoChar(buf, ')');
9651  }
9652  break;
9653 
9654  case T_InferenceElem:
9655  {
9656  InferenceElem *iexpr = (InferenceElem *) node;
9657  bool save_varprefix;
9658  bool need_parens;
9659 
9660  /*
9661  * InferenceElem can only refer to target relation, so a
9662  * prefix is not useful, and indeed would cause parse errors.
9663  */
9664  save_varprefix = context->varprefix;
9665  context->varprefix = false;
9666 
9667  /*
9668  * Parenthesize the element unless it's a simple Var or a bare
9669  * function call. Follows pg_get_indexdef_worker().
9670  */
9671  need_parens = !IsA(iexpr->expr, Var);
9672  if (IsA(iexpr->expr, FuncExpr) &&
9673  ((FuncExpr *) iexpr->expr)->funcformat ==
9675  need_parens = false;
9676 
9677  if (need_parens)
9678  appendStringInfoChar(buf, '(');
9679  get_rule_expr((Node *) iexpr->expr,
9680  context, false);
9681  if (need_parens)
9682  appendStringInfoChar(buf, ')');
9683 
9684  context->varprefix = save_varprefix;
9685 
9686  if (iexpr->infercollid)
9687  appendStringInfo(buf, " COLLATE %s",
9689 
9690  /* Add the operator class name, if not default */
9691  if (iexpr->inferopclass)
9692  {
9693  Oid inferopclass = iexpr->inferopclass;
9694  Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass);
9695 
9696  get_opclass_name(inferopclass, inferopcinputtype, buf);
9697  }
9698  }
9699  break;
9700 
9701  case T_PartitionBoundSpec:
9702  {
9703  PartitionBoundSpec *spec = (PartitionBoundSpec *) node;
9704  ListCell *cell;
9705  char *sep;
9706 
9707  if (spec->is_default)
9708  {
9709  appendStringInfoString(buf, "DEFAULT");
9710  break;
9711  }
9712 
9713  switch (spec->strategy)
9714  {
9716  Assert(spec->modulus > 0 && spec->remainder >= 0);
9717  Assert(spec->modulus > spec->remainder);
9718 
9719  appendStringInfoString(buf, "FOR VALUES");
9720  appendStringInfo(buf, " WITH (modulus %d, remainder %d)",
9721  spec->modulus, spec->remainder);
9722  break;
9723 
9725  Assert(spec->listdatums != NIL);
9726 
9727  appendStringInfoString(buf, "FOR VALUES IN (");
9728  sep = "";
9729  foreach(cell, spec->listdatums)
9730  {
9731  Const *val = lfirst_node(Const, cell);
9732 
9734  get_const_expr(val, context, -1);
9735  sep = ", ";
9736  }
9737 
9738  appendStringInfoChar(buf, ')');
9739  break;
9740 
9742  Assert(spec->lowerdatums != NIL &&
9743  spec->upperdatums != NIL &&
9744  list_length(spec->lowerdatums) ==
9745  list_length(spec->upperdatums));
9746 
9747  appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
9750  break;
9751 
9752  default:
9753  elog(ERROR, "unrecognized partition strategy: %d",
9754  (int) spec->strategy);
9755  break;
9756  }
9757  }
9758  break;
9759 
9760  case T_JsonValueExpr:
9761  {
9762  JsonValueExpr *jve = (JsonValueExpr *) node;
9763 
9764  get_rule_expr((Node *) jve->raw_expr, context, false);
9765  get_json_format(jve->format, context->buf);
9766  }
9767  break;
9768 
9769  case T_JsonConstructorExpr:
9770  get_json_constructor((JsonConstructorExpr *) node, context, false);
9771  break;
9772 
9773  case T_JsonIsPredicate:
9774  {
9775  JsonIsPredicate *pred = (JsonIsPredicate *) node;
9776 
9777  if (!PRETTY_PAREN(context))
9778  appendStringInfoChar(context->buf, '(');
9779 
9780  get_rule_expr_paren(pred->expr, context, true, node);
9781 
9782  appendStringInfoString(context->buf, " IS JSON");
9783 
9784  /* TODO: handle FORMAT clause */
9785 
9786  switch (pred->item_type)
9787  {
9788  case JS_TYPE_SCALAR:
9789  appendStringInfoString(context->buf, " SCALAR");
9790  break;
9791  case JS_TYPE_ARRAY:
9792  appendStringInfoString(context->buf, " ARRAY");
9793  break;
9794  case JS_TYPE_OBJECT:
9795  appendStringInfoString(context->buf, " OBJECT");
9796  break;
9797  default:
9798  break;
9799  }
9800 
9801  if (pred->unique_keys)
9802  appendStringInfoString(context->buf, " WITH UNIQUE KEYS");
9803 
9804  if (!PRETTY_PAREN(context))
9805  appendStringInfoChar(context->buf, ')');
9806  }
9807  break;
9808 
9809  case T_List:
9810  {
9811  char *sep;
9812  ListCell *l;
9813 
9814  sep = "";
9815  foreach(l, (List *) node)
9816  {
9818  get_rule_expr((Node *) lfirst(l), context, showimplicit);
9819  sep = ", ";
9820  }
9821  }
9822  break;
9823 
9824  case T_TableFunc:
9825  get_tablefunc((TableFunc *) node, context, showimplicit);
9826  break;
9827 
9828  default:
9829  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
9830  break;
9831  }
9832 }
9833 
9834 /*
9835  * get_rule_expr_toplevel - Parse back a toplevel expression
9836  *
9837  * Same as get_rule_expr(), except that if the expr is just a Var, we pass
9838  * istoplevel = true not false to get_variable(). This causes whole-row Vars
9839  * to get printed with decoration that will prevent expansion of "*".
9840  * We need to use this in contexts such as ROW() and VALUES(), where the
9841  * parser would expand "foo.*" appearing at top level. (In principle we'd
9842  * use this in get_target_list() too, but that has additional worries about
9843  * whether to print AS, so it needs to invoke get_variable() directly anyway.)
9844  */
9845 static void
9847  bool showimplicit)
9848 {
9849  if (node && IsA(node, Var))
9850  (void) get_variable((Var *) node, 0, true, context);
9851  else
9852  get_rule_expr(node, context, showimplicit);
9853 }
9854 
9855 /*
9856  * get_rule_list_toplevel - Parse back a list of toplevel expressions
9857  *
9858  * Apply get_rule_expr_toplevel() to each element of a List.
9859  *
9860  * This adds commas between the expressions, but caller is responsible
9861  * for printing surrounding decoration.
9862  */
9863 static void
9865  bool showimplicit)
9866 {
9867  const char *sep;
9868  ListCell *lc;
9869 
9870  sep = "";
9871  foreach(lc, lst)
9872  {
9873  Node *e = (Node *) lfirst(lc);
9874 
9875  appendStringInfoString(context->buf, sep);
9876  get_rule_expr_toplevel(e, context, showimplicit);
9877  sep = ", ";
9878  }
9879 }
9880 
9881 /*
9882  * get_rule_expr_funccall - Parse back a function-call expression
9883  *
9884  * Same as get_rule_expr(), except that we guarantee that the output will
9885  * look like a function call, or like one of the things the grammar treats as
9886  * equivalent to a function call (see the func_expr_windowless production).
9887  * This is needed in places where the grammar uses func_expr_windowless and
9888  * you can't substitute a parenthesized a_expr. If what we have isn't going
9889  * to look like a function call, wrap it in a dummy CAST() expression, which
9890  * will satisfy the grammar --- and, indeed, is likely what the user wrote to
9891  * produce such a thing.
9892  */
9893 static void
9895  bool showimplicit)
9896 {
9897  if (looks_like_function(node))
9898  get_rule_expr(node, context, showimplicit);
9899  else
9900  {
9901  StringInfo buf = context->buf;
9902 
9903  appendStringInfoString(buf, "CAST(");
9904  /* no point in showing any top-level implicit cast */
9905  get_rule_expr(node, context, false);
9906  appendStringInfo(buf, " AS %s)",
9908  exprTypmod(node)));
9909  }
9910 }
9911 
9912 /*
9913  * Helper function to identify node types that satisfy func_expr_windowless.
9914  * If in doubt, "false" is always a safe answer.
9915  */
9916 static bool
9918 {
9919  if (node == NULL)
9920  return false; /* probably shouldn't happen */
9921  switch (nodeTag(node))
9922  {
9923  case T_FuncExpr:
9924  /* OK, unless it's going to deparse as a cast */
9925  return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL ||
9926  ((FuncExpr *) node)->funcformat == COERCE_SQL_SYNTAX);
9927  case T_NullIfExpr:
9928  case T_CoalesceExpr:
9929  case T_MinMaxExpr:
9930  case T_SQLValueFunction:
9931  case T_XmlExpr:
9932  /* these are all accepted by func_expr_common_subexpr */
9933  return true;
9934  default:
9935  break;
9936  }
9937  return false;
9938 }
9939 
9940 
9941 /*
9942  * get_oper_expr - Parse back an OpExpr node
9943  */
9944 static void
9946 {
9947  StringInfo buf = context->buf;
9948  Oid opno = expr->opno;
9949  List *args = expr->args;
9950 
9951  if (!PRETTY_PAREN(context))
9952  appendStringInfoChar(buf, '(');
9953  if (list_length(args) == 2)
9954  {
9955  /* binary operator */
9956  Node *arg1 = (Node *) linitial(args);
9957  Node *arg2 = (Node *) lsecond(args);
9958 
9959  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9960  appendStringInfo(buf, " %s ",
9962  exprType(arg1),
9963  exprType(arg2)));
9964  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9965  }
9966  else
9967  {
9968  /* prefix operator */
9969  Node *arg = (Node *) linitial(args);
9970 
9971  appendStringInfo(buf, "%s ",
9973  InvalidOid,
9974  exprType(arg)));
9975  get_rule_expr_paren(arg, context, true, (Node *) expr);
9976  }
9977  if (!PRETTY_PAREN(context))
9978  appendStringInfoChar(buf, ')');
9979 }
9980 
9981 /*
9982  * get_func_expr - Parse back a FuncExpr node
9983  */
9984 static void
9986  bool showimplicit)
9987 {
9988  StringInfo buf = context->buf;
9989  Oid funcoid = expr->funcid;
9990  Oid argtypes[FUNC_MAX_ARGS];
9991  int nargs;
9992  List *argnames;
9993  bool use_variadic;
9994  ListCell *l;
9995 
9996  /*
9997  * If the function call came from an implicit coercion, then just show the
9998  * first argument --- unless caller wants to see implicit coercions.
9999  */
10000  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
10001  {
10002  get_rule_expr_paren((Node *) linitial(expr->args), context,
10003  false, (Node *) expr);
10004  return;
10005  }
10006 
10007  /*
10008  * If the function call came from a cast, then show the first argument
10009  * plus an explicit cast operation.
10010  */
10011  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
10012  expr->funcformat == COERCE_IMPLICIT_CAST)
10013  {
10014  Node *arg = linitial(expr->args);
10015  Oid rettype = expr->funcresulttype;
10016  int32 coercedTypmod;
10017 
10018  /* Get the typmod if this is a length-coercion function */
10019  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
10020 
10021  get_coercion_expr(arg, context,
10022  rettype, coercedTypmod,
10023  (Node *) expr);
10024 
10025  return;
10026  }
10027 
10028  /*
10029  * If the function was called using one of the SQL spec's random special
10030  * syntaxes, try to reproduce that. If we don't recognize the function,
10031  * fall through.
10032  */
10033  if (expr->funcformat == COERCE_SQL_SYNTAX)
10034  {
10035  if (get_func_sql_syntax(expr, context))
10036  return;
10037  }
10038 
10039  /*
10040  * Normal function: display as proname(args). First we need to extract
10041  * the argument datatypes.
10042  */
10043  if (list_length(expr->args) > FUNC_MAX_ARGS)
10044  ereport(ERROR,
10045  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
10046  errmsg("too many arguments")));
10047  nargs = 0;
10048  argnames = NIL;
10049  foreach(l, expr->args)
10050  {
10051  Node *arg = (Node *) lfirst(l);
10052 
10053  if (IsA(arg, NamedArgExpr))
10054  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
10055  argtypes[nargs] = exprType(arg);
10056  nargs++;
10057  }
10058 
10059  appendStringInfo(buf, "%s(",
10060  generate_function_name(funcoid, nargs,
10061  argnames, argtypes,
10062  expr->funcvariadic,
10063  &use_variadic,
10064  context->special_exprkind));
10065  nargs = 0;
10066  foreach(l, expr->args)
10067  {
10068  if (nargs++ > 0)
10069  appendStringInfoString(buf, ", ");
10070  if (use_variadic && lnext(expr->args, l) == NULL)
10071  appendStringInfoString(buf, "VARIADIC ");
10072  get_rule_expr((Node *) lfirst(l), context, true);
10073  }
10074  appendStringInfoChar(buf, ')');
10075 }
10076 
10077 /*
10078  * get_agg_expr - Parse back an Aggref node
10079  */
10080 static void
10082  Aggref *original_aggref)
10083 {
10084  get_agg_expr_helper(aggref, context, original_aggref, NULL, NULL,
10085  false);
10086 }
10087 
10088 /*
10089  * get_agg_expr_helper - subroutine for get_agg_expr and
10090  * get_json_agg_constructor
10091  */
10092 static void
10094  Aggref *original_aggref, const char *funcname,
10095  const char *options, bool is_json_objectagg)
10096 {
10097  StringInfo buf = context->buf;
10098  Oid argtypes[FUNC_MAX_ARGS];
10099  int nargs;
10100  bool use_variadic = false;
10101 
10102  /*
10103  * For a combining aggregate, we look up and deparse the corresponding
10104  * partial aggregate instead. This is necessary because our input
10105  * argument list has been replaced; the new argument list always has just
10106  * one element, which will point to a partial Aggref that supplies us with
10107  * transition states to combine.
10108  */
10109  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
10110  {
10111  TargetEntry *tle;
10112 
10113  Assert(list_length(aggref->args) == 1);
10114  tle = linitial_node(TargetEntry, aggref->args);
10115  resolve_special_varno((Node *) tle->expr, context,
10116  get_agg_combine_expr, original_aggref);
10117  return;
10118  }
10119 
10120  /*
10121  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
10122  * to avoid printing this when recursing from the code just above.
10123  */
10124  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
10125  appendStringInfoString(buf, "PARTIAL ");
10126 
10127  /* Extract the argument types as seen by the parser */
10128  nargs = get_aggregate_argtypes(aggref, argtypes);
10129 
10130  if (!funcname)
10131  funcname = generate_function_name(aggref->aggfnoid, nargs, NIL,
10132  argtypes, aggref->aggvariadic,
10133  &use_variadic,
10134  context->special_exprkind);
10135 
10136  /* Print the aggregate name, schema-qualified if needed */
10137  appendStringInfo(buf, "%s(%s", funcname,
10138  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
10139 
10140  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
10141  {
10142  /*
10143  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
10144  * worry about inserting VARIADIC. So we can just dump the direct
10145  * args as-is.
10146  */
10147  Assert(!aggref->aggvariadic);
10148  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
10149  Assert(aggref->aggorder != NIL);
10150  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
10151  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
10152  }
10153  else
10154  {
10155  /* aggstar can be set only in zero-argument aggregates */
10156  if (aggref->aggstar)
10157  appendStringInfoChar(buf, '*');
10158  else
10159  {
10160  ListCell *l;
10161  int i;
10162 
10163  i = 0;
10164  foreach(l, aggref->args)
10165  {
10166  TargetEntry *tle = (TargetEntry *) lfirst(l);
10167  Node *arg = (Node *) tle->expr;
10168 
10169  Assert(!IsA(arg, NamedArgExpr));
10170  if (tle->resjunk)
10171  continue;
10172  if (i++ > 0)
10173  {
10174  if (is_json_objectagg)
10175  {
10176  /*
10177  * the ABSENT ON NULL and WITH UNIQUE args are printed
10178  * separately, so ignore them here
10179  */
10180  if (i > 2)
10181  break;
10182 
10183  appendStringInfoString(buf, " : ");
10184  }
10185  else
10186  appendStringInfoString(buf, ", ");
10187  }
10188  if (use_variadic && i == nargs)
10189  appendStringInfoString(buf, "VARIADIC ");
10190  get_rule_expr(arg, context, true);
10191  }
10192  }
10193 
10194  if (aggref->aggorder != NIL)
10195  {
10196  appendStringInfoString(buf, " ORDER BY ");
10197  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
10198  }
10199  }
10200 
10201  if (options)
10203 
10204  if (aggref->aggfilter != NULL)
10205  {
10206  appendStringInfoString(buf, ") FILTER (WHERE ");
10207  get_rule_expr((Node *) aggref->aggfilter, context, false);
10208  }
10209 
10210  appendStringInfoChar(buf, ')');
10211 }
10212 
10213 /*
10214  * This is a helper function for get_agg_expr(). It's used when we deparse
10215  * a combining Aggref; resolve_special_varno locates the corresponding partial
10216  * Aggref and then calls this.
10217  */
10218 static void
10219 get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
10220 {
10221  Aggref *aggref;
10222  Aggref *original_aggref = callback_arg;
10223 
10224  if (!IsA(node, Aggref))
10225  elog(ERROR, "combining Aggref does not point to an Aggref");
10226 
10227  aggref = (Aggref *) node;
10228  get_agg_expr(aggref, context, original_aggref);
10229 }
10230 
10231 /*
10232  * get_windowfunc_expr - Parse back a WindowFunc node
10233  */
10234 static void
10236 {
10237  get_windowfunc_expr_helper(wfunc, context, NULL, NULL, false);
10238 }
10239 
10240 
10241 /*
10242  * get_windowfunc_expr_helper - subroutine for get_windowfunc_expr and
10243  * get_json_agg_constructor
10244  */
10245 static void
10247  const char *funcname, const char *options,
10248  bool is_json_objectagg)
10249 {
10250  StringInfo buf = context->buf;
10251  Oid argtypes[FUNC_MAX_ARGS];
10252  int nargs;
10253  List *argnames;
10254  ListCell *l;
10255 
10256  if (list_length(wfunc->args) > FUNC_MAX_ARGS)
10257  ereport(ERROR,
10258  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
10259  errmsg("too many arguments")));
10260  nargs = 0;
10261  argnames = NIL;
10262  foreach(l, wfunc->args)
10263  {
10264  Node *arg = (Node *) lfirst(l);
10265 
10266  if (IsA(arg, NamedArgExpr))
10267  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
10268  argtypes[nargs] = exprType(arg);
10269  nargs++;
10270  }
10271 
10272  if (!funcname)
10273  funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
10274  argtypes, false, NULL,
10275  context->special_exprkind);
10276 
10277  appendStringInfo(buf, "%s(", funcname);
10278 
10279  /* winstar can be set only in zero-argument aggregates */
10280  if (wfunc->winstar)
10281  appendStringInfoChar(buf, '*');
10282  else
10283  {
10284  if (is_json_objectagg)
10285  {
10286  get_rule_expr((Node *) linitial(wfunc->args), context, false);
10287  appendStringInfoString(buf, " : ");
10288  get_rule_expr((Node *) lsecond(wfunc->args), context, false);
10289  }
10290  else
10291  get_rule_expr((Node *) wfunc->args, context, true);
10292  }
10293 
10294  if (options)
10296 
10297  if (wfunc->aggfilter != NULL)
10298  {
10299  appendStringInfoString(buf, ") FILTER (WHERE ");
10300  get_rule_expr((Node *) wfunc->aggfilter, context, false);
10301  }
10302 
10303  appendStringInfoString(buf, ") OVER ");
10304 
10305  foreach(l, context->windowClause)
10306  {
10307  WindowClause *wc = (WindowClause *) lfirst(l);
10308 
10309  if (wc->winref == wfunc->winref)
10310  {
10311  if (wc->name)
10313  else
10314  get_rule_windowspec(wc, context->windowTList, context);
10315  break;
10316  }
10317  }
10318  if (l == NULL)
10319  {
10320  if (context->windowClause)
10321  elog(ERROR, "could not find window clause for winref %u",
10322  wfunc->winref);
10323 
10324  /*
10325  * In EXPLAIN, we don't have window context information available, so
10326  * we have to settle for this:
10327  */
10328  appendStringInfoString(buf, "(?)");
10329  }
10330 }
10331 
10332 /*
10333  * get_func_sql_syntax - Parse back a SQL-syntax function call
10334  *
10335  * Returns true if we successfully deparsed, false if we did not
10336  * recognize the function.
10337  */
10338 static bool
10340 {
10341  StringInfo buf = context->buf;
10342  Oid funcoid = expr->funcid;
10343 
10344  switch (funcoid)
10345  {
10346  case F_TIMEZONE_INTERVAL_TIMESTAMP:
10347  case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
10348  case F_TIMEZONE_INTERVAL_TIMETZ:
10349  case F_TIMEZONE_TEXT_TIMESTAMP:
10350  case F_TIMEZONE_TEXT_TIMESTAMPTZ:
10351  case F_TIMEZONE_TEXT_TIMETZ:
10352  /* AT TIME ZONE ... note reversed argument order */
10353  appendStringInfoChar(buf, '(');
10354  get_rule_expr_paren((Node *) lsecond(expr->args), context, false,
10355  (Node *) expr);
10356  appendStringInfoString(buf, " AT TIME ZONE ");
10357  get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10358  (Node *) expr);
10359  appendStringInfoChar(buf, ')');
10360  return true;
10361 
10362  case F_TIMEZONE_TIMESTAMP:
10363  case F_TIMEZONE_TIMESTAMPTZ:
10364  case F_TIMEZONE_TIMETZ:
10365  /* AT LOCAL */
10366  appendStringInfoChar(buf, '(');
10367  get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10368  (Node *) expr);
10369  appendStringInfoString(buf, " AT LOCAL)");
10370  return true;
10371 
10372  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
10373  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
10374  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
10375  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
10376  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
10377  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
10378  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
10379  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
10380  case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
10381  case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
10382  case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
10383  case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
10384  case F_OVERLAPS_TIME_TIME_TIME_TIME:
10385  /* (x1, x2) OVERLAPS (y1, y2) */
10386  appendStringInfoString(buf, "((");
10387  get_rule_expr((Node *) linitial(expr->args), context, false);
10388  appendStringInfoString(buf, ", ");
10389  get_rule_expr((Node *) lsecond(expr->args), context, false);
10390  appendStringInfoString(buf, ") OVERLAPS (");
10391  get_rule_expr((Node *) lthird(expr->args), context, false);
10392  appendStringInfoString(buf, ", ");
10393  get_rule_expr((Node *) lfourth(expr->args), context, false);
10394  appendStringInfoString(buf, "))");
10395  return true;
10396 
10397  case F_EXTRACT_TEXT_DATE:
10398  case F_EXTRACT_TEXT_TIME:
10399  case F_EXTRACT_TEXT_TIMETZ:
10400  case F_EXTRACT_TEXT_TIMESTAMP:
10401  case F_EXTRACT_TEXT_TIMESTAMPTZ:
10402  case F_EXTRACT_TEXT_INTERVAL:
10403  /* EXTRACT (x FROM y) */
10404  appendStringInfoString(buf, "EXTRACT(");
10405  {
10406  Const *con = (Const *) linitial(expr->args);
10407 
10408  Assert(IsA(con, Const) &&
10409  con->consttype == TEXTOID &&
10410  !con->constisnull);
10411  appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
10412  }
10413  appendStringInfoString(buf, " FROM ");
10414  get_rule_expr((Node *) lsecond(expr->args), context, false);
10415  appendStringInfoChar(buf, ')');
10416  return true;
10417 
10418  case F_IS_NORMALIZED:
10419  /* IS xxx NORMALIZED */
10420  appendStringInfoChar(buf, '(');
10421  get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10422  (Node *) expr);
10423  appendStringInfoString(buf, " IS");
10424  if (list_length(expr->args) == 2)
10425  {
10426  Const *con = (Const *) lsecond(expr->args);
10427 
10428  Assert(IsA(con, Const) &&
10429  con->consttype == TEXTOID &&
10430  !con->constisnull);
10431  appendStringInfo(buf, " %s",
10432  TextDatumGetCString(con->constvalue));
10433  }
10434  appendStringInfoString(buf, " NORMALIZED)");
10435  return true;
10436 
10437  case F_PG_COLLATION_FOR:
10438  /* COLLATION FOR */
10439  appendStringInfoString(buf, "COLLATION FOR (");
10440  get_rule_expr((Node *) linitial(expr->args), context, false);
10441  appendStringInfoChar(buf, ')');
10442  return true;
10443 
10444  case F_NORMALIZE:
10445  /* NORMALIZE() */
10446  appendStringInfoString(buf, "NORMALIZE(");
10447  get_rule_expr((Node *) linitial(expr->args), context, false);
10448  if (list_length(expr->args) == 2)
10449  {
10450  Const *con = (Const *) lsecond(expr->args);
10451 
10452  Assert(IsA(con, Const) &&
10453  con->consttype == TEXTOID &&
10454  !con->constisnull);
10455  appendStringInfo(buf, ", %s",
10456  TextDatumGetCString(con->constvalue));
10457  }
10458  appendStringInfoChar(buf, ')');
10459  return true;
10460 
10461  case F_OVERLAY_BIT_BIT_INT4:
10462  case F_OVERLAY_BIT_BIT_INT4_INT4:
10463  case F_OVERLAY_BYTEA_BYTEA_INT4:
10464  case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
10465  case F_OVERLAY_TEXT_TEXT_INT4:
10466  case F_OVERLAY_TEXT_TEXT_INT4_INT4:
10467  /* OVERLAY() */
10468  appendStringInfoString(buf, "OVERLAY(");
10469  get_rule_expr((Node *) linitial(expr->args), context, false);
10470  appendStringInfoString(buf, " PLACING ");
10471  get_rule_expr((Node *) lsecond(expr->args), context, false);
10472  appendStringInfoString(buf, " FROM ");
10473  get_rule_expr((Node *) lthird(expr->args), context, false);
10474  if (list_length(expr->args) == 4)
10475  {
10476  appendStringInfoString(buf, " FOR ");
10477  get_rule_expr((Node *) lfourth(expr->args), context, false);
10478  }
10479  appendStringInfoChar(buf, ')');
10480  return true;
10481 
10482  case F_POSITION_BIT_BIT:
10483  case F_POSITION_BYTEA_BYTEA:
10484  case F_POSITION_TEXT_TEXT:
10485  /* POSITION() ... extra parens since args are b_expr not a_expr */
10486  appendStringInfoString(buf, "POSITION((");
10487  get_rule_expr((Node *) lsecond(expr->args), context, false);
10488  appendStringInfoString(buf, ") IN (");
10489  get_rule_expr((Node *) linitial(expr->args), context, false);
10490  appendStringInfoString(buf, "))");
10491  return true;
10492 
10493  case F_SUBSTRING_BIT_INT4:
10494  case F_SUBSTRING_BIT_INT4_INT4:
10495  case F_SUBSTRING_BYTEA_INT4:
10496  case F_SUBSTRING_BYTEA_INT4_INT4:
10497  case F_SUBSTRING_TEXT_INT4:
10498  case F_SUBSTRING_TEXT_INT4_INT4:
10499  /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
10500  appendStringInfoString(buf, "SUBSTRING(");
10501  get_rule_expr((Node *) linitial(expr->args), context, false);
10502  appendStringInfoString(buf, " FROM ");
10503  get_rule_expr((Node *) lsecond(expr->args), context, false);
10504  if (list_length(expr->args) == 3)
10505  {
10506  appendStringInfoString(buf, " FOR ");
10507  get_rule_expr((Node *) lthird(expr->args), context, false);
10508  }
10509  appendStringInfoChar(buf, ')');
10510  return true;
10511 
10512  case F_SUBSTRING_TEXT_TEXT_TEXT:
10513  /* SUBSTRING SIMILAR/ESCAPE */
10514  appendStringInfoString(buf, "SUBSTRING(");
10515  get_rule_expr((Node *) linitial(expr->args), context, false);
10516  appendStringInfoString(buf, " SIMILAR ");
10517  get_rule_expr((Node *) lsecond(expr->args), context, false);
10518  appendStringInfoString(buf, " ESCAPE ");
10519  get_rule_expr((Node *) lthird(expr->args), context, false);
10520  appendStringInfoChar(buf, ')');
10521  return true;
10522 
10523  case F_BTRIM_BYTEA_BYTEA:
10524  case F_BTRIM_TEXT:
10525  case F_BTRIM_TEXT_TEXT:
10526  /* TRIM() */
10527  appendStringInfoString(buf, "TRIM(BOTH");
10528  if (list_length(expr->args) == 2)
10529  {
10530  appendStringInfoChar(buf, ' ');
10531  get_rule_expr((Node *) lsecond(expr->args), context, false);
10532  }
10533  appendStringInfoString(buf, " FROM ");
10534  get_rule_expr((Node *) linitial(expr->args), context, false);
10535  appendStringInfoChar(buf, ')');
10536  return true;
10537 
10538  case F_LTRIM_BYTEA_BYTEA:
10539  case F_LTRIM_TEXT:
10540  case F_LTRIM_TEXT_TEXT:
10541  /* TRIM() */
10542  appendStringInfoString(buf, "TRIM(LEADING");
10543  if (list_length(expr->args) == 2)
10544  {
10545  appendStringInfoChar(buf, ' ');
10546  get_rule_expr((Node *) lsecond(expr->args), context, false);
10547  }
10548  appendStringInfoString(buf, " FROM ");
10549  get_rule_expr((Node *) linitial(expr->args), context, false);
10550  appendStringInfoChar(buf, ')');
10551  return true;
10552 
10553  case F_RTRIM_BYTEA_BYTEA:
10554  case F_RTRIM_TEXT:
10555  case F_RTRIM_TEXT_TEXT:
10556  /* TRIM() */
10557  appendStringInfoString(buf, "TRIM(TRAILING");
10558  if (list_length(expr->args) == 2)
10559  {
10560  appendStringInfoChar(buf, ' ');
10561  get_rule_expr((Node *) lsecond(expr->args), context, false);
10562  }
10563  appendStringInfoString(buf, " FROM ");
10564  get_rule_expr((Node *) linitial(expr->args), context, false);
10565  appendStringInfoChar(buf, ')');
10566  return true;
10567 
10568  case F_SYSTEM_USER:
10569  appendStringInfoString(buf, "SYSTEM_USER");
10570  return true;
10571 
10572  case F_XMLEXISTS:
10573  /* XMLEXISTS ... extra parens because args are c_expr */
10574  appendStringInfoString(buf, "XMLEXISTS((");
10575  get_rule_expr((Node *) linitial(expr->args), context, false);
10576  appendStringInfoString(buf, ") PASSING (");
10577  get_rule_expr((Node *) lsecond(expr->args), context, false);
10578  appendStringInfoString(buf, "))");
10579  return true;
10580  }
10581  return false;
10582 }
10583 
10584 /* ----------
10585  * get_coercion_expr
10586  *
10587  * Make a string representation of a value coerced to a specific type
10588  * ----------
10589  */
10590 static void
10592  Oid resulttype, int32 resulttypmod,
10593  Node *parentNode)
10594 {
10595  StringInfo buf = context->buf;
10596 
10597  /*
10598  * Since parse_coerce.c doesn't immediately collapse application of
10599  * length-coercion functions to constants, what we'll typically see in
10600  * such cases is a Const with typmod -1 and a length-coercion function
10601  * right above it. Avoid generating redundant output. However, beware of
10602  * suppressing casts when the user actually wrote something like
10603  * 'foo'::text::char(3).
10604  *
10605  * Note: it might seem that we are missing the possibility of needing to
10606  * print a COLLATE clause for such a Const. However, a Const could only
10607  * have nondefault collation in a post-constant-folding tree, in which the
10608  * length coercion would have been folded too. See also the special
10609  * handling of CollateExpr in coerce_to_target_type(): any collation
10610  * marking will be above the coercion node, not below it.
10611  */
10612  if (arg && IsA(arg, Const) &&
10613  ((Const *) arg)->consttype == resulttype &&
10614  ((Const *) arg)->consttypmod == -1)
10615  {
10616  /* Show the constant without normal ::typename decoration */
10617  get_const_expr((Const *) arg, context, -1);
10618  }
10619  else
10620  {
10621  if (!PRETTY_PAREN(context))
10622  appendStringInfoChar(buf, '(');
10623  get_rule_expr_paren(arg, context, false, parentNode);
10624  if (!PRETTY_PAREN(context))
10625  appendStringInfoChar(buf, ')');
10626  }
10627 
10628  /*
10629  * Never emit resulttype(arg) functional notation. A pg_proc entry could
10630  * take precedence, and a resulttype in pg_temp would require schema
10631  * qualification that format_type_with_typemod() would usually omit. We've
10632  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
10633  * would work fine.
10634  */
10635  appendStringInfo(buf, "::%s",
10636  format_type_with_typemod(resulttype, resulttypmod));
10637 }
10638 
10639 /* ----------
10640  * get_const_expr
10641  *
10642  * Make a string representation of a Const
10643  *
10644  * showtype can be -1 to never show "::typename" decoration, or +1 to always
10645  * show it, or 0 to show it only if the constant wouldn't be assumed to be
10646  * the right type by default.
10647  *
10648  * If the Const's collation isn't default for its type, show that too.
10649  * We mustn't do this when showtype is -1 (since that means the caller will
10650  * print "::typename", and we can't put a COLLATE clause in between). It's
10651  * caller's responsibility that collation isn't missed in such cases.
10652  * ----------
10653  */
10654 static void
10655 get_const_expr(Const *constval, deparse_context *context, int showtype)
10656 {
10657  StringInfo buf = context->buf;
10658  Oid typoutput;
10659  bool typIsVarlena;
10660  char *extval;
10661  bool needlabel = false;
10662 
10663  if (constval->constisnull)
10664  {
10665  /*
10666  * Always label the type of a NULL constant to prevent misdecisions
10667  * about type when reparsing.
10668  */
10669  appendStringInfoString(buf, "NULL");
10670  if (showtype >= 0)
10671  {
10672  appendStringInfo(buf, "::%s",
10674  constval->consttypmod));
10675  get_const_collation(constval, context);
10676  }
10677  return;
10678  }
10679 
10680  getTypeOutputInfo(constval->consttype,
10681  &typoutput, &typIsVarlena);
10682 
10683  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
10684 
10685  switch (constval->consttype)
10686  {
10687  case INT4OID:
10688 
10689  /*
10690  * INT4 can be printed without any decoration, unless it is
10691  * negative; in that case print it as '-nnn'::integer to ensure
10692  * that the output will re-parse as a constant, not as a constant
10693  * plus operator. In most cases we could get away with printing
10694  * (-nnn) instead, because of the way that gram.y handles negative
10695  * literals; but that doesn't work for INT_MIN, and it doesn't
10696  * seem that much prettier anyway.
10697  */
10698  if (extval[0] != '-')
10699  appendStringInfoString(buf, extval);
10700  else
10701  {
10702  appendStringInfo(buf, "'%s'", extval);
10703  needlabel = true; /* we must attach a cast */
10704  }
10705  break;
10706 
10707  case NUMERICOID:
10708 
10709  /*
10710  * NUMERIC can be printed without quotes if it looks like a float
10711  * constant (not an integer, and not Infinity or NaN) and doesn't
10712  * have a leading sign (for the same reason as for INT4).
10713  */
10714  if (isdigit((unsigned char) extval[0]) &&
10715  strcspn(extval, "eE.") != strlen(extval))
10716  {
10717  appendStringInfoString(buf, extval);
10718  }
10719  else
10720  {
10721  appendStringInfo(buf, "'%s'", extval);
10722  needlabel = true; /* we must attach a cast */
10723  }
10724  break;
10725 
10726  case BOOLOID:
10727  if (strcmp(extval, "t") == 0)
10728  appendStringInfoString(buf, "true");
10729  else
10730  appendStringInfoString(buf, "false");
10731  break;
10732 
10733  default:
10734  simple_quote_literal(buf, extval);
10735  break;
10736  }
10737 
10738  pfree(extval);
10739 
10740  if (showtype < 0)
10741  return;
10742 
10743  /*
10744  * For showtype == 0, append ::typename unless the constant will be
10745  * implicitly typed as the right type when it is read in.
10746  *
10747  * XXX this code has to be kept in sync with the behavior of the parser,
10748  * especially make_const.
10749  */
10750  switch (constval->consttype)
10751  {
10752  case BOOLOID:
10753  case UNKNOWNOID:
10754  /* These types can be left unlabeled */
10755  needlabel = false;
10756  break;
10757  case INT4OID:
10758  /* We determined above whether a label is needed */
10759  break;
10760  case NUMERICOID:
10761 
10762  /*
10763  * Float-looking constants will be typed as numeric, which we
10764  * checked above; but if there's a nondefault typmod we need to
10765  * show it.
10766  */
10767  needlabel |= (constval->consttypmod >= 0);
10768  break;
10769  default:
10770  needlabel = true;
10771  break;
10772  }
10773  if (needlabel || showtype > 0)
10774  appendStringInfo(buf, "::%s",
10776  constval->consttypmod));
10777 
10778  get_const_collation(constval, context);
10779 }
10780 
10781 /*
10782  * helper for get_const_expr: append COLLATE if needed
10783  */
10784 static void
10786 {
10787  StringInfo buf = context->buf;
10788 
10789  if (OidIsValid(constval->constcollid))
10790  {
10791  Oid typcollation = get_typcollation(constval->consttype);
10792 
10793  if (constval->constcollid != typcollation)
10794  {
10795  appendStringInfo(buf, " COLLATE %s",
10796  generate_collation_name(constval->constcollid));
10797  }
10798  }
10799 }
10800 
10801 /*
10802  * get_json_format - Parse back a JsonFormat node
10803  */
10804 static void
10806 {
10807  if (format->format_type == JS_FORMAT_DEFAULT)
10808  return;
10809 
10811  format->format_type == JS_FORMAT_JSONB ?
10812  " FORMAT JSONB" : " FORMAT JSON");
10813 
10814  if (format->encoding != JS_ENC_DEFAULT)
10815  {
10816  const char *encoding;
10817 
10818  encoding =
10819  format->encoding == JS_ENC_UTF16 ? "UTF16" :
10820  format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
10821 
10822  appendStringInfo(buf, " ENCODING %s", encoding);
10823  }
10824 }
10825 
10826 /*
10827  * get_json_returning - Parse back a JsonReturning structure
10828  */
10829 static void
10831  bool json_format_by_default)
10832 {
10833  if (!OidIsValid(returning->typid))
10834  return;
10835 
10836  appendStringInfo(buf, " RETURNING %s",
10837  format_type_with_typemod(returning->typid,
10838  returning->typmod));
10839 
10840  if (!json_format_by_default ||
10841  returning->format->format_type !=
10842  (returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
10843  get_json_format(returning->format, buf);
10844 }
10845 
10846 /*
10847  * get_json_constructor - Parse back a JsonConstructorExpr node
10848  */
10849 static void
10851  bool showimplicit)
10852 {
10853  StringInfo buf = context->buf;
10854  const char *funcname;
10855  bool is_json_object;
10856  int curridx;
10857  ListCell *lc;
10858 
10859  if (ctor->type == JSCTOR_JSON_OBJECTAGG)
10860  {
10861  get_json_agg_constructor(ctor, context, "JSON_OBJECTAGG", true);
10862  return;
10863  }
10864  else if (ctor->type == JSCTOR_JSON_ARRAYAGG)
10865  {
10866  get_json_agg_constructor(ctor, context, "JSON_ARRAYAGG", false);
10867  return;
10868  }
10869 
10870  switch (ctor->type)
10871  {
10872  case JSCTOR_JSON_OBJECT:
10873  funcname = "JSON_OBJECT";
10874  break;
10875  case JSCTOR_JSON_ARRAY:
10876  funcname = "JSON_ARRAY";
10877  break;
10878  case JSCTOR_JSON_PARSE:
10879  funcname = "JSON";
10880  break;
10881  case JSCTOR_JSON_SCALAR:
10882  funcname = "JSON_SCALAR";
10883  break;
10884  case JSCTOR_JSON_SERIALIZE:
10885  funcname = "JSON_SERIALIZE";
10886  break;
10887  default:
10888  elog(ERROR, "invalid JsonConstructorType %d", ctor->type);
10889  }
10890 
10891  appendStringInfo(buf, "%s(", funcname);
10892 
10893  is_json_object = ctor->type == JSCTOR_JSON_OBJECT;
10894  foreach(lc, ctor->args)
10895  {
10896  curridx = foreach_current_index(lc);
10897  if (curridx > 0)
10898  {
10899  const char *sep;
10900 
10901  sep = (is_json_object && (curridx % 2) != 0) ? " : " : ", ";
10903  }
10904 
10905  get_rule_expr((Node *) lfirst(lc), context, true);
10906  }
10907 
10909  appendStringInfoChar(buf, ')');
10910 }
10911 
10912 /*
10913  * Append options, if any, to the JSON constructor being deparsed
10914  */
10915 static void
10917 {
10918  if (ctor->absent_on_null)
10919  {
10920  if (ctor->type == JSCTOR_JSON_OBJECT ||
10921  ctor->type == JSCTOR_JSON_OBJECTAGG)
10922  appendStringInfoString(buf, " ABSENT ON NULL");
10923  }
10924  else
10925  {
10926  if (ctor->type == JSCTOR_JSON_ARRAY ||
10927  ctor->type == JSCTOR_JSON_ARRAYAGG)
10928  appendStringInfoString(buf, " NULL ON NULL");
10929  }
10930 
10931  if (ctor->unique)
10932  appendStringInfoString(buf, " WITH UNIQUE KEYS");
10933 
10934  /*
10935  * Append RETURNING clause if needed; JSON() and JSON_SCALAR() don't
10936  * support one.
10937  */
10938  if (ctor->type != JSCTOR_JSON_PARSE && ctor->type != JSCTOR_JSON_SCALAR)
10939  get_json_returning(ctor->returning, buf, true);
10940 }
10941 
10942 /*
10943  * get_json_agg_constructor - Parse back an aggregate JsonConstructorExpr node
10944  */
10945 static void
10947  const char *funcname, bool is_json_objectagg)
10948 {
10950 
10953 
10954  if (IsA(ctor->func, Aggref))
10955  get_agg_expr_helper((Aggref *) ctor->func, context,
10956  (Aggref *) ctor->func,
10957  funcname, options.data, is_json_objectagg);
10958  else if (IsA(ctor->func, WindowFunc))
10959  get_windowfunc_expr_helper((WindowFunc *) ctor->func, context,
10960  funcname, options.data,
10961  is_json_objectagg);
10962  else
10963  elog(ERROR, "invalid JsonConstructorExpr underlying node type: %d",
10964  nodeTag(ctor->func));
10965 }
10966 
10967 /*
10968  * simple_quote_literal - Format a string as a SQL literal, append to buf
10969  */
10970 static void
10972 {
10973  const char *valptr;
10974 
10975  /*
10976  * We form the string literal according to the prevailing setting of
10977  * standard_conforming_strings; we never use E''. User is responsible for
10978  * making sure result is used correctly.
10979  */
10980  appendStringInfoChar(buf, '\'');
10981  for (valptr = val; *valptr; valptr++)
10982  {
10983  char ch = *valptr;
10984 
10988  }
10989  appendStringInfoChar(buf, '\'');
10990 }
10991 
10992 
10993 /* ----------
10994  * get_sublink_expr - Parse back a sublink
10995  * ----------
10996  */
10997 static void
10999 {
11000  StringInfo buf = context->buf;
11001  Query *query = (Query *) (sublink->subselect);
11002  char *opname = NULL;
11003  bool need_paren;
11004 
11005  if (sublink->subLinkType == ARRAY_SUBLINK)
11006  appendStringInfoString(buf, "ARRAY(");
11007  else
11008  appendStringInfoChar(buf, '(');
11009 
11010  /*
11011  * Note that we print the name of only the first operator, when there are
11012  * multiple combining operators. This is an approximation that could go
11013  * wrong in various scenarios (operators in different schemas, renamed
11014  * operators, etc) but there is not a whole lot we can do about it, since
11015  * the syntax allows only one operator to be shown.
11016  */
11017  if (sublink->testexpr)
11018  {
11019  if (IsA(sublink->testexpr, OpExpr))
11020  {
11021  /* single combining operator */
11022  OpExpr *opexpr = (OpExpr *) sublink->testexpr;
11023 
11024  get_rule_expr(linitial(opexpr->args), context, true);
11025  opname = generate_operator_name(opexpr->opno,
11026  exprType(linitial(opexpr->args)),
11027  exprType(lsecond(opexpr->args)));
11028  }
11029  else if (IsA(sublink->testexpr, BoolExpr))
11030  {
11031  /* multiple combining operators, = or <> cases */
11032  char *sep;
11033  ListCell *l;
11034 
11035  appendStringInfoChar(buf, '(');
11036  sep = "";
11037  foreach(l, ((BoolExpr *) sublink->testexpr)->args)
11038  {
11039  OpExpr *opexpr = lfirst_node(OpExpr, l);
11040 
11042  get_rule_expr(linitial(opexpr->args), context, true);
11043  if (!opname)
11044  opname = generate_operator_name(opexpr->opno,
11045  exprType(linitial(opexpr->args)),
11046  exprType(lsecond(opexpr->args)));
11047  sep = ", ";
11048  }
11049  appendStringInfoChar(buf, ')');
11050  }
11051  else if (IsA(sublink->testexpr, RowCompareExpr))
11052  {
11053  /* multiple combining operators, < <= > >= cases */
11054  RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
11055 
11056  appendStringInfoChar(buf, '(');
11057  get_rule_expr((Node *) rcexpr->largs, context, true);
11058  opname = generate_operator_name(linitial_oid(rcexpr->opnos),
11059  exprType(linitial(rcexpr->largs)),
11060  exprType(linitial(rcexpr->rargs)));
11061  appendStringInfoChar(buf, ')');
11062  }
11063  else
11064  elog(ERROR, "unrecognized testexpr type: %d",
11065  (int) nodeTag(sublink->testexpr));
11066  }
11067 
11068  need_paren = true;
11069 
11070  switch (sublink->subLinkType)
11071  {
11072  case EXISTS_SUBLINK:
11073  appendStringInfoString(buf, "EXISTS ");
11074  break;
11075 
11076  case ANY_SUBLINK:
11077  if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
11078  appendStringInfoString(buf, " IN ");
11079  else
11080  appendStringInfo(buf, " %s ANY ", opname);
11081  break;
11082 
11083  case ALL_SUBLINK:
11084  appendStringInfo(buf, " %s ALL ", opname);
11085  break;
11086 
11087  case ROWCOMPARE_SUBLINK:
11088  appendStringInfo(buf, " %s ", opname);
11089  break;
11090 
11091  case EXPR_SUBLINK:
11092  case MULTIEXPR_SUBLINK:
11093  case ARRAY_SUBLINK:
11094  need_paren = false;
11095  break;
11096 
11097  case CTE_SUBLINK: /* shouldn't occur in a SubLink */
11098  default:
11099  elog(ERROR, "unrecognized sublink type: %d",
11100  (int) sublink->subLinkType);
11101  break;
11102  }
11103 
11104  if (need_paren)
11105  appendStringInfoChar(buf, '(');
11106 
11107  get_query_def(query, buf, context->namespaces, NULL, false,
11108  context->prettyFlags, context->wrapColumn,
11109  context->indentLevel);
11110 
11111  if (need_paren)
11112  appendStringInfoString(buf, "))");
11113  else
11114  appendStringInfoChar(buf, ')');
11115 }
11116 
11117 
11118 /* ----------
11119  * get_tablefunc - Parse back a table function
11120  * ----------
11121  */
11122 static void
11123 get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
11124 {
11125  StringInfo buf = context->buf;
11126 
11127  /* XMLTABLE is the only existing implementation. */
11128 
11129  appendStringInfoString(buf, "XMLTABLE(");
11130 
11131  if (tf->ns_uris != NIL)
11132  {
11133  ListCell *lc1,
11134  *lc2;
11135  bool first = true;
11136 
11137  appendStringInfoString(buf, "XMLNAMESPACES (");
11138  forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
11139  {
11140  Node *expr = (Node *) lfirst(lc1);
11141  String *ns_node = lfirst_node(String, lc2);
11142 
11143  if (!first)
11144  appendStringInfoString(buf, ", ");
11145  else
11146  first = false;
11147 
11148  if (ns_node != NULL)
11149  {
11150  get_rule_expr(expr, context, showimplicit);
11151  appendStringInfo(buf, " AS %s", strVal(ns_node));
11152  }
11153  else
11154  {
11155  appendStringInfoString(buf, "DEFAULT ");
11156  get_rule_expr(expr, context, showimplicit);
11157  }
11158  }
11159  appendStringInfoString(buf, "), ");
11160  }
11161 
11162  appendStringInfoChar(buf, '(');
11163  get_rule_expr((Node *) tf->rowexpr, context, showimplicit);
11164  appendStringInfoString(buf, ") PASSING (");
11165  get_rule_expr((Node *) tf->docexpr, context, showimplicit);
11166  appendStringInfoChar(buf, ')');
11167 
11168  if (tf->colexprs != NIL)
11169  {
11170  ListCell *l1;
11171  ListCell *l2;
11172  ListCell *l3;
11173  ListCell *l4;
11174  ListCell *l5;
11175  int colnum = 0;
11176 
11177  appendStringInfoString(buf, " COLUMNS ");
11178  forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods,
11179  l4, tf->colexprs, l5, tf->coldefexprs)
11180  {
11181  char *colname = strVal(lfirst(l1));
11182  Oid typid = lfirst_oid(l2);
11183  int32 typmod = lfirst_int(l3);
11184  Node *colexpr = (Node *) lfirst(l4);
11185  Node *coldefexpr = (Node *) lfirst(l5);
11186  bool ordinality = (tf->ordinalitycol == colnum);
11187  bool notnull = bms_is_member(colnum, tf->notnulls);
11188 
11189  if (colnum > 0)
11190  appendStringInfoString(buf, ", ");
11191  colnum++;
11192 
11193  appendStringInfo(buf, "%s %s", quote_identifier(colname),
11194  ordinality ? "FOR ORDINALITY" :
11195  format_type_with_typemod(typid, typmod));
11196  if (ordinality)
11197  continue;
11198 
11199  if (coldefexpr != NULL)
11200  {
11201  appendStringInfoString(buf, " DEFAULT (");
11202  get_rule_expr((Node *) coldefexpr, context, showimplicit);
11203  appendStringInfoChar(buf, ')');
11204  }
11205  if (colexpr != NULL)
11206  {
11207  appendStringInfoString(buf, " PATH (");
11208  get_rule_expr((Node *) colexpr, context, showimplicit);
11209  appendStringInfoChar(buf, ')');
11210  }
11211  if (notnull)
11212  appendStringInfoString(buf, " NOT NULL");
11213  }
11214  }
11215 
11216  appendStringInfoChar(buf, ')');
11217 }
11218 
11219 /* ----------
11220  * get_from_clause - Parse back a FROM clause
11221  *
11222  * "prefix" is the keyword that denotes the start of the list of FROM
11223  * elements. It is FROM when used to parse back SELECT and UPDATE, but
11224  * is USING when parsing back DELETE.
11225  * ----------
11226  */
11227 static void
11228 get_from_clause(Query *query, const char *prefix, deparse_context *context)
11229 {
11230  StringInfo buf = context->buf;
11231  bool first = true;
11232  ListCell *l;
11233 
11234  /*
11235  * We use the query's jointree as a guide to what to print. However, we
11236  * must ignore auto-added RTEs that are marked not inFromCl. (These can
11237  * only appear at the top level of the jointree, so it's sufficient to
11238  * check here.) This check also ensures we ignore the rule pseudo-RTEs
11239  * for NEW and OLD.
11240  */
11241  foreach(l, query->jointree->fromlist)
11242  {
11243  Node *jtnode = (Node *) lfirst(l);
11244 
11245  if (IsA(jtnode, RangeTblRef))
11246  {
11247  int varno = ((RangeTblRef *) jtnode)->rtindex;
11248  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
11249 
11250  if (!rte->inFromCl)
11251  continue;
11252  }
11253 
11254  if (first)
11255  {
11256  appendContextKeyword(context, prefix,
11258  first = false;
11259 
11260  get_from_clause_item(jtnode, query, context);
11261  }
11262  else
11263  {
11264  StringInfoData itembuf;
11265 
11266  appendStringInfoString(buf, ", ");
11267 
11268  /*
11269  * Put the new FROM item's text into itembuf so we can decide
11270  * after we've got it whether or not it needs to go on a new line.
11271  */
11272  initStringInfo(&itembuf);
11273  context->buf = &itembuf;
11274 
11275  get_from_clause_item(jtnode, query, context);
11276 
11277  /* Restore context's output buffer */
11278  context->buf = buf;
11279 
11280  /* Consider line-wrapping if enabled */
11281  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
11282  {
11283  /* Does the new item start with a new line? */
11284  if (itembuf.len > 0 && itembuf.data[0] == '\n')
11285  {
11286  /* If so, we shouldn't add anything */
11287  /* instead, remove any trailing spaces currently in buf */
11289  }
11290  else
11291  {
11292  char *trailing_nl;
11293 
11294  /* Locate the start of the current line in the buffer */
11295  trailing_nl = strrchr(buf->data, '\n');
11296  if (trailing_nl == NULL)
11297  trailing_nl = buf->data;
11298  else
11299  trailing_nl++;
11300 
11301  /*
11302  * Add a newline, plus some indentation, if the new item
11303  * would cause an overflow.
11304  */
11305  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
11306  appendContextKeyword(context, "", -PRETTYINDENT_STD,
11309  }
11310  }
11311 
11312  /* Add the new item */
11313  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
11314 
11315  /* clean up */
11316  pfree(itembuf.data);
11317  }
11318  }
11319 }
11320 
11321 static void
11323 {
11324  StringInfo buf = context->buf;
11326 
11327  if (IsA(jtnode, RangeTblRef))
11328  {
11329  int varno = ((RangeTblRef *) jtnode)->rtindex;
11330  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
11331  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
11332  RangeTblFunction *rtfunc1 = NULL;
11333 
11334  if (rte->lateral)
11335  appendStringInfoString(buf, "LATERAL ");
11336 
11337  /* Print the FROM item proper */
11338  switch (rte->rtekind)
11339  {
11340  case RTE_RELATION:
11341  /* Normal relation RTE */
11342  appendStringInfo(buf, "%s%s",
11343  only_marker(rte),
11345  context->namespaces));
11346  break;
11347  case RTE_SUBQUERY:
11348  /* Subquery RTE */
11349  appendStringInfoChar(buf, '(');
11350  get_query_def(rte->subquery, buf, context->namespaces, NULL,
11351  true,
11352  context->prettyFlags, context->wrapColumn,
11353  context->indentLevel);
11354  appendStringInfoChar(buf, ')');
11355  break;
11356  case RTE_FUNCTION:
11357  /* Function RTE */
11358  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
11359 
11360  /*
11361  * Omit ROWS FROM() syntax for just one function, unless it
11362  * has both a coldeflist and WITH ORDINALITY. If it has both,
11363  * we must use ROWS FROM() syntax to avoid ambiguity about
11364  * whether the coldeflist includes the ordinality column.
11365  */
11366  if (list_length(rte->functions) == 1 &&
11367  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
11368  {
11369  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
11370  /* we'll print the coldeflist below, if it has one */
11371  }
11372  else
11373  {
11374  bool all_unnest;
11375  ListCell *lc;
11376 
11377  /*
11378  * If all the function calls in the list are to unnest,
11379  * and none need a coldeflist, then collapse the list back
11380  * down to UNNEST(args). (If we had more than one
11381  * built-in unnest function, this would get more
11382  * difficult.)
11383  *
11384  * XXX This is pretty ugly, since it makes not-terribly-
11385  * future-proof assumptions about what the parser would do
11386  * with the output; but the alternative is to emit our
11387  * nonstandard ROWS FROM() notation for what might have
11388  * been a perfectly spec-compliant multi-argument
11389  * UNNEST().
11390  */
11391  all_unnest = true;
11392  foreach(lc, rte->functions)
11393  {
11394  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
11395 
11396  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
11397  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
11398  rtfunc->funccolnames != NIL)
11399  {
11400  all_unnest = false;
11401  break;
11402  }
11403  }
11404 
11405  if (all_unnest)
11406  {
11407  List *allargs = NIL;
11408 
11409  foreach(lc, rte->functions)
11410  {
11411  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
11412  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
11413 
11414  allargs = list_concat(allargs, args);
11415  }
11416 
11417  appendStringInfoString(buf, "UNNEST(");
11418  get_rule_expr((Node *) allargs, context, true);
11419  appendStringInfoChar(buf, ')');
11420  }
11421  else
11422  {
11423  int funcno = 0;
11424 
11425  appendStringInfoString(buf, "ROWS FROM(");
11426  foreach(lc, rte->functions)
11427  {
11428  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
11429 
11430  if (funcno > 0)
11431  appendStringInfoString(buf, ", ");
11432  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
11433  if (rtfunc->funccolnames != NIL)
11434  {
11435  /* Reconstruct the column definition list */
11436  appendStringInfoString(buf, " AS ");
11438  NULL,
11439  context);
11440  }
11441  funcno++;
11442  }
11443  appendStringInfoChar(buf, ')');
11444  }
11445  /* prevent printing duplicate coldeflist below */
11446  rtfunc1 = NULL;
11447  }
11448  if (rte->funcordinality)
11449  appendStringInfoString(buf, " WITH ORDINALITY");
11450  break;
11451  case RTE_TABLEFUNC:
11452  get_tablefunc(rte->tablefunc, context, true);
11453  break;
11454  case RTE_VALUES:
11455  /* Values list RTE */
11456  appendStringInfoChar(buf, '(');
11457  get_values_def(rte->values_lists, context);
11458  appendStringInfoChar(buf, ')');
11459  break;
11460  case RTE_CTE:
11462  break;
11463  default:
11464  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
11465  break;
11466  }
11467 
11468  /* Print the relation alias, if needed */
11469  get_rte_alias(rte, varno, false, context);
11470 
11471  /* Print the column definitions or aliases, if needed */
11472  if (rtfunc1 && rtfunc1->funccolnames != NIL)
11473  {
11474  /* Reconstruct the columndef list, which is also the aliases */
11475  get_from_clause_coldeflist(rtfunc1, colinfo, context);
11476  }
11477  else
11478  {
11479  /* Else print column aliases as needed */
11480  get_column_alias_list(colinfo, context);
11481  }
11482 
11483  /* Tablesample clause must go after any alias */
11484  if (rte->rtekind == RTE_RELATION && rte->tablesample)
11485  get_tablesample_def(rte->tablesample, context);
11486  }
11487  else if (IsA(jtnode, JoinExpr))
11488  {
11489  JoinExpr *j = (JoinExpr *) jtnode;
11490  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
11491  bool need_paren_on_right;
11492 
11493  need_paren_on_right = PRETTY_PAREN(context) &&
11494  !IsA(j->rarg, RangeTblRef) &&
11495  !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
11496 
11497  if (!PRETTY_PAREN(context) || j->alias != NULL)
11498  appendStringInfoChar(buf, '(');
11499 
11500  get_from_clause_item(j->larg, query, context);
11501 
11502  switch (j->jointype)
11503  {
11504  case JOIN_INNER:
11505  if (j->quals)
11506  appendContextKeyword(context, " JOIN ",
11510  else
11511  appendContextKeyword(context, " CROSS JOIN ",
11515  break;
11516  case JOIN_LEFT:
11517  appendContextKeyword(context, " LEFT JOIN ",
11521  break;
11522  case JOIN_FULL:
11523  appendContextKeyword(context, " FULL JOIN ",
11527  break;
11528  case JOIN_RIGHT:
11529  appendContextKeyword(context, " RIGHT JOIN ",
11533  break;
11534  default:
11535  elog(ERROR, "unrecognized join type: %d",
11536  (int) j->jointype);
11537  }
11538 
11539  if (need_paren_on_right)
11540  appendStringInfoChar(buf, '(');
11541  get_from_clause_item(j->rarg, query, context);
11542  if (need_paren_on_right)
11543  appendStringInfoChar(buf, ')');
11544 
11545  if (j->usingClause)
11546  {
11547  ListCell *lc;
11548  bool first = true;
11549 
11550  appendStringInfoString(buf, " USING (");
11551  /* Use the assigned names, not what's in usingClause */
11552  foreach(lc, colinfo->usingNames)
11553  {
11554  char *colname = (char *) lfirst(lc);
11555 
11556  if (first)
11557  first = false;
11558  else
11559  appendStringInfoString(buf, ", ");
11561  }
11562  appendStringInfoChar(buf, ')');
11563 
11564  if (j->join_using_alias)
11565  appendStringInfo(buf, " AS %s",
11566  quote_identifier(j->join_using_alias->aliasname));
11567  }
11568  else if (j->quals)
11569  {
11570  appendStringInfoString(buf, " ON ");
11571  if (!PRETTY_PAREN(context))
11572  appendStringInfoChar(buf, '(');
11573  get_rule_expr(j->quals, context, false);
11574  if (!PRETTY_PAREN(context))
11575  appendStringInfoChar(buf, ')');
11576  }
11577  else if (j->jointype != JOIN_INNER)
11578  {
11579  /* If we didn't say CROSS JOIN above, we must provide an ON */
11580  appendStringInfoString(buf, " ON TRUE");
11581  }
11582 
11583  if (!PRETTY_PAREN(context) || j->alias != NULL)
11584  appendStringInfoChar(buf, ')');
11585 
11586  /* Yes, it's correct to put alias after the right paren ... */
11587  if (j->alias != NULL)
11588  {
11589  /*
11590  * Note that it's correct to emit an alias clause if and only if
11591  * there was one originally. Otherwise we'd be converting a named
11592  * join to unnamed or vice versa, which creates semantic
11593  * subtleties we don't want. However, we might print a different
11594  * alias name than was there originally.
11595  */
11596  appendStringInfo(buf, " %s",
11598  context)));
11599  get_column_alias_list(colinfo, context);
11600  }
11601  }
11602  else
11603  elog(ERROR, "unrecognized node type: %d",
11604  (int) nodeTag(jtnode));
11605 }
11606 
11607 /*
11608  * get_rte_alias - print the relation's alias, if needed
11609  *
11610  * If printed, the alias is preceded by a space, or by " AS " if use_as is true.
11611  */
11612 static void
11613 get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
11614  deparse_context *context)
11615 {
11617  char *refname = get_rtable_name(varno, context);
11618  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
11619  bool printalias = false;
11620 
11621  if (rte->alias != NULL)
11622  {
11623  /* Always print alias if user provided one */
11624  printalias = true;
11625  }
11626  else if (colinfo->printaliases)
11627  {
11628  /* Always print alias if we need to print column aliases */
11629  printalias = true;
11630  }
11631  else if (rte->rtekind == RTE_RELATION)
11632  {
11633  /*
11634  * No need to print alias if it's same as relation name (this would
11635  * normally be the case, but not if set_rtable_names had to resolve a
11636  * conflict).
11637  */
11638  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
11639  printalias = true;
11640  }
11641  else if (rte->rtekind == RTE_FUNCTION)
11642  {
11643  /*
11644  * For a function RTE, always print alias. This covers possible
11645  * renaming of the function and/or instability of the FigureColname
11646  * rules for things that aren't simple functions. Note we'd need to
11647  * force it anyway for the columndef list case.
11648  */
11649  printalias = true;
11650  }
11651  else if (rte->rtekind == RTE_SUBQUERY ||
11652  rte->rtekind == RTE_VALUES)
11653  {
11654  /*
11655  * For a subquery, always print alias. This makes the output
11656  * SQL-spec-compliant, even though we allow such aliases to be omitted
11657  * on input.
11658  */
11659  printalias = true;
11660  }
11661  else if (rte->rtekind == RTE_CTE)
11662  {
11663  /*
11664  * No need to print alias if it's same as CTE name (this would
11665  * normally be the case, but not if set_rtable_names had to resolve a
11666  * conflict).
11667  */
11668  if (strcmp(refname, rte->ctename) != 0)
11669  printalias = true;
11670  }
11671 
11672  if (printalias)
11673  appendStringInfo(context->buf, "%s%s",
11674  use_as ? " AS " : " ",
11675  quote_identifier(refname));
11676 }
11677 
11678 /*
11679  * get_column_alias_list - print column alias list for an RTE
11680  *
11681  * Caller must already have printed the relation's alias name.
11682  */
11683 static void
11685 {
11686  StringInfo buf = context->buf;
11687  int i;
11688  bool first = true;
11689 
11690  /* Don't print aliases if not needed */
11691  if (!colinfo->printaliases)
11692  return;
11693 
11694  for (i = 0; i < colinfo->num_new_cols; i++)
11695  {
11696  char *colname = colinfo->new_colnames[i];
11697 
11698  if (first)
11699  {
11700  appendStringInfoChar(buf, '(');
11701  first = false;
11702  }
11703  else
11704  appendStringInfoString(buf, ", ");
11706  }
11707  if (!first)
11708  appendStringInfoChar(buf, ')');
11709 }
11710 
11711 /*
11712  * get_from_clause_coldeflist - reproduce FROM clause coldeflist
11713  *
11714  * When printing a top-level coldeflist (which is syntactically also the
11715  * relation's column alias list), use column names from colinfo. But when
11716  * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
11717  * original coldeflist's names, which are available in rtfunc->funccolnames.
11718  * Pass NULL for colinfo to select the latter behavior.
11719  *
11720  * The coldeflist is appended immediately (no space) to buf. Caller is
11721  * responsible for ensuring that an alias or AS is present before it.
11722  */
11723 static void
11725  deparse_columns *colinfo,
11726  deparse_context *context)
11727 {
11728  StringInfo buf = context->buf;
11729  ListCell *l1;
11730  ListCell *l2;
11731  ListCell *l3;
11732  ListCell *l4;
11733  int i;
11734 
11735  appendStringInfoChar(buf, '(');
11736 
11737  i = 0;
11738  forfour(l1, rtfunc->funccoltypes,
11739  l2, rtfunc->funccoltypmods,
11740  l3, rtfunc->funccolcollations,
11741  l4, rtfunc->funccolnames)
11742  {
11743  Oid atttypid = lfirst_oid(l1);
11744  int32 atttypmod = lfirst_int(l2);
11745  Oid attcollation = lfirst_oid(l3);
11746  char *attname;
11747 
11748  if (colinfo)
11749  attname = colinfo->colnames[i];
11750  else
11751  attname = strVal(lfirst(l4));
11752 
11753  Assert(attname); /* shouldn't be any dropped columns here */
11754 
11755  if (i > 0)
11756  appendStringInfoString(buf, ", ");
11757  appendStringInfo(buf, "%s %s",
11759  format_type_with_typemod(atttypid, atttypmod));
11760  if (OidIsValid(attcollation) &&
11761  attcollation != get_typcollation(atttypid))
11762  appendStringInfo(buf, " COLLATE %s",
11763  generate_collation_name(attcollation));
11764 
11765  i++;
11766  }
11767 
11768  appendStringInfoChar(buf, ')');
11769 }
11770 
11771 /*
11772  * get_tablesample_def - print a TableSampleClause
11773  */
11774 static void
11776 {
11777  StringInfo buf = context->buf;
11778  Oid argtypes[1];
11779  int nargs;
11780  ListCell *l;
11781 
11782  /*
11783  * We should qualify the handler's function name if it wouldn't be
11784  * resolved by lookup in the current search path.
11785  */
11786  argtypes[0] = INTERNALOID;
11787  appendStringInfo(buf, " TABLESAMPLE %s (",
11788  generate_function_name(tablesample->tsmhandler, 1,
11789  NIL, argtypes,
11790  false, NULL, EXPR_KIND_NONE));
11791 
11792  nargs = 0;
11793  foreach(l, tablesample->args)
11794  {
11795  if (nargs++ > 0)
11796  appendStringInfoString(buf, ", ");
11797  get_rule_expr((Node *) lfirst(l), context, false);
11798  }
11799  appendStringInfoChar(buf, ')');
11800 
11801  if (tablesample->repeatable != NULL)
11802  {
11803  appendStringInfoString(buf, " REPEATABLE (");
11804  get_rule_expr((Node *) tablesample->repeatable, context, false);
11805  appendStringInfoChar(buf, ')');
11806  }
11807 }
11808 
11809 /*
11810  * get_opclass_name - fetch name of an index operator class
11811  *
11812  * The opclass name is appended (after a space) to buf.
11813  *
11814  * Output is suppressed if the opclass is the default for the given
11815  * actual_datatype. (If you don't want this behavior, just pass
11816  * InvalidOid for actual_datatype.)
11817  */
11818 static void
11819 get_opclass_name(Oid opclass, Oid actual_datatype,
11820  StringInfo buf)
11821 {
11822  HeapTuple ht_opc;
11823  Form_pg_opclass opcrec;
11824  char *opcname;
11825  char *nspname;
11826 
11827  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
11828  if (!HeapTupleIsValid(ht_opc))
11829  elog(ERROR, "cache lookup failed for opclass %u", opclass);
11830  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
11831 
11832  if (!OidIsValid(actual_datatype) ||
11833  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
11834  {
11835  /* Okay, we need the opclass name. Do we need to qualify it? */
11836  opcname = NameStr(opcrec->opcname);
11837  if (OpclassIsVisible(opclass))
11838  appendStringInfo(buf, " %s", quote_identifier(opcname));
11839  else
11840  {
11841  nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
11842  appendStringInfo(buf, " %s.%s",
11843  quote_identifier(nspname),
11844  quote_identifier(opcname));
11845  }
11846  }
11847  ReleaseSysCache(ht_opc);
11848 }
11849 
11850 /*
11851  * generate_opclass_name
11852  * Compute the name to display for an opclass specified by OID
11853  *
11854  * The result includes all necessary quoting and schema-prefixing.
11855  */
11856 char *
11858 {
11860 
11861  initStringInfo(&buf);
11862  get_opclass_name(opclass, InvalidOid, &buf);
11863 
11864  return &buf.data[1]; /* get_opclass_name() prepends space */
11865 }
11866 
11867 /*
11868  * processIndirection - take care of array and subfield assignment
11869  *
11870  * We strip any top-level FieldStore or assignment SubscriptingRef nodes that
11871  * appear in the input, printing them as decoration for the base column
11872  * name (which we assume the caller just printed). We might also need to
11873  * strip CoerceToDomain nodes, but only ones that appear above assignment
11874  * nodes.
11875  *
11876  * Returns the subexpression that's to be assigned.
11877  */
11878 static Node *
11880 {
11881  StringInfo buf = context->buf;
11882  CoerceToDomain *cdomain = NULL;
11883 
11884  for (;;)
11885  {
11886  if (node == NULL)
11887  break;
11888  if (IsA(node, FieldStore))
11889  {
11890  FieldStore *fstore = (FieldStore *) node;
11891  Oid typrelid;
11892  char *fieldname;
11893 
11894  /* lookup tuple type */
11895  typrelid = get_typ_typrelid(fstore->resulttype);
11896  if (!OidIsValid(typrelid))
11897  elog(ERROR, "argument type %s of FieldStore is not a tuple type",
11898  format_type_be(fstore->resulttype));
11899 
11900  /*
11901  * Print the field name. There should only be one target field in
11902  * stored rules. There could be more than that in executable
11903  * target lists, but this function cannot be used for that case.
11904  */
11905  Assert(list_length(fstore->fieldnums) == 1);
11906  fieldname = get_attname(typrelid,
11907  linitial_int(fstore->fieldnums), false);
11908  appendStringInfo(buf, ".%s", quote_identifier(fieldname));
11909 
11910  /*
11911  * We ignore arg since it should be an uninteresting reference to
11912  * the target column or subcolumn.
11913  */
11914  node = (Node *) linitial(fstore->newvals);
11915  }
11916  else if (IsA(node, SubscriptingRef))
11917  {
11918  SubscriptingRef *sbsref = (SubscriptingRef *) node;
11919 
11920  if (sbsref->refassgnexpr == NULL)
11921  break;
11922 
11923  printSubscripts(sbsref, context);
11924 
11925  /*
11926  * We ignore refexpr since it should be an uninteresting reference
11927  * to the target column or subcolumn.
11928  */
11929  node = (Node *) sbsref->refassgnexpr;
11930  }
11931  else if (IsA(node, CoerceToDomain))
11932  {
11933  cdomain = (CoerceToDomain *) node;
11934  /* If it's an explicit domain coercion, we're done */
11935  if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
11936  break;
11937  /* Tentatively descend past the CoerceToDomain */
11938  node = (Node *) cdomain->arg;
11939  }
11940  else
11941  break;
11942  }
11943 
11944  /*
11945  * If we descended past a CoerceToDomain whose argument turned out not to
11946  * be a FieldStore or array assignment, back up to the CoerceToDomain.
11947  * (This is not enough to be fully correct if there are nested implicit
11948  * CoerceToDomains, but such cases shouldn't ever occur.)
11949  */
11950  if (cdomain && node == (Node *) cdomain->arg)
11951  node = (Node *) cdomain;
11952 
11953  return node;
11954 }
11955 
11956 static void
11958 {
11959  StringInfo buf = context->buf;
11960  ListCell *lowlist_item;
11961  ListCell *uplist_item;
11962 
11963  lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */
11964  foreach(uplist_item, sbsref->refupperindexpr)
11965  {
11966  appendStringInfoChar(buf, '[');
11967  if (lowlist_item)
11968  {
11969  /* If subexpression is NULL, get_rule_expr prints nothing */
11970  get_rule_expr((Node *) lfirst(lowlist_item), context, false);
11971  appendStringInfoChar(buf, ':');
11972  lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
11973  }
11974  /* If subexpression is NULL, get_rule_expr prints nothing */
11975  get_rule_expr((Node *) lfirst(uplist_item), context, false);
11976  appendStringInfoChar(buf, ']');
11977  }
11978 }
11979 
11980 /*
11981  * quote_identifier - Quote an identifier only if needed
11982  *
11983  * When quotes are needed, we palloc the required space; slightly
11984  * space-wasteful but well worth it for notational simplicity.
11985  */
11986 const char *
11988 {
11989  /*
11990  * Can avoid quoting if ident starts with a lowercase letter or underscore
11991  * and contains only lowercase letters, digits, and underscores, *and* is
11992  * not any SQL keyword. Otherwise, supply quotes.
11993  */
11994  int nquotes = 0;
11995  bool safe;
11996  const char *ptr;
11997  char *result;
11998  char *optr;
11999 
12000  /*
12001  * would like to use <ctype.h> macros here, but they might yield unwanted
12002  * locale-specific results...
12003  */
12004  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12005 
12006  for (ptr = ident; *ptr; ptr++)
12007  {
12008  char ch = *ptr;
12009 
12010  if ((ch >= 'a' && ch <= 'z') ||
12011  (ch >= '0' && ch <= '9') ||
12012  (ch == '_'))
12013  {
12014  /* okay */
12015  }
12016  else
12017  {
12018  safe = false;
12019  if (ch == '"')
12020  nquotes++;
12021  }
12022  }
12023 
12025  safe = false;
12026 
12027  if (safe)
12028  {
12029  /*
12030  * Check for keyword. We quote keywords except for unreserved ones.
12031  * (In some cases we could avoid quoting a col_name or type_func_name
12032  * keyword, but it seems much harder than it's worth to tell that.)
12033  *
12034  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12035  * that's fine, since we already know we have all-lower-case.
12036  */
12037  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12038 
12039  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12040  safe = false;
12041  }
12042 
12043  if (safe)
12044  return ident; /* no change needed */
12045 
12046  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12047 
12048  optr = result;
12049  *optr++ = '"';
12050  for (ptr = ident; *ptr; ptr++)
12051  {
12052  char ch = *ptr;
12053 
12054  if (ch == '"')
12055  *optr++ = '"';
12056  *optr++ = ch;
12057  }
12058  *optr++ = '"';
12059  *optr = '\0';
12060 
12061  return result;
12062 }
12063 
12064 /*
12065  * quote_qualified_identifier - Quote a possibly-qualified identifier
12066  *
12067  * Return a name of the form qualifier.ident, or just ident if qualifier
12068  * is NULL, quoting each component if necessary. The result is palloc'd.
12069  */
12070 char *
12071 quote_qualified_identifier(const char *qualifier,
12072  const char *ident)
12073 {
12075 
12076  initStringInfo(&buf);
12077  if (qualifier)
12078  appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
12080  return buf.data;
12081 }
12082 
12083 /*
12084  * get_relation_name
12085  * Get the unqualified name of a relation specified by OID
12086  *
12087  * This differs from the underlying get_rel_name() function in that it will
12088  * throw error instead of silently returning NULL if the OID is bad.
12089  */
12090 static char *
12092 {
12093  char *relname = get_rel_name(relid);
12094 
12095  if (!relname)
12096  elog(ERROR, "cache lookup failed for relation %u", relid);
12097  return relname;
12098 }
12099 
12100 /*
12101  * generate_relation_name
12102  * Compute the name to display for a relation specified by OID
12103  *
12104  * The result includes all necessary quoting and schema-prefixing.
12105  *
12106  * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
12107  * We will forcibly qualify the relation name if it equals any CTE name
12108  * visible in the namespace list.
12109  */
12110 static char *
12111 generate_relation_name(Oid relid, List *namespaces)
12112 {
12113  HeapTuple tp;
12114  Form_pg_class reltup;
12115  bool need_qual;
12116  ListCell *nslist;
12117  char *relname;
12118  char *nspname;
12119  char *result;
12120 
12121  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12122  if (!HeapTupleIsValid(tp))
12123  elog(ERROR, "cache lookup failed for relation %u", relid);
12124  reltup = (Form_pg_class) GETSTRUCT(tp);
12125  relname = NameStr(reltup->relname);
12126 
12127  /* Check for conflicting CTE name */
12128  need_qual = false;
12129  foreach(nslist, namespaces)
12130  {
12131  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
12132  ListCell *ctlist;
12133 
12134  foreach(ctlist, dpns->ctes)
12135  {
12136  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
12137 
12138  if (strcmp(cte->ctename, relname) == 0)
12139  {
12140  need_qual = true;
12141  break;
12142  }
12143  }
12144  if (need_qual)
12145  break;
12146  }
12147 
12148  /* Otherwise, qualify the name if not visible in search path */
12149  if (!need_qual)
12150  need_qual = !RelationIsVisible(relid);
12151 
12152  if (need_qual)
12153  nspname = get_namespace_name_or_temp(reltup->relnamespace);
12154  else
12155  nspname = NULL;
12156 
12157  result = quote_qualified_identifier(nspname, relname);
12158 
12159  ReleaseSysCache(tp);
12160 
12161  return result;
12162 }
12163 
12164 /*
12165  * generate_qualified_relation_name
12166  * Compute the name to display for a relation specified by OID
12167  *
12168  * As above, but unconditionally schema-qualify the name.
12169  */
12170 static char *
12172 {
12173  HeapTuple tp;
12174  Form_pg_class reltup;
12175  char *relname;
12176  char *nspname;
12177  char *result;
12178 
12179  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12180  if (!HeapTupleIsValid(tp))
12181  elog(ERROR, "cache lookup failed for relation %u", relid);
12182  reltup = (Form_pg_class) GETSTRUCT(tp);
12183  relname = NameStr(reltup->relname);
12184 
12185  nspname = get_namespace_name_or_temp(reltup->relnamespace);
12186  if (!nspname)
12187  elog(ERROR, "cache lookup failed for namespace %u",
12188  reltup->relnamespace);
12189 
12190  result = quote_qualified_identifier(nspname, relname);
12191 
12192  ReleaseSysCache(tp);
12193 
12194  return result;
12195 }
12196 
12197 /*
12198  * generate_function_name
12199  * Compute the name to display for a function specified by OID,
12200  * given that it is being called with the specified actual arg names and
12201  * types. (Those matter because of ambiguous-function resolution rules.)
12202  *
12203  * If we're dealing with a potentially variadic function (in practice, this
12204  * means a FuncExpr or Aggref, not some other way of calling a function), then
12205  * has_variadic must specify whether variadic arguments have been merged,
12206  * and *use_variadic_p will be set to indicate whether to print VARIADIC in
12207  * the output. For non-FuncExpr cases, has_variadic should be false and
12208  * use_variadic_p can be NULL.
12209  *
12210  * The result includes all necessary quoting and schema-prefixing.
12211  */
12212 static char *
12213 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
12214  bool has_variadic, bool *use_variadic_p,
12215  ParseExprKind special_exprkind)
12216 {
12217  char *result;
12218  HeapTuple proctup;
12219  Form_pg_proc procform;
12220  char *proname;
12221  bool use_variadic;
12222  char *nspname;
12223  FuncDetailCode p_result;
12224  Oid p_funcid;
12225  Oid p_rettype;
12226  bool p_retset;
12227  int p_nvargs;
12228  Oid p_vatype;
12229  Oid *p_true_typeids;
12230  bool force_qualify = false;
12231 
12232  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
12233  if (!HeapTupleIsValid(proctup))
12234  elog(ERROR, "cache lookup failed for function %u", funcid);
12235  procform = (Form_pg_proc) GETSTRUCT(proctup);
12236  proname = NameStr(procform->proname);
12237 
12238  /*
12239  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
12240  * qualification in some special cases.
12241  */
12242  if (special_exprkind == EXPR_KIND_GROUP_BY)
12243  {
12244  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
12245  force_qualify = true;
12246  }
12247 
12248  /*
12249  * Determine whether VARIADIC should be printed. We must do this first
12250  * since it affects the lookup rules in func_get_detail().
12251  *
12252  * We always print VARIADIC if the function has a merged variadic-array
12253  * argument. Note that this is always the case for functions taking a
12254  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
12255  * and printed the array elements as separate arguments, the call could
12256  * match a newer non-VARIADIC function.
12257  */
12258  if (use_variadic_p)
12259  {
12260  /* Parser should not have set funcvariadic unless fn is variadic */
12261  Assert(!has_variadic || OidIsValid(procform->provariadic));
12262  use_variadic = has_variadic;
12263  *use_variadic_p = use_variadic;
12264  }
12265  else
12266  {
12267  Assert(!has_variadic);
12268  use_variadic = false;
12269  }
12270 
12271  /*
12272  * The idea here is to schema-qualify only if the parser would fail to
12273  * resolve the correct function given the unqualified func name with the
12274  * specified argtypes and VARIADIC flag. But if we already decided to
12275  * force qualification, then we can skip the lookup and pretend we didn't
12276  * find it.
12277  */
12278  if (!force_qualify)
12280  NIL, argnames, nargs, argtypes,
12281  !use_variadic, true, false,
12282  &p_funcid, &p_rettype,
12283  &p_retset, &p_nvargs, &p_vatype,
12284  &p_true_typeids, NULL);
12285  else
12286  {
12287  p_result = FUNCDETAIL_NOTFOUND;
12288  p_funcid = InvalidOid;
12289  }
12290 
12291  if ((p_result == FUNCDETAIL_NORMAL ||
12292  p_result == FUNCDETAIL_AGGREGATE ||
12293  p_result == FUNCDETAIL_WINDOWFUNC) &&
12294  p_funcid == funcid)
12295  nspname = NULL;
12296  else
12297  nspname = get_namespace_name_or_temp(procform->pronamespace);
12298 
12299  result = quote_qualified_identifier(nspname, proname);
12300 
12301  ReleaseSysCache(proctup);
12302 
12303  return result;
12304 }
12305 
12306 /*
12307  * generate_operator_name
12308  * Compute the name to display for an operator specified by OID,
12309  * given that it is being called with the specified actual arg types.
12310  * (Arg types matter because of ambiguous-operator resolution rules.
12311  * Pass InvalidOid for unused arg of a unary operator.)
12312  *
12313  * The result includes all necessary quoting and schema-prefixing,
12314  * plus the OPERATOR() decoration needed to use a qualified operator name
12315  * in an expression.
12316  */
12317 static char *
12318 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
12319 {
12321  HeapTuple opertup;
12322  Form_pg_operator operform;
12323  char *oprname;
12324  char *nspname;
12325  Operator p_result;
12326 
12327  initStringInfo(&buf);
12328 
12329  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
12330  if (!HeapTupleIsValid(opertup))
12331  elog(ERROR, "cache lookup failed for operator %u", operid);
12332  operform = (Form_pg_operator) GETSTRUCT(opertup);
12333  oprname = NameStr(operform->oprname);
12334 
12335  /*
12336  * The idea here is to schema-qualify only if the parser would fail to
12337  * resolve the correct operator given the unqualified op name with the
12338  * specified argtypes.
12339  */
12340  switch (operform->oprkind)
12341  {
12342  case 'b':
12343  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
12344  true, -1);
12345  break;
12346  case 'l':
12347  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
12348  true, -1);
12349  break;
12350  default:
12351  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
12352  p_result = NULL; /* keep compiler quiet */
12353  break;
12354  }
12355 
12356  if (p_result != NULL && oprid(p_result) == operid)
12357  nspname = NULL;
12358  else
12359  {
12360  nspname = get_namespace_name_or_temp(operform->oprnamespace);
12361  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
12362  }
12363 
12364  appendStringInfoString(&buf, oprname);
12365 
12366  if (nspname)
12367  appendStringInfoChar(&buf, ')');
12368 
12369  if (p_result != NULL)
12370  ReleaseSysCache(p_result);
12371 
12372  ReleaseSysCache(opertup);
12373 
12374  return buf.data;
12375 }
12376 
12377 /*
12378  * generate_operator_clause --- generate a binary-operator WHERE clause
12379  *
12380  * This is used for internally-generated-and-executed SQL queries, where
12381  * precision is essential and readability is secondary. The basic
12382  * requirement is to append "leftop op rightop" to buf, where leftop and
12383  * rightop are given as strings and are assumed to yield types leftoptype
12384  * and rightoptype; the operator is identified by OID. The complexity
12385  * comes from needing to be sure that the parser will select the desired
12386  * operator when the query is parsed. We always name the operator using
12387  * OPERATOR(schema.op) syntax, so as to avoid search-path uncertainties.
12388  * We have to emit casts too, if either input isn't already the input type
12389  * of the operator; else we are at the mercy of the parser's heuristics for
12390  * ambiguous-operator resolution. The caller must ensure that leftop and
12391  * rightop are suitable arguments for a cast operation; it's best to insert
12392  * parentheses if they aren't just variables or parameters.
12393  */
12394 void
12396  const char *leftop, Oid leftoptype,
12397  Oid opoid,
12398  const char *rightop, Oid rightoptype)
12399 {
12400  HeapTuple opertup;
12401  Form_pg_operator operform;
12402  char *oprname;
12403  char *nspname;
12404 
12405  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
12406  if (!HeapTupleIsValid(opertup))
12407  elog(ERROR, "cache lookup failed for operator %u", opoid);
12408  operform = (Form_pg_operator) GETSTRUCT(opertup);
12409  Assert(operform->oprkind == 'b');
12410  oprname = NameStr(operform->oprname);
12411 
12412  nspname = get_namespace_name(operform->oprnamespace);
12413 
12414  appendStringInfoString(buf, leftop);
12415  if (leftoptype != operform->oprleft)
12416  add_cast_to(buf, operform->oprleft);
12417  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
12418  appendStringInfoString(buf, oprname);
12419  appendStringInfo(buf, ") %s", rightop);
12420  if (rightoptype != operform->oprright)
12421  add_cast_to(buf, operform->oprright);
12422 
12423  ReleaseSysCache(opertup);
12424 }
12425 
12426 /*
12427  * Add a cast specification to buf. We spell out the type name the hard way,
12428  * intentionally not using format_type_be(). This is to avoid corner cases
12429  * for CHARACTER, BIT, and perhaps other types, where specifying the type
12430  * using SQL-standard syntax results in undesirable data truncation. By
12431  * doing it this way we can be certain that the cast will have default (-1)
12432  * target typmod.
12433  */
12434 static void
12436 {
12437  HeapTuple typetup;
12438  Form_pg_type typform;
12439  char *typname;
12440  char *nspname;
12441 
12442  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
12443  if (!HeapTupleIsValid(typetup))
12444  elog(ERROR, "cache lookup failed for type %u", typid);
12445  typform = (Form_pg_type) GETSTRUCT(typetup);
12446 
12447  typname = NameStr(typform->typname);
12448  nspname = get_namespace_name_or_temp(typform->typnamespace);
12449 
12450  appendStringInfo(buf, "::%s.%s",
12452 
12453  ReleaseSysCache(typetup);
12454 }
12455 
12456 /*
12457  * generate_qualified_type_name
12458  * Compute the name to display for a type specified by OID
12459  *
12460  * This is different from format_type_be() in that we unconditionally
12461  * schema-qualify the name. That also means no special syntax for
12462  * SQL-standard type names ... although in current usage, this should
12463  * only get used for domains, so such cases wouldn't occur anyway.
12464  */
12465 static char *
12467 {
12468  HeapTuple tp;
12469  Form_pg_type typtup;
12470  char *typname;
12471  char *nspname;
12472  char *result;
12473 
12474  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
12475  if (!HeapTupleIsValid(tp))
12476  elog(ERROR, "cache lookup failed for type %u", typid);
12477  typtup = (Form_pg_type) GETSTRUCT(tp);
12478  typname = NameStr(typtup->typname);
12479 
12480  nspname = get_namespace_name_or_temp(typtup->typnamespace);
12481  if (!nspname)
12482  elog(ERROR, "cache lookup failed for namespace %u",
12483  typtup->typnamespace);
12484 
12485  result = quote_qualified_identifier(nspname, typname);
12486 
12487  ReleaseSysCache(tp);
12488 
12489  return result;
12490 }
12491 
12492 /*
12493  * generate_collation_name
12494  * Compute the name to display for a collation specified by OID
12495  *
12496  * The result includes all necessary quoting and schema-prefixing.
12497  */
12498 char *
12500 {
12501  HeapTuple tp;
12502  Form_pg_collation colltup;
12503  char *collname;
12504  char *nspname;
12505  char *result;
12506 
12507  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
12508  if (!HeapTupleIsValid(tp))
12509  elog(ERROR, "cache lookup failed for collation %u", collid);
12510  colltup = (Form_pg_collation) GETSTRUCT(tp);
12511  collname = NameStr(colltup->collname);
12512 
12513  if (!CollationIsVisible(collid))
12514  nspname = get_namespace_name_or_temp(colltup->collnamespace);
12515  else
12516  nspname = NULL;
12517 
12518  result = quote_qualified_identifier(nspname, collname);
12519 
12520  ReleaseSysCache(tp);
12521 
12522  return result;
12523 }
12524 
12525 /*
12526  * Given a C string, produce a TEXT datum.
12527  *
12528  * We assume that the input was palloc'd and may be freed.
12529  */
12530 static text *
12532 {
12533  text *result;
12534 
12535  result = cstring_to_text(str);
12536  pfree(str);
12537  return result;
12538 }
12539 
12540 /*
12541  * Generate a C string representing a relation options from text[] datum.
12542  */
12543 static void
12545 {
12546  Datum *options;
12547  int noptions;
12548  int i;
12549 
12550  deconstruct_array_builtin(DatumGetArrayTypeP(reloptions), TEXTOID,
12551  &options, NULL, &noptions);
12552 
12553  for (i = 0; i < noptions; i++)
12554  {
12555  char *option = TextDatumGetCString(options[i]);
12556  char *name;
12557  char *separator;
12558  char *value;
12559 
12560  /*
12561  * Each array element should have the form name=value. If the "=" is
12562  * missing for some reason, treat it like an empty value.
12563  */
12564  name = option;
12565  separator = strchr(option, '=');
12566  if (separator)
12567  {
12568  *separator = '\0';
12569  value = separator + 1;
12570  }
12571  else
12572  value = "";
12573 
12574  if (i > 0)
12575  appendStringInfoString(buf, ", ");
12577 
12578  /*
12579  * In general we need to quote the value; but to avoid unnecessary
12580  * clutter, do not quote if it is an identifier that would not need
12581  * quoting. (We could also allow numbers, but that is a bit trickier
12582  * than it looks --- for example, are leading zeroes significant? We
12583  * don't want to assume very much here about what custom reloptions
12584  * might mean.)
12585  */
12586  if (quote_identifier(value) == value)
12588  else
12590 
12591  pfree(option);
12592  }
12593 }
12594 
12595 /*
12596  * Generate a C string representing a relation's reloptions, or NULL if none.
12597  */
12598 static char *
12600 {
12601  char *result = NULL;
12602  HeapTuple tuple;
12603  Datum reloptions;
12604  bool isnull;
12605 
12606  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12607  if (!HeapTupleIsValid(tuple))
12608  elog(ERROR, "cache lookup failed for relation %u", relid);
12609 
12610  reloptions = SysCacheGetAttr(RELOID, tuple,
12611  Anum_pg_class_reloptions, &isnull);
12612  if (!isnull)
12613  {
12615 
12616  initStringInfo(&buf);
12617  get_reloptions(&buf, reloptions);
12618 
12619  result = buf.data;
12620  }
12621 
12622  ReleaseSysCache(tuple);
12623 
12624  return result;
12625 }
12626 
12627 /*
12628  * get_range_partbound_string
12629  * A C string representation of one range partition bound
12630  */
12631 char *
12633 {
12634  deparse_context context;
12636  ListCell *cell;
12637  char *sep;
12638 
12639  memset(&context, 0, sizeof(deparse_context));
12640  context.buf = buf;
12641 
12642  appendStringInfoChar(buf, '(');
12643  sep = "";
12644  foreach(cell, bound_datums)
12645  {
12646  PartitionRangeDatum *datum =
12648 
12650  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
12651  appendStringInfoString(buf, "MINVALUE");
12652  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
12653  appendStringInfoString(buf, "MAXVALUE");
12654  else
12655  {
12656  Const *val = castNode(Const, datum->value);
12657 
12658  get_const_expr(val, &context, -1);
12659  }
12660  sep = ", ";
12661  }
12662  appendStringInfoChar(buf, ')');
12663 
12664  return buf->data;
12665 }
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
#define ARR_LBOUND(a)
Definition: array.h:296
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5331
Datum array_ref(ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:3139
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3678
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5401
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1472
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
#define bms_is_empty(a)
Definition: bitmapset.h:118
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:733
uint16 bits16
Definition: c.h:501
NameData * Name
Definition: c.h:731
signed short int16
Definition: c.h:480
signed int int32
Definition: c.h:481
#define Max(x, y)
Definition: c.h:985
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1150
unsigned int Index
Definition: c.h:601
float float4
Definition: c.h:616
#define OidIsValid(objectId)
Definition: c.h:762
Oid collid
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
#define palloc0_array(type, count)
Definition: fe_memutils.h:65
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_NAME(x)
Definition: fmgr.h:363
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:362
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int get_func_trftypes(HeapTuple procTup, Oid **p_trftypes)
Definition: funcapi.c:1467
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1371
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:543
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
int GetConfigOptionFlags(const char *name, bool missing_ok)
Definition: guc.c:4395
#define GUC_LIST_QUOTE
Definition: guc.h:211
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:455
#define HASH_STRINGS
Definition: hsearch.h:96
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
#define stmt
Definition: indent_codes.h:59
#define ident
Definition: indent_codes.h:47
#define funcname
Definition: indent_codes.h:69
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2338
long val
Definition: informix.c:664
static struct @150 value
int a
Definition: isn.c:69
int j
Definition: isn.c:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_first(List *list)
Definition: list.c:943
void list_free(List *list)
Definition: list.c:1546
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1613
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
List * lcons(void *datum, List *list)
Definition: list.c:495
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
@ LockWaitSkip
Definition: lockoptions.h:41
@ LockWaitError
Definition: lockoptions.h:43
@ LCS_FORUPDATE
Definition: lockoptions.h:27
@ LCS_NONE
Definition: lockoptions.h:23
@ LCS_FORSHARE
Definition: lockoptions.h:25
@ LCS_FORKEYSHARE
Definition: lockoptions.h:24
@ LCS_FORNOKEYUPDATE
Definition: lockoptions.h:26
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1139
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1190
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3346
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2611
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3322
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2863
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:970
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1981
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:3012
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1906
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:1081
Oid get_rel_tablespace(Oid relid)
Definition: lsyscache.c:2032
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2687
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2788
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition: lsyscache.c:943
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:389
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
char * pstrdup(const char *in)
Definition: mcxt.c:1683
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc0(Size size)
Definition: mcxt.c:1334
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131
void * palloc(Size size)
Definition: mcxt.c:1304
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2392
bool RelationIsVisible(Oid relid)
Definition: namespace.c:898
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:2139
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3539
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:524
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:284
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:788
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:672
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:375
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:374
@ ONCONFLICT_NOTHING
Definition: nodes.h:408
@ CMD_MERGE
Definition: nodes.h:259
@ CMD_UTILITY
Definition: nodes.h:260
@ CMD_INSERT
Definition: nodes.h:257
@ CMD_DELETE
Definition: nodes.h:258
@ CMD_UPDATE
Definition: nodes.h:256
@ CMD_SELECT
Definition: nodes.h:255
@ CMD_NOTHING
Definition: nodes.h:262
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:421
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
@ JOIN_FULL
Definition: nodes.h:285
@ JOIN_INNER
Definition: nodes.h:283
@ JOIN_RIGHT
Definition: nodes.h:286
@ JOIN_LEFT
Definition: nodes.h:284
#define repalloc0_array(pointer, type, oldcount, count)
Definition: palloc.h:109
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1908
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, bool include_out_arguments, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1394
FuncDetailCode
Definition: parse_func.h:23
@ FUNCDETAIL_NORMAL
Definition: parse_func.h:26
@ FUNCDETAIL_WINDOWFUNC
Definition: parse_func.h:29
@ FUNCDETAIL_NOTFOUND
Definition: parse_func.h:24
@ FUNCDETAIL_AGGREGATE
Definition: parse_func.h:28
ParseExprKind
Definition: parse_node.h:39
@ EXPR_KIND_NONE
Definition: parse_node.h:40
@ EXPR_KIND_GROUP_BY
Definition: parse_node.h:59
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:518
Oid oprid(Operator op)
Definition: parse_oper.c:238
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:370
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, int location, bool include_dropped, List **colnames, List **colvars)
#define FRAMEOPTION_END_CURRENT_ROW
Definition: parsenodes.h:590
#define FRAMEOPTION_END_OFFSET
Definition: parsenodes.h:601
#define FRAMEOPTION_EXCLUDE_CURRENT_ROW
Definition: parsenodes.h:595
@ GROUPING_SET_CUBE
Definition: parsenodes.h:1460
@ GROUPING_SET_SIMPLE
Definition: parsenodes.h:1458
@ GROUPING_SET_ROLLUP
Definition: parsenodes.h:1459
@ GROUPING_SET_SETS
Definition: parsenodes.h:1461
@ GROUPING_SET_EMPTY
Definition: parsenodes.h:1457
#define FKCONSTR_ACTION_RESTRICT
Definition: parsenodes.h:2570
@ SETOP_INTERSECT
Definition: parsenodes.h:1963
@ SETOP_UNION
Definition: parsenodes.h:1962
@ SETOP_EXCEPT
Definition: parsenodes.h:1964
#define FRAMEOPTION_END_OFFSET_PRECEDING
Definition: parsenodes.h:592
#define FRAMEOPTION_START_UNBOUNDED_PRECEDING
Definition: parsenodes.h:585
#define GetCTETargetList(cte)
Definition: parsenodes.h:1665
#define FKCONSTR_ACTION_SETDEFAULT
Definition: parsenodes.h:2573
@ PARTITION_STRATEGY_HASH
Definition: parsenodes.h:870
@ PARTITION_STRATEGY_LIST
Definition: parsenodes.h:868
@ PARTITION_STRATEGY_RANGE
Definition: parsenodes.h:869
#define FRAMEOPTION_START_CURRENT_ROW
Definition: parsenodes.h:589
#define FKCONSTR_MATCH_SIMPLE
Definition: parsenodes.h:2578
@ RTE_JOIN
Definition: parsenodes.h:1013
@ RTE_CTE
Definition: parsenodes.h:1017
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1018
@ RTE_VALUES
Definition: parsenodes.h:1016
@ RTE_SUBQUERY
Definition: parsenodes.h:1012
@ RTE_RESULT
Definition: parsenodes.h:1019
@ RTE_FUNCTION
Definition: parsenodes.h:1014
@ RTE_TABLEFUNC
Definition: parsenodes.h:1015
@ RTE_RELATION
Definition: parsenodes.h:1011
#define FRAMEOPTION_START_OFFSET
Definition: parsenodes.h:599
@ PARTITION_RANGE_DATUM_MAXVALUE
Definition: parsenodes.h:922
@ PARTITION_RANGE_DATUM_MINVALUE
Definition: parsenodes.h:920
#define FKCONSTR_MATCH_PARTIAL
Definition: parsenodes.h:2577
#define FRAMEOPTION_END_OFFSET_FOLLOWING
Definition: parsenodes.h:594
#define FRAMEOPTION_EXCLUDE_TIES
Definition: parsenodes.h:597
#define FRAMEOPTION_RANGE
Definition: parsenodes.h:581
#define FRAMEOPTION_EXCLUDE_GROUP
Definition: parsenodes.h:596
#define FKCONSTR_ACTION_CASCADE
Definition: parsenodes.h:2571
#define FRAMEOPTION_GROUPS
Definition: parsenodes.h:583
#define FRAMEOPTION_BETWEEN
Definition: parsenodes.h:584
#define FKCONSTR_ACTION_SETNULL
Definition: parsenodes.h:2572
#define FRAMEOPTION_END_UNBOUNDED_FOLLOWING
Definition: parsenodes.h:588
#define FRAMEOPTION_START_OFFSET_PRECEDING
Definition: parsenodes.h:591
#define FRAMEOPTION_START_OFFSET_FOLLOWING
Definition: parsenodes.h:593
#define FRAMEOPTION_NONDEFAULT
Definition: parsenodes.h:580
#define FKCONSTR_MATCH_FULL
Definition: parsenodes.h:2576
#define FKCONSTR_ACTION_NOACTION
Definition: parsenodes.h:2569
#define FRAMEOPTION_ROWS
Definition: parsenodes.h:582
@ CTEMaterializeNever
Definition: parsenodes.h:1600
@ CTEMaterializeAlways
Definition: parsenodes.h:1599
@ CTEMaterializeDefault
Definition: parsenodes.h:1598
PGDLLIMPORT bool standard_conforming_strings
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Expr * get_partition_qual_relid(Oid relid)
Definition: partcache.c:299
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
void * arg
static char format
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
#define NAMEDATALEN
#define FUNC_MAX_ARGS
AttrNumber extractNotNullColumn(HeapTuple constrTup)
FormData_pg_constraint * Form_pg_constraint
while(p+4<=pend)
int32 encoding
Definition: pg_database.h:41
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:72
FormData_pg_index * Form_pg_index
Definition: pg_index.h:70
#define lfirst(lc)
Definition: pg_list.h:172
#define llast(l)
Definition: pg_list.h:198
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define lsecond_node(type, l)
Definition: pg_list.h:186
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
#define lfirst_int(lc)
Definition: pg_list.h:173
#define lthird(l)
Definition: pg_list.h:188
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial_int(l)
Definition: pg_list.h:179
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:438
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
#define for_each_from(cell, lst, N)
Definition: pg_list.h:414
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:575
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define lfourth(l)
Definition: pg_list.h:193
#define linitial_oid(l)
Definition: pg_list.h:180
#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5)
Definition: pg_list.h:588
#define lfirst_oid(lc)
Definition: pg_list.h:174
#define list_make2(x1, x2)
Definition: pg_list.h:214
static int list_cell_number(const List *l, const ListCell *c)
Definition: pg_list.h:333
#define lthird_node(type, l)
Definition: pg_list.h:191
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
FormData_pg_partitioned_table * Form_pg_partitioned_table
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
NameData proname
Definition: pg_proc.h:35
static size_t noptions
static char ** options
#define plan(x)
Definition: pg_regress.c:162
FormData_pg_statistic_ext * Form_pg_statistic_ext
static char * buf
Definition: pg_test_fsync.c:73
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:80
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
#define innerPlan(node)
Definition: plannodes.h:181
#define outerPlan(node)
Definition: plannodes.h:182
#define sprintf
Definition: port.h:240
void check_stack_depth(void)
Definition: postgres.c:3531
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Name DatumGetName(Datum X)
Definition: postgres.h:360
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static char DatumGetChar(Datum X)
Definition: postgres.h:112
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
e
Definition: preproc-init.c:82
char string[11]
Definition: preproc-type.c:52
@ IS_NOT_TRUE
Definition: primnodes.h:1739
@ IS_NOT_FALSE
Definition: primnodes.h:1739
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1739
@ IS_TRUE
Definition: primnodes.h:1739
@ IS_UNKNOWN
Definition: primnodes.h:1739
@ IS_FALSE
Definition: primnodes.h:1739
@ ARRAY_SUBLINK
Definition: primnodes.h:959
@ ANY_SUBLINK
Definition: primnodes.h:955
@ MULTIEXPR_SUBLINK
Definition: primnodes.h:958
@ CTE_SUBLINK
Definition: primnodes.h:960
@ EXPR_SUBLINK
Definition: primnodes.h:957
@ ROWCOMPARE_SUBLINK
Definition: primnodes.h:956
@ ALL_SUBLINK
Definition: primnodes.h:954
@ EXISTS_SUBLINK
Definition: primnodes.h:953
@ JS_FORMAT_JSONB
Definition: primnodes.h:1596
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1594
@ JS_FORMAT_JSON
Definition: primnodes.h:1595
@ IS_LEAST
Definition: primnodes.h:1459
@ IS_GREATEST
Definition: primnodes.h:1458
BoolExprType
Definition: primnodes.h:886
@ AND_EXPR
Definition: primnodes.h:887
@ OR_EXPR
Definition: primnodes.h:887
@ NOT_EXPR
Definition: primnodes.h:887
@ JS_ENC_DEFAULT
Definition: primnodes.h:1582
@ JS_ENC_UTF32
Definition: primnodes.h:1585
@ JS_ENC_UTF16
Definition: primnodes.h:1584
@ XMLOPTION_DOCUMENT
Definition: primnodes.h:1548
@ SVFOP_CURRENT_CATALOG
Definition: primnodes.h:1505
@ SVFOP_LOCALTIME_N
Definition: primnodes.h:1498
@ SVFOP_CURRENT_TIMESTAMP
Definition: primnodes.h:1495
@ SVFOP_LOCALTIME
Definition: primnodes.h:1497
@ SVFOP_CURRENT_TIMESTAMP_N
Definition: primnodes.h:1496
@ SVFOP_CURRENT_ROLE
Definition: primnodes.h:1501
@ SVFOP_USER
Definition: primnodes.h:1503
@ SVFOP_CURRENT_SCHEMA
Definition: primnodes.h:1506
@ SVFOP_LOCALTIMESTAMP_N
Definition: primnodes.h:1500
@ SVFOP_CURRENT_DATE
Definition: primnodes.h:1492
@ SVFOP_CURRENT_TIME_N
Definition: primnodes.h:1494
@ SVFOP_CURRENT_TIME
Definition: primnodes.h:1493
@ SVFOP_LOCALTIMESTAMP
Definition: primnodes.h:1499
@ SVFOP_CURRENT_USER
Definition: primnodes.h:1502
@ SVFOP_SESSION_USER
Definition: primnodes.h:1504
@ PARAM_MULTIEXPR
Definition: primnodes.h:356
@ PARAM_EXTERN
Definition: primnodes.h:353
@ PARAM_EXEC
Definition: primnodes.h:354
@ IS_DOCUMENT
Definition: primnodes.h:1543
@ IS_XMLFOREST
Definition: primnodes.h:1538
@ IS_XMLCONCAT
Definition: primnodes.h:1536
@ IS_XMLPI
Definition: primnodes.h:1540
@ IS_XMLPARSE
Definition: primnodes.h:1539
@ IS_XMLSERIALIZE
Definition: primnodes.h:1542
@ IS_XMLROOT
Definition: primnodes.h:1541
@ IS_XMLELEMENT
Definition: primnodes.h:1537
CoercionForm
Definition: primnodes.h:689
@ COERCE_SQL_SYNTAX
Definition: primnodes.h:693
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:692
@ COERCE_EXPLICIT_CAST
Definition: primnodes.h:691
@ COERCE_EXPLICIT_CALL
Definition: primnodes.h:690
@ OVERRIDING_SYSTEM_VALUE
Definition: primnodes.h:29
@ OVERRIDING_USER_VALUE
Definition: primnodes.h:28
@ IS_NULL
Definition: primnodes.h:1715
@ IS_NOT_NULL
Definition: primnodes.h:1715
@ JS_TYPE_ARRAY
Definition: primnodes.h:1676
@ JS_TYPE_OBJECT
Definition: primnodes.h:1675
@ JS_TYPE_SCALAR
Definition: primnodes.h:1677
#define OUTER_VAR
Definition: primnodes.h:223
@ JSCTOR_JSON_SERIALIZE
Definition: primnodes.h:1648
@ JSCTOR_JSON_ARRAYAGG
Definition: primnodes.h:1645
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1646
@ JSCTOR_JSON_OBJECT
Definition: primnodes.h:1642
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1647
@ JSCTOR_JSON_ARRAY
Definition: primnodes.h:1643
@ JSCTOR_JSON_OBJECTAGG
Definition: primnodes.h:1644
#define INNER_VAR
Definition: primnodes.h:222
#define INDEX_VAR
Definition: primnodes.h:224
void * stringToNode(const char *str)
Definition: read.c:90
static SPIPlanPtr splan
Definition: regress.c:269
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
Query * getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
Definition: rewriteManip.c:998
#define ViewSelectRuleName
Datum pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:857
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags, int wrapColumn)
Definition: ruleutils.c:5346
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:8561
static bool looks_like_function(Node *node)
Definition: ruleutils.c:9917
Datum pg_get_partition_constraintdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2065
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4943
Datum pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
Definition: ruleutils.c:687
static void set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
Definition: ruleutils.c:4307
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:8507
Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1167
static void set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
Definition: ruleutils.c:4142
static Plan * find_recursive_union(deparse_namespace *dpns, WorkTableScan *wtscan)
Definition: ruleutils.c:5043
static text * string_to_text(char *str)
Definition: ruleutils.c:12531
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5509
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3599
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:86
Datum pg_get_viewdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:649
static char * make_colname_unique(char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
Definition: ruleutils.c:4817
static const char * get_simple_binary_op_name(OpExpr *expr)
Definition: ruleutils.c:8254
static void get_json_agg_constructor(JsonConstructorExpr *ctor, deparse_context *context, const char *funcname, bool is_json_objectagg)
Definition: ruleutils.c:10946
Datum pg_get_constraintdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2115
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3970
static void print_function_trftypes(StringInfo buf, HeapTuple proctup)
Definition: ruleutils.c:3412
void(* rsv_callback)(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:309
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
char * pg_get_constraintdef_command(Oid constraintId)
Definition: ruleutils.c:2153
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
static bool is_input_argument(int nth, const char *argmodes)
Definition: ruleutils.c:3400
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, bool colNamesVisible, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5431
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:11775
Datum pg_get_functiondef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2881
Datum pg_get_function_result(PG_FUNCTION_ARGS)
Definition: ruleutils.c:3184
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11987
Datum pg_get_indexdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1147
static void get_sublink_expr(SubLink *sublink, deparse_context *context)
Definition: ruleutils.c:10998
static void get_rte_alias(RangeTblEntry *rte, int varno, bool use_as, deparse_context *context)
Definition: ruleutils.c:11613
#define only_marker(rte)
Definition: ruleutils.c:520
Datum pg_get_function_arg_default(PG_FUNCTION_ARGS)
Definition: ruleutils.c:3440
char * generate_opclass_name(Oid opclass)
Definition: ruleutils.c:11857
static void get_parameter(Param *param, deparse_context *context)
Definition: ruleutils.c:8141
Datum pg_get_statisticsobjdef_expressions(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1807
Datum pg_get_ruledef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:530
#define PRETTYFLAG_INDENT
Definition: ruleutils.c:90
List * deparse_context_for(const char *aliasname, Oid relid)
Definition: ruleutils.c:3659
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:11684
Datum pg_get_statisticsobjdef_columns(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1606
Datum pg_get_statisticsobjdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1577
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:10971
static bool colname_is_unique(const char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
Definition: ruleutils.c:4763
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:11724
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:11228
static void get_basic_select_query(Query *query, deparse_context *context, TupleDesc resultDesc, bool colNamesVisible)
Definition: ruleutils.c:5892
static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Definition: ruleutils.c:10339
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc, bool colNamesVisible)
Definition: ruleutils.c:6026
Datum pg_get_partkeydef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:1878
static char * generate_qualified_relation_name(Oid relid)
Definition: ruleutils.c:12171
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:4035
#define PRETTY_INDENT(context)
Definition: ruleutils.c:103
#define PRETTYFLAG_PAREN
Definition: ruleutils.c:89
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:6353
static char * pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, bool attrsOnly, bool keysOnly, bool showTblSpc, bool inherits, int prettyFlags, bool missing_ok)
Definition: ruleutils.c:1239
static char * pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags, bool missing_ok)
Definition: ruleutils.c:2162
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9894
static void expand_colnames_array_to(deparse_columns *colinfo, int n)
Definition: ruleutils.c:4856
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:12435
static void get_special_variable(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:7496
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc, bool colNamesVisible)
Definition: ruleutils.c:5691
static void get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context, const char *funcname, const char *options, bool is_json_objectagg)
Definition: ruleutils.c:10246
static void get_rule_list_toplevel(List *lst, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9864
char * pg_get_statisticsobjdef_string(Oid statextid)
Definition: ruleutils.c:1596
static char * pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
Definition: ruleutils.c:1623
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:296
static void get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:10850
static const char *const query_getrulebyoid
Definition: ruleutils.c:318
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:12213
static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
Definition: ruleutils.c:11957
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:5141
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:12499
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8580
bool quote_all_identifiers
Definition: ruleutils.c:323
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:10081
static int decompile_column_index_array(Datum column_index_array, Oid relId, StringInfo buf)
Definition: ruleutils.c:2577
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:10785
static void get_delete_query_def(Query *query, deparse_context *context, bool colNamesVisible)
Definition: ruleutils.c:7038
static SPIPlanPtr plan_getrulebyoid
Definition: ruleutils.c:317
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3626
Datum pg_get_ruledef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:548
static void print_function_sqlbody(StringInfo buf, HeapTuple proctup)
Definition: ruleutils.c:3510
static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
Definition: ruleutils.c:4076
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6296
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3796
char * pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
Definition: ruleutils.c:2097
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12071
static char * pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
Definition: ruleutils.c:760
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:5120
static SPIPlanPtr plan_getviewrule
Definition: ruleutils.c:319
char * pg_get_partkeydef_columns(Oid relid, bool pretty)
Definition: ruleutils.c:1893
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:99
static char * flatten_reloptions(Oid relid)
Definition: ruleutils.c:12599
static text * pg_get_expr_worker(text *expr, Oid relid, int prettyFlags)
Definition: ruleutils.c:2664
List * set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
Definition: ruleutils.c:3773
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:11879
static void get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:10219
#define PRETTY_PAREN(context)
Definition: ruleutils.c:102
Datum pg_get_triggerdef(PG_FUNCTION_ARGS)
Definition: ruleutils.c:843
Datum pg_get_function_sqlbody(PG_FUNCTION_ARGS)
Definition: ruleutils.c:3564
Datum pg_get_expr(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2629
static char * generate_qualified_type_name(Oid typid)
Definition: ruleutils.c:12466
char * pg_get_indexdef_columns_extended(Oid indexrelid, bits16 flags)
Definition: ruleutils.c:1218
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:7217
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:12091
Datum pg_get_expr_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2646
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:6471
static void get_rule_windowspec(WindowClause *wc, List *targetList, deparse_context *context)
Definition: ruleutils.c:6503
static void get_json_returning(JsonReturning *returning, StringInfo buf, bool json_format_by_default)
Definition: ruleutils.c:10830
Datum pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:732
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:8031
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6413
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:5090
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:7625
static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
Definition: ruleutils.c:4503
Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2132
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3825
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6886
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8612
Datum pg_get_viewdef_ext(PG_FUNCTION_ARGS)
Definition: ruleutils.c:668
static char * pg_get_partkeydef_worker(Oid relid, int prettyFlags, bool attrsOnly, bool missing_ok)
Definition: ruleutils.c:1906
static void get_oper_expr(OpExpr *expr, deparse_context *context)
Definition: ruleutils.c:9945
char * pg_get_querydef(Query *query, bool pretty)
Definition: ruleutils.c:1557
Datum pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
Definition: ruleutils.c:3159
static char * pg_get_triggerdef_worker(Oid trigid, bool pretty)
Definition: ruleutils.c:872
#define GET_PRETTY_FLAGS(pretty)
Definition: ruleutils.c:94
static void get_reloptions(StringInfo buf, Datum reloptions)
Definition: ruleutils.c:12544
static void get_func_expr(FuncExpr *expr, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9985
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:10655
void generate_operator_clause(StringInfo buf, const char *leftop, Oid leftoptype, Oid opoid, const char *rightop, Oid rightoptype)
Definition: ruleutils.c:12395
static void get_setop_query(Node *setOp, Query *query, deparse_context *context, TupleDesc resultDesc, bool colNamesVisible)
Definition: ruleutils.c:6162
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
Definition: ruleutils.c:5157
static const char *const query_getviewrule
Definition: ruleutils.c:320
static char * pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
Definition: ruleutils.c:567
static int print_function_arguments(StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults)
Definition: ruleutils.c:3252
static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, deparse_columns *colinfo)
Definition: ruleutils.c:4875
char * pg_get_indexdef_columns(Oid indexrelid, bool pretty)
Definition: ruleutils.c:1204
static void print_function_rettype(StringInfo buf, HeapTuple proctup)
Definition: ruleutils.c:3214
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5823
static void set_deparse_plan(deparse_namespace *dpns, Plan *plan)
Definition: ruleutils.c:4962
static void resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
Definition: ruleutils.c:7517
static void get_merge_query_def(Query *query, deparse_context *context, bool colNamesVisible)
Definition: ruleutils.c:7090
static void get_json_format(JsonFormat *format, StringInfo buf)
Definition: ruleutils.c:10805
static void get_insert_query_def(Query *query, deparse_context *context, bool colNamesVisible)
Definition: ruleutils.c:6612
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:11123
static void get_rule_expr_toplevel(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9846
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:10591
static void push_child_plan(deparse_namespace *dpns, Plan *plan, deparse_namespace *save_dpns)
Definition: ruleutils.c:5073
static void get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
Definition: ruleutils.c:10916
char * get_range_partbound_string(List *bound_datums)
Definition: ruleutils.c:12632
static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
Definition: ruleutils.c:8280
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5552
char * pg_get_indexdef_string(Oid indexrelid)
Definition: ruleutils.c:1194
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3704
static void get_update_query_def(Query *query, deparse_context *context, bool colNamesVisible)
Definition: ruleutils.c:6829
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:12111
static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
Definition: ruleutils.c:10235
static char * get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
Definition: ruleutils.c:7262
Datum pg_get_serial_sequence(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2787
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:12318
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:11322
Datum pg_get_function_arguments(PG_FUNCTION_ARGS)
Definition: ruleutils.c:3133
#define PRETTYFLAG_SCHEMA
Definition: ruleutils.c:91
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:11819
Datum pg_get_viewdef_name(PG_FUNCTION_ARGS)
Definition: ruleutils.c:707
Datum pg_get_userbyid(PG_FUNCTION_ARGS)
Definition: ruleutils.c:2749
static void get_agg_expr_helper(Aggref *aggref, deparse_context *context, Aggref *original_aggref, const char *funcname, const char *options, bool is_json_objectagg)
Definition: ruleutils.c:10093
#define RULE_INDEXDEF_PRETTY
Definition: ruleutils.h:24
#define RULE_INDEXDEF_KEYS_ONLY
Definition: ruleutils.h:25
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:836
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:794
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:1172
uint64 SPI_processed
Definition: spi.c:44
SPITupleTable * SPI_tuptable
Definition: spi.c:45
int SPI_connect(void)
Definition: spi.c:94
int SPI_finish(void)
Definition: spi.c:182
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:669
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:857
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:973
char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
Definition: spi.c:1217
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:1249
#define SPI_OK_CONNECT
Definition: spi.h:82
#define SPI_OK_FINISH
Definition: spi.h:83
#define SPI_OK_SELECT
Definition: spi.h:86
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:88
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
#define BTEqualStrategyNumber
Definition: stratnum.h:31
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:212
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Oid aggfnoid
Definition: primnodes.h:430
List * aggdistinct
Definition: primnodes.h:460
List * aggdirectargs
Definition: primnodes.h:451
List * args
Definition: primnodes.h:454
Expr * aggfilter
Definition: primnodes.h:463
List * aggorder
Definition: primnodes.h:457
char * aliasname
Definition: primnodes.h:50
List * colnames
Definition: primnodes.h:51
Index child_relid
Definition: pathnodes.h:2944
Index parent_relid
Definition: pathnodes.h:2943
int num_child_cols
Definition: pathnodes.h:2979
List * elements
Definition: primnodes.h:1336
BoolExprType boolop
Definition: primnodes.h:895
List * args
Definition: primnodes.h:896
BoolTestType booltesttype
Definition: primnodes.h:1746
Expr * arg
Definition: primnodes.h:1745
Expr * arg
Definition: primnodes.h:1269
Expr * defresult
Definition: primnodes.h:1271
List * args
Definition: primnodes.h:1270
List * args
Definition: primnodes.h:1448
Expr * arg
Definition: primnodes.h:1163
Oid resulttype
Definition: primnodes.h:1164
Expr * arg
Definition: primnodes.h:1235
CTEMaterialize ctematerialized
Definition: parsenodes.h:1639
Oid consttype
Definition: primnodes.h:298
char * cursor_name
Definition: primnodes.h:1851
AttrNumber fieldnum
Definition: primnodes.h:1085
Expr * arg
Definition: primnodes.h:1084
List * newvals
Definition: primnodes.h:1116
Node * quals
Definition: primnodes.h:2062
List * fromlist
Definition: primnodes.h:2061
Oid funcid
Definition: primnodes.h:706
List * args
Definition: primnodes.h:724
List * content
Definition: parsenodes.h:1468
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
Definition: dynahash.c:220
bool amcanorder
Definition: amapi.h:223
JsonReturning * returning
Definition: primnodes.h:1662
JsonConstructorType type
Definition: primnodes.h:1658
JsonFormatType format_type
Definition: primnodes.h:1607
JsonValueType item_type
Definition: primnodes.h:1689
JsonFormat * format
Definition: primnodes.h:1619
JsonFormat * format
Definition: primnodes.h:1637
Expr * raw_expr
Definition: primnodes.h:1635
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1474
MinMaxOp op
Definition: primnodes.h:1472
Expr * arg
Definition: primnodes.h:747
Var * paramval
Definition: plannodes.h:817
List * nestParams
Definition: plannodes.h:808
Definition: nodes.h:129
NullTestType nulltesttype
Definition: primnodes.h:1722
Expr * arg
Definition: primnodes.h:1721
List * arbiterElems
Definition: primnodes.h:2080
OnConflictAction action
Definition: primnodes.h:2077
List * onConflictSet
Definition: primnodes.h:2086
Node * onConflictWhere
Definition: primnodes.h:2087
Node * arbiterWhere
Definition: primnodes.h:2082
Oid opno
Definition: primnodes.h:774
List * args
Definition: primnodes.h:792
int paramid
Definition: primnodes.h:363
ParamKind paramkind
Definition: primnodes.h:362
PartitionRangeDatumKind kind
Definition: parsenodes.h:929
List * targetlist
Definition: plannodes.h:152
List * appendRelations
Definition: plannodes.h:80
List * subplans
Definition: plannodes.h:82
List * rtable
Definition: plannodes.h:72
List * rowMarks
Definition: parsenodes.h:216
bool groupDistinct
Definition: parsenodes.h:200
Node * limitCount
Definition: parsenodes.h:213
FromExpr * jointree
Definition: parsenodes.h:175
List * returningList
Definition: parsenodes.h:197
Node * setOperations
Definition: parsenodes.h:218
List * cteList
Definition: parsenodes.h:166
OnConflictExpr * onConflict
Definition: parsenodes.h:195
List * groupClause
Definition: parsenodes.h:199
Node * havingQual
Definition: parsenodes.h:204
List * rtable
Definition: parsenodes.h:168
Node * limitOffset
Definition: parsenodes.h:212
CmdType commandType
Definition: parsenodes.h:121
LimitOption limitOption
Definition: parsenodes.h:214
Node * utilityStmt
Definition: parsenodes.h:136
List * mergeActionList
Definition: parsenodes.h:178
List * windowClause
Definition: parsenodes.h:206
List * targetList
Definition: parsenodes.h:190
List * groupingSets
Definition: parsenodes.h:202
List * distinctClause
Definition: parsenodes.h:208
List * sortClause
Definition: parsenodes.h:210
char * ctename
Definition: parsenodes.h:1169
TableFunc * tablefunc
Definition: parsenodes.h:1159
Index ctelevelsup
Definition: parsenodes.h:1170
bool funcordinality
Definition: parsenodes.h:1154
struct TableSampleClause * tablesample
Definition: parsenodes.h:1081
Query * subquery
Definition: parsenodes.h:1086
Alias * eref
Definition: parsenodes.h:1205
List * joinrightcols
Definition: parsenodes.h:1136
List * values_lists
Definition: parsenodes.h:1164
List * joinaliasvars
Definition: parsenodes.h:1134
Alias * alias
Definition: parsenodes.h:1204
List * functions
Definition: parsenodes.h:1153
List * joinleftcols
Definition: parsenodes.h:1135
RTEKind rtekind
Definition: parsenodes.h:1030
char * relname
Definition: primnodes.h:82
Oid resulttype
Definition: primnodes.h:1141
Expr * arg
Definition: primnodes.h:1140
TupleDesc rd_att
Definition: rel.h:112
List * args
Definition: primnodes.h:1367
LockClauseStrength strength
Definition: parsenodes.h:1540
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1541
TupleDesc tupdesc
Definition: spi.h:25
HeapTuple * vals
Definition: spi.h:26
SQLValueFunctionOp op
Definition: primnodes.h:1512
SetOperation op
Definition: parsenodes.h:2039
Index tleSortGroupRef
Definition: parsenodes.h:1397
Definition: value.h:64
char * plan_name
Definition: primnodes.h:1028
List * args
Definition: primnodes.h:1047
bool useHashTable
Definition: primnodes.h:1035
List * parParam
Definition: primnodes.h:1046
Expr * refassgnexpr
Definition: primnodes.h:659
List * refupperindexpr
Definition: primnodes.h:649
Expr * refexpr
Definition: primnodes.h:657
List * reflowerindexpr
Definition: primnodes.h:655
Node * docexpr
Definition: primnodes.h:111
Node * rowexpr
Definition: primnodes.h:113
List * colexprs
Definition: primnodes.h:123
Expr * expr
Definition: primnodes.h:1943
AttrNumber resno
Definition: primnodes.h:1945
Definition: primnodes.h:234
AttrNumber varattno
Definition: primnodes.h:246
int varno
Definition: primnodes.h:241
Index varlevelsup
Definition: primnodes.h:266
Node * startOffset
Definition: parsenodes.h:1505
List * partitionClause
Definition: parsenodes.h:1501
Node * endOffset
Definition: parsenodes.h:1506
List * orderClause
Definition: parsenodes.h:1503
List * args
Definition: primnodes.h:561
Index winref
Definition: primnodes.h:565
Expr * aggfilter
Definition: primnodes.h:563
Oid winfnoid
Definition: primnodes.h:553
List * args
Definition: primnodes.h:1564
List * named_args
Definition: primnodes.h:1560
XmlExprOp op
Definition: primnodes.h:1556
List * parentUsing
Definition: ruleutils.c:269
char ** new_colnames
Definition: ruleutils.c:262
char ** colnames
Definition: ruleutils.c:245
int * rightattnos
Definition: ruleutils.c:291
List * usingNames
Definition: ruleutils.c:292
bool * is_new_col
Definition: ruleutils.c:263
int * leftattnos
Definition: ruleutils.c:290
StringInfo buf
Definition: ruleutils.c:115
List * namespaces
Definition: ruleutils.c:116
List * windowClause
Definition: ruleutils.c:117
List * windowTList
Definition: ruleutils.c:118
Bitmapset * appendparents
Definition: ruleutils.c:125
ParseExprKind special_exprkind
Definition: ruleutils.c:123
List * rtable_names
Definition: ruleutils.c:164
List * inner_tlist
Definition: ruleutils.c:178
List * outer_tlist
Definition: ruleutils.c:177
char ** argnames
Definition: ruleutils.c:183
AppendRelInfo ** appendrels
Definition: ruleutils.c:168
List * rtable_columns
Definition: ruleutils.c:165
List * index_tlist
Definition: ruleutils.c:179
List * using_names
Definition: ruleutils.c:171
Definition: c.h:702
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:709
Definition: c.h:728
Definition: c.h:713
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:720
Definition: c.h:674
Definition: type.h:88
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:345
int count_nonjunk_tlist_entries(List *tlist)
Definition: tlist.c:186
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:346
#define TYPECACHE_GT_OPR
Definition: typcache.h:139
#define TYPECACHE_LT_OPR
Definition: typcache.h:138
String * makeString(char *str)
Definition: value.c:63
#define strVal(v)
Definition: value.h:82
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:108
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3398
bool SplitGUCList(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3704
char * text_to_cstring(const text *t)
Definition: varlena.c:217
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type
const char * name
char * map_xml_name_to_sql_identifier(const char *name)
Definition: xml.c:2371
@ XML_STANDALONE_NO_VALUE
Definition: xml.h:29
@ XML_STANDALONE_YES
Definition: xml.h:27
@ XML_STANDALONE_NO
Definition: xml.h:28
static void convert(const int32 val, char *const buf)
Definition: zic.c:1992