Fix mis-deparsing of ORDER BY lists when there is a name conflict.
[pgsql.git] / src / backend / utils / adt / ruleutils.c
blobb31be31321dc3c6bbc36a5be8e8495e835c4cea3
1 /*-------------------------------------------------------------------------
3 * ruleutils.c
4 * Functions to convert stored expressions/querytrees back to
5 * source text
7 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * IDENTIFICATION
12 * src/backend/utils/adt/ruleutils.c
14 *-------------------------------------------------------------------------
16 #include "postgres.h"
18 #include <ctype.h>
19 #include <unistd.h>
20 #include <fcntl.h>
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"
35 #include "catalog/pg_partitioned_table.h"
36 #include "catalog/pg_proc.h"
37 #include "catalog/pg_statistic_ext.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_oper.h"
54 #include "parser/parse_relation.h"
55 #include "parser/parser.h"
56 #include "parser/parsetree.h"
57 #include "rewrite/rewriteHandler.h"
58 #include "rewrite/rewriteManip.h"
59 #include "rewrite/rewriteSupport.h"
60 #include "utils/array.h"
61 #include "utils/builtins.h"
62 #include "utils/fmgroids.h"
63 #include "utils/guc.h"
64 #include "utils/hsearch.h"
65 #include "utils/lsyscache.h"
66 #include "utils/partcache.h"
67 #include "utils/rel.h"
68 #include "utils/ruleutils.h"
69 #include "utils/snapmgr.h"
70 #include "utils/syscache.h"
71 #include "utils/typcache.h"
72 #include "utils/varlena.h"
73 #include "utils/xml.h"
75 /* ----------
76 * Pretty formatting constants
77 * ----------
80 /* Indent counts */
81 #define PRETTYINDENT_STD 8
82 #define PRETTYINDENT_JOIN 4
83 #define PRETTYINDENT_VAR 4
85 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
87 /* Pretty flags */
88 #define PRETTYFLAG_PAREN 0x0001
89 #define PRETTYFLAG_INDENT 0x0002
90 #define PRETTYFLAG_SCHEMA 0x0004
92 /* Standard conversion of a "bool pretty" option to detailed flags */
93 #define GET_PRETTY_FLAGS(pretty) \
94 ((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
95 : PRETTYFLAG_INDENT)
97 /* Default line length for pretty-print wrapping: 0 means wrap always */
98 #define WRAP_COLUMN_DEFAULT 0
100 /* macros to test if pretty action needed */
101 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
102 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
103 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
106 /* ----------
107 * Local data types
108 * ----------
111 /* Context info needed for invoking a recursive querytree display routine */
112 typedef struct
114 StringInfo buf; /* output buffer to append to */
115 List *namespaces; /* List of deparse_namespace nodes */
116 TupleDesc resultDesc; /* if top level of a view, the view's tupdesc */
117 List *targetList; /* Current query level's SELECT targetlist */
118 List *windowClause; /* Current query level's 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 bool colNamesVisible; /* do we care about output column names? */
124 bool inGroupBy; /* deparsing GROUP BY clause? */
125 bool varInOrderBy; /* deparsing simple Var in ORDER BY? */
126 Bitmapset *appendparents; /* if not null, map child Vars of these relids
127 * back to the parent rel */
128 } deparse_context;
131 * Each level of query context around a subtree needs a level of Var namespace.
132 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
133 * the current context's namespaces list.
135 * rtable is the list of actual RTEs from the Query or PlannedStmt.
136 * rtable_names holds the alias name to be used for each RTE (either a C
137 * string, or NULL for nameless RTEs such as unnamed joins).
138 * rtable_columns holds the column alias names to be used for each RTE.
140 * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
141 * in the PlannedStmt case).
142 * ctes is a list of CommonTableExpr nodes (only used in the Query case).
143 * appendrels, if not null (it's only used in the PlannedStmt case), is an
144 * array of AppendRelInfo nodes, indexed by child relid. We use that to map
145 * child-table Vars to their inheritance parents.
147 * In some cases we need to make names of merged JOIN USING columns unique
148 * across the whole query, not only per-RTE. If so, unique_using is true
149 * and using_names is a list of C strings representing names already assigned
150 * to USING columns.
152 * When deparsing plan trees, there is always just a single item in the
153 * deparse_namespace list (since a plan tree never contains Vars with
154 * varlevelsup > 0). We store the Plan node that is the immediate
155 * parent of the expression to be deparsed, as well as a list of that
156 * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
157 * as well as their targetlists, and the index tlist if the current plan node
158 * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
159 * from the current Plan node, but it seems notationally clearer to set them
160 * up as separate fields.)
162 typedef struct
164 List *rtable; /* List of RangeTblEntry nodes */
165 List *rtable_names; /* Parallel list of names for RTEs */
166 List *rtable_columns; /* Parallel list of deparse_columns structs */
167 List *subplans; /* List of Plan trees for SubPlans */
168 List *ctes; /* List of CommonTableExpr nodes */
169 AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
170 /* Workspace for column alias assignment: */
171 bool unique_using; /* Are we making USING names globally unique */
172 List *using_names; /* List of assigned names for USING columns */
173 /* Remaining fields are used only when deparsing a Plan tree: */
174 Plan *plan; /* immediate parent of current expression */
175 List *ancestors; /* ancestors of plan */
176 Plan *outer_plan; /* outer subnode, or NULL if none */
177 Plan *inner_plan; /* inner subnode, or NULL if none */
178 List *outer_tlist; /* referent for OUTER_VAR Vars */
179 List *inner_tlist; /* referent for INNER_VAR Vars */
180 List *index_tlist; /* referent for INDEX_VAR Vars */
181 /* Special namespace representing a function signature: */
182 char *funcname;
183 int numargs;
184 char **argnames;
185 } deparse_namespace;
188 * Per-relation data about column alias names.
190 * Selecting aliases is unreasonably complicated because of the need to dump
191 * rules/views whose underlying tables may have had columns added, deleted, or
192 * renamed since the query was parsed. We must nonetheless print the rule/view
193 * in a form that can be reloaded and will produce the same results as before.
195 * For each RTE used in the query, we must assign column aliases that are
196 * unique within that RTE. SQL does not require this of the original query,
197 * but due to factors such as *-expansion we need to be able to uniquely
198 * reference every column in a decompiled query. As long as we qualify all
199 * column references, per-RTE uniqueness is sufficient for that.
201 * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
202 * since they just inherit column names from their input RTEs, and we can't
203 * rename the columns at the join level. Most of the time this isn't an issue
204 * because we don't need to reference the join's output columns as such; we
205 * can reference the input columns instead. That approach can fail for merged
206 * JOIN USING columns, however, so when we have one of those in an unnamed
207 * join, we have to make that column's alias globally unique across the whole
208 * query to ensure it can be referenced unambiguously.
210 * Another problem is that a JOIN USING clause requires the columns to be
211 * merged to have the same aliases in both input RTEs, and that no other
212 * columns in those RTEs or their children conflict with the USING names.
213 * To handle that, we do USING-column alias assignment in a recursive
214 * traversal of the query's jointree. When descending through a JOIN with
215 * USING, we preassign the USING column names to the child columns, overriding
216 * other rules for column alias assignment. We also mark each RTE with a list
217 * of all USING column names selected for joins containing that RTE, so that
218 * when we assign other columns' aliases later, we can avoid conflicts.
220 * Another problem is that if a JOIN's input tables have had columns added or
221 * deleted since the query was parsed, we must generate a column alias list
222 * for the join that matches the current set of input columns --- otherwise, a
223 * change in the number of columns in the left input would throw off matching
224 * of aliases to columns of the right input. Thus, positions in the printable
225 * column alias list are not necessarily one-for-one with varattnos of the
226 * JOIN, so we need a separate new_colnames[] array for printing purposes.
228 typedef struct
231 * colnames is an array containing column aliases to use for columns that
232 * existed when the query was parsed. Dropped columns have NULL entries.
233 * This array can be directly indexed by varattno to get a Var's name.
235 * Non-NULL entries are guaranteed unique within the RTE, *except* when
236 * this is for an unnamed JOIN RTE. In that case we merely copy up names
237 * from the two input RTEs.
239 * During the recursive descent in set_using_names(), forcible assignment
240 * of a child RTE's column name is represented by pre-setting that element
241 * of the child's colnames array. So at that stage, NULL entries in this
242 * array just mean that no name has been preassigned, not necessarily that
243 * the column is dropped.
245 int num_cols; /* length of colnames[] array */
246 char **colnames; /* array of C strings and NULLs */
249 * new_colnames is an array containing column aliases to use for columns
250 * that would exist if the query was re-parsed against the current
251 * definitions of its base tables. This is what to print as the column
252 * alias list for the RTE. This array does not include dropped columns,
253 * but it will include columns added since original parsing. Indexes in
254 * it therefore have little to do with current varattno values. As above,
255 * entries are unique unless this is for an unnamed JOIN RTE. (In such an
256 * RTE, we never actually print this array, but we must compute it anyway
257 * for possible use in computing column names of upper joins.) The
258 * parallel array is_new_col marks which of these columns are new since
259 * original parsing. Entries with is_new_col false must match the
260 * non-NULL colnames entries one-for-one.
262 int num_new_cols; /* length of new_colnames[] array */
263 char **new_colnames; /* array of C strings */
264 bool *is_new_col; /* array of bool flags */
266 /* This flag tells whether we should actually print a column alias list */
267 bool printaliases;
269 /* This list has all names used as USING names in joins above this RTE */
270 List *parentUsing; /* names assigned to parent merged columns */
273 * If this struct is for a JOIN RTE, we fill these fields during the
274 * set_using_names() pass to describe its relationship to its child RTEs.
276 * leftattnos and rightattnos are arrays with one entry per existing
277 * output column of the join (hence, indexable by join varattno). For a
278 * simple reference to a column of the left child, leftattnos[i] is the
279 * child RTE's attno and rightattnos[i] is zero; and conversely for a
280 * column of the right child. But for merged columns produced by JOIN
281 * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
282 * Note that a simple reference might be to a child RTE column that's been
283 * dropped; but that's OK since the column could not be used in the query.
285 * If it's a JOIN USING, usingNames holds the alias names selected for the
286 * merged columns (these might be different from the original USING list,
287 * if we had to modify names to achieve uniqueness).
289 int leftrti; /* rangetable index of left child */
290 int rightrti; /* rangetable index of right child */
291 int *leftattnos; /* left-child varattnos of join cols, or 0 */
292 int *rightattnos; /* right-child varattnos of join cols, or 0 */
293 List *usingNames; /* names assigned to merged columns */
294 } deparse_columns;
296 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
297 #define deparse_columns_fetch(rangetable_index, dpns) \
298 ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
301 * Entry in set_rtable_names' hash table
303 typedef struct
305 char name[NAMEDATALEN]; /* Hash key --- must be first */
306 int counter; /* Largest addition used so far for name */
307 } NameHashEntry;
309 /* Callback signature for resolve_special_varno() */
310 typedef void (*rsv_callback) (Node *node, deparse_context *context,
311 void *callback_arg);
314 /* ----------
315 * Global data
316 * ----------
318 static SPIPlanPtr plan_getrulebyoid = NULL;
319 static const char *const query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
320 static SPIPlanPtr plan_getviewrule = NULL;
321 static const char *const query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
323 /* GUC parameters */
324 bool quote_all_identifiers = false;
327 /* ----------
328 * Local functions
330 * Most of these functions used to use fixed-size buffers to build their
331 * results. Now, they take an (already initialized) StringInfo object
332 * as a parameter, and append their text output to its contents.
333 * ----------
335 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
336 bool forceprefix, bool showimplicit,
337 int prettyFlags, int startIndent);
338 static char *pg_get_viewdef_worker(Oid viewoid,
339 int prettyFlags, int wrapColumn);
340 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
341 static int decompile_column_index_array(Datum column_index_array, Oid relId,
342 StringInfo buf);
343 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
344 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
345 const Oid *excludeOps,
346 bool attrsOnly, bool keysOnly,
347 bool showTblSpc, bool inherits,
348 int prettyFlags, bool missing_ok);
349 static char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
350 bool missing_ok);
351 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
352 bool attrsOnly, bool missing_ok);
353 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
354 int prettyFlags, bool missing_ok);
355 static text *pg_get_expr_worker(text *expr, Oid relid, int prettyFlags);
356 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
357 bool print_table_args, bool print_defaults);
358 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
359 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
360 static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
361 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
362 Bitmapset *rels_used);
363 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
364 List *parent_namespaces);
365 static void set_simple_column_names(deparse_namespace *dpns);
366 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
367 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
368 List *parentUsing);
369 static void set_relation_column_names(deparse_namespace *dpns,
370 RangeTblEntry *rte,
371 deparse_columns *colinfo);
372 static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
373 deparse_columns *colinfo);
374 static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
375 deparse_columns *colinfo);
376 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
377 deparse_columns *colinfo);
378 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
379 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
380 deparse_columns *colinfo);
381 static char *get_rtable_name(int rtindex, deparse_context *context);
382 static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
383 static Plan *find_recursive_union(deparse_namespace *dpns,
384 WorkTableScan *wtscan);
385 static void push_child_plan(deparse_namespace *dpns, Plan *plan,
386 deparse_namespace *save_dpns);
387 static void pop_child_plan(deparse_namespace *dpns,
388 deparse_namespace *save_dpns);
389 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
390 deparse_namespace *save_dpns);
391 static void pop_ancestor_plan(deparse_namespace *dpns,
392 deparse_namespace *save_dpns);
393 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
394 int prettyFlags);
395 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
396 int prettyFlags, int wrapColumn);
397 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
398 TupleDesc resultDesc, bool colNamesVisible,
399 int prettyFlags, int wrapColumn, int startIndent);
400 static void get_values_def(List *values_lists, deparse_context *context);
401 static void get_with_clause(Query *query, deparse_context *context);
402 static void get_select_query_def(Query *query, deparse_context *context);
403 static void get_insert_query_def(Query *query, deparse_context *context);
404 static void get_update_query_def(Query *query, deparse_context *context);
405 static void get_update_query_targetlist_def(Query *query, List *targetList,
406 deparse_context *context,
407 RangeTblEntry *rte);
408 static void get_delete_query_def(Query *query, deparse_context *context);
409 static void get_merge_query_def(Query *query, deparse_context *context);
410 static void get_utility_query_def(Query *query, deparse_context *context);
411 static void get_basic_select_query(Query *query, deparse_context *context);
412 static void get_target_list(List *targetList, deparse_context *context);
413 static void get_setop_query(Node *setOp, Query *query,
414 deparse_context *context);
415 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
416 bool force_colno,
417 deparse_context *context);
418 static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
419 bool omit_parens, deparse_context *context);
420 static void get_rule_orderby(List *orderList, List *targetList,
421 bool force_colno, deparse_context *context);
422 static void get_rule_windowclause(Query *query, deparse_context *context);
423 static void get_rule_windowspec(WindowClause *wc, List *targetList,
424 deparse_context *context);
425 static char *get_variable(Var *var, int levelsup, bool istoplevel,
426 deparse_context *context);
427 static void get_special_variable(Node *node, deparse_context *context,
428 void *callback_arg);
429 static void resolve_special_varno(Node *node, deparse_context *context,
430 rsv_callback callback, void *callback_arg);
431 static Node *find_param_referent(Param *param, deparse_context *context,
432 deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
433 static SubPlan *find_param_generator(Param *param, deparse_context *context,
434 int *column_p);
435 static SubPlan *find_param_generator_initplan(Param *param, Plan *plan,
436 int *column_p);
437 static void get_parameter(Param *param, deparse_context *context);
438 static const char *get_simple_binary_op_name(OpExpr *expr);
439 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
440 static void appendContextKeyword(deparse_context *context, const char *str,
441 int indentBefore, int indentAfter, int indentPlus);
442 static void removeStringInfoSpaces(StringInfo str);
443 static void get_rule_expr(Node *node, deparse_context *context,
444 bool showimplicit);
445 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
446 bool showimplicit);
447 static void get_rule_list_toplevel(List *lst, deparse_context *context,
448 bool showimplicit);
449 static void get_rule_expr_funccall(Node *node, deparse_context *context,
450 bool showimplicit);
451 static bool looks_like_function(Node *node);
452 static void get_oper_expr(OpExpr *expr, deparse_context *context);
453 static void get_func_expr(FuncExpr *expr, deparse_context *context,
454 bool showimplicit);
455 static void get_agg_expr(Aggref *aggref, deparse_context *context,
456 Aggref *original_aggref);
457 static void get_agg_expr_helper(Aggref *aggref, deparse_context *context,
458 Aggref *original_aggref, const char *funcname,
459 const char *options, bool is_json_objectagg);
460 static void get_agg_combine_expr(Node *node, deparse_context *context,
461 void *callback_arg);
462 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
463 static void get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
464 const char *funcname, const char *options,
465 bool is_json_objectagg);
466 static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
467 static void get_coercion_expr(Node *arg, deparse_context *context,
468 Oid resulttype, int32 resulttypmod,
469 Node *parentNode);
470 static void get_const_expr(Const *constval, deparse_context *context,
471 int showtype);
472 static void get_const_collation(Const *constval, deparse_context *context);
473 static void get_json_format(JsonFormat *format, StringInfo buf);
474 static void get_json_returning(JsonReturning *returning, StringInfo buf,
475 bool json_format_by_default);
476 static void get_json_constructor(JsonConstructorExpr *ctor,
477 deparse_context *context, bool showimplicit);
478 static void get_json_constructor_options(JsonConstructorExpr *ctor,
479 StringInfo buf);
480 static void get_json_agg_constructor(JsonConstructorExpr *ctor,
481 deparse_context *context,
482 const char *funcname,
483 bool is_json_objectagg);
484 static void simple_quote_literal(StringInfo buf, const char *val);
485 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
486 static void get_tablefunc(TableFunc *tf, deparse_context *context,
487 bool showimplicit);
488 static void get_from_clause(Query *query, const char *prefix,
489 deparse_context *context);
490 static void get_from_clause_item(Node *jtnode, Query *query,
491 deparse_context *context);
492 static void get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
493 deparse_context *context);
494 static void get_column_alias_list(deparse_columns *colinfo,
495 deparse_context *context);
496 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
497 deparse_columns *colinfo,
498 deparse_context *context);
499 static void get_tablesample_def(TableSampleClause *tablesample,
500 deparse_context *context);
501 static void get_opclass_name(Oid opclass, Oid actual_datatype,
502 StringInfo buf);
503 static Node *processIndirection(Node *node, deparse_context *context);
504 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
505 static char *get_relation_name(Oid relid);
506 static char *generate_relation_name(Oid relid, List *namespaces);
507 static char *generate_qualified_relation_name(Oid relid);
508 static char *generate_function_name(Oid funcid, int nargs,
509 List *argnames, Oid *argtypes,
510 bool has_variadic, bool *use_variadic_p,
511 bool inGroupBy);
512 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
513 static void add_cast_to(StringInfo buf, Oid typid);
514 static char *generate_qualified_type_name(Oid typid);
515 static text *string_to_text(char *str);
516 static char *flatten_reloptions(Oid relid);
517 static void get_reloptions(StringInfo buf, Datum reloptions);
518 static void get_json_path_spec(Node *path_spec, deparse_context *context,
519 bool showimplicit);
520 static void get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan,
521 deparse_context *context,
522 bool showimplicit);
523 static void get_json_table_nested_columns(TableFunc *tf, JsonTablePlan *plan,
524 deparse_context *context,
525 bool showimplicit,
526 bool needcomma);
528 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
531 /* ----------
532 * pg_get_ruledef - Do it all and return a text
533 * that could be used as a statement
534 * to recreate the rule
535 * ----------
537 Datum
538 pg_get_ruledef(PG_FUNCTION_ARGS)
540 Oid ruleoid = PG_GETARG_OID(0);
541 int prettyFlags;
542 char *res;
544 prettyFlags = PRETTYFLAG_INDENT;
546 res = pg_get_ruledef_worker(ruleoid, prettyFlags);
548 if (res == NULL)
549 PG_RETURN_NULL();
551 PG_RETURN_TEXT_P(string_to_text(res));
555 Datum
556 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
558 Oid ruleoid = PG_GETARG_OID(0);
559 bool pretty = PG_GETARG_BOOL(1);
560 int prettyFlags;
561 char *res;
563 prettyFlags = GET_PRETTY_FLAGS(pretty);
565 res = pg_get_ruledef_worker(ruleoid, prettyFlags);
567 if (res == NULL)
568 PG_RETURN_NULL();
570 PG_RETURN_TEXT_P(string_to_text(res));
574 static char *
575 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
577 Datum args[1];
578 char nulls[1];
579 int spirc;
580 HeapTuple ruletup;
581 TupleDesc rulettc;
582 StringInfoData buf;
585 * Do this first so that string is alloc'd in outer context not SPI's.
587 initStringInfo(&buf);
590 * Connect to SPI manager
592 if (SPI_connect() != SPI_OK_CONNECT)
593 elog(ERROR, "SPI_connect failed");
596 * On the first call prepare the plan to lookup pg_rewrite. We read
597 * pg_rewrite over the SPI manager instead of using the syscache to be
598 * checked for read access on pg_rewrite.
600 if (plan_getrulebyoid == NULL)
602 Oid argtypes[1];
603 SPIPlanPtr plan;
605 argtypes[0] = OIDOID;
606 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
607 if (plan == NULL)
608 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
609 SPI_keepplan(plan);
610 plan_getrulebyoid = plan;
614 * Get the pg_rewrite tuple for this rule
616 args[0] = ObjectIdGetDatum(ruleoid);
617 nulls[0] = ' ';
618 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
619 if (spirc != SPI_OK_SELECT)
620 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
621 if (SPI_processed != 1)
624 * There is no tuple data available here, just keep the output buffer
625 * empty.
628 else
631 * Get the rule's definition and put it into executor's memory
633 ruletup = SPI_tuptable->vals[0];
634 rulettc = SPI_tuptable->tupdesc;
635 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
639 * Disconnect from SPI manager
641 if (SPI_finish() != SPI_OK_FINISH)
642 elog(ERROR, "SPI_finish failed");
644 if (buf.len == 0)
645 return NULL;
647 return buf.data;
651 /* ----------
652 * pg_get_viewdef - Mainly the same thing, but we
653 * only return the SELECT part of a view
654 * ----------
656 Datum
657 pg_get_viewdef(PG_FUNCTION_ARGS)
659 /* By OID */
660 Oid viewoid = PG_GETARG_OID(0);
661 int prettyFlags;
662 char *res;
664 prettyFlags = PRETTYFLAG_INDENT;
666 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
668 if (res == NULL)
669 PG_RETURN_NULL();
671 PG_RETURN_TEXT_P(string_to_text(res));
675 Datum
676 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
678 /* By OID */
679 Oid viewoid = PG_GETARG_OID(0);
680 bool pretty = PG_GETARG_BOOL(1);
681 int prettyFlags;
682 char *res;
684 prettyFlags = GET_PRETTY_FLAGS(pretty);
686 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
688 if (res == NULL)
689 PG_RETURN_NULL();
691 PG_RETURN_TEXT_P(string_to_text(res));
694 Datum
695 pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
697 /* By OID */
698 Oid viewoid = PG_GETARG_OID(0);
699 int wrap = PG_GETARG_INT32(1);
700 int prettyFlags;
701 char *res;
703 /* calling this implies we want pretty printing */
704 prettyFlags = GET_PRETTY_FLAGS(true);
706 res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
708 if (res == NULL)
709 PG_RETURN_NULL();
711 PG_RETURN_TEXT_P(string_to_text(res));
714 Datum
715 pg_get_viewdef_name(PG_FUNCTION_ARGS)
717 /* By qualified name */
718 text *viewname = PG_GETARG_TEXT_PP(0);
719 int prettyFlags;
720 RangeVar *viewrel;
721 Oid viewoid;
722 char *res;
724 prettyFlags = PRETTYFLAG_INDENT;
726 /* Look up view name. Can't lock it - we might not have privileges. */
727 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
728 viewoid = RangeVarGetRelid(viewrel, NoLock, false);
730 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
732 if (res == NULL)
733 PG_RETURN_NULL();
735 PG_RETURN_TEXT_P(string_to_text(res));
739 Datum
740 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
742 /* By qualified name */
743 text *viewname = PG_GETARG_TEXT_PP(0);
744 bool pretty = PG_GETARG_BOOL(1);
745 int prettyFlags;
746 RangeVar *viewrel;
747 Oid viewoid;
748 char *res;
750 prettyFlags = GET_PRETTY_FLAGS(pretty);
752 /* Look up view name. Can't lock it - we might not have privileges. */
753 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
754 viewoid = RangeVarGetRelid(viewrel, NoLock, false);
756 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
758 if (res == NULL)
759 PG_RETURN_NULL();
761 PG_RETURN_TEXT_P(string_to_text(res));
765 * Common code for by-OID and by-name variants of pg_get_viewdef
767 static char *
768 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
770 Datum args[2];
771 char nulls[2];
772 int spirc;
773 HeapTuple ruletup;
774 TupleDesc rulettc;
775 StringInfoData buf;
778 * Do this first so that string is alloc'd in outer context not SPI's.
780 initStringInfo(&buf);
783 * Connect to SPI manager
785 if (SPI_connect() != SPI_OK_CONNECT)
786 elog(ERROR, "SPI_connect failed");
789 * On the first call prepare the plan to lookup pg_rewrite. We read
790 * pg_rewrite over the SPI manager instead of using the syscache to be
791 * checked for read access on pg_rewrite.
793 if (plan_getviewrule == NULL)
795 Oid argtypes[2];
796 SPIPlanPtr plan;
798 argtypes[0] = OIDOID;
799 argtypes[1] = NAMEOID;
800 plan = SPI_prepare(query_getviewrule, 2, argtypes);
801 if (plan == NULL)
802 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
803 SPI_keepplan(plan);
804 plan_getviewrule = plan;
808 * Get the pg_rewrite tuple for the view's SELECT rule
810 args[0] = ObjectIdGetDatum(viewoid);
811 args[1] = DirectFunctionCall1(namein, CStringGetDatum(ViewSelectRuleName));
812 nulls[0] = ' ';
813 nulls[1] = ' ';
814 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
815 if (spirc != SPI_OK_SELECT)
816 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
817 if (SPI_processed != 1)
820 * There is no tuple data available here, just keep the output buffer
821 * empty.
824 else
827 * Get the rule's definition and put it into executor's memory
829 ruletup = SPI_tuptable->vals[0];
830 rulettc = SPI_tuptable->tupdesc;
831 make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
835 * Disconnect from SPI manager
837 if (SPI_finish() != SPI_OK_FINISH)
838 elog(ERROR, "SPI_finish failed");
840 if (buf.len == 0)
841 return NULL;
843 return buf.data;
846 /* ----------
847 * pg_get_triggerdef - Get the definition of a trigger
848 * ----------
850 Datum
851 pg_get_triggerdef(PG_FUNCTION_ARGS)
853 Oid trigid = PG_GETARG_OID(0);
854 char *res;
856 res = pg_get_triggerdef_worker(trigid, false);
858 if (res == NULL)
859 PG_RETURN_NULL();
861 PG_RETURN_TEXT_P(string_to_text(res));
864 Datum
865 pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
867 Oid trigid = PG_GETARG_OID(0);
868 bool pretty = PG_GETARG_BOOL(1);
869 char *res;
871 res = pg_get_triggerdef_worker(trigid, pretty);
873 if (res == NULL)
874 PG_RETURN_NULL();
876 PG_RETURN_TEXT_P(string_to_text(res));
879 static char *
880 pg_get_triggerdef_worker(Oid trigid, bool pretty)
882 HeapTuple ht_trig;
883 Form_pg_trigger trigrec;
884 StringInfoData buf;
885 Relation tgrel;
886 ScanKeyData skey[1];
887 SysScanDesc tgscan;
888 int findx = 0;
889 char *tgname;
890 char *tgoldtable;
891 char *tgnewtable;
892 Datum value;
893 bool isnull;
896 * Fetch the pg_trigger tuple by the Oid of the trigger
898 tgrel = table_open(TriggerRelationId, AccessShareLock);
900 ScanKeyInit(&skey[0],
901 Anum_pg_trigger_oid,
902 BTEqualStrategyNumber, F_OIDEQ,
903 ObjectIdGetDatum(trigid));
905 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
906 NULL, 1, skey);
908 ht_trig = systable_getnext(tgscan);
910 if (!HeapTupleIsValid(ht_trig))
912 systable_endscan(tgscan);
913 table_close(tgrel, AccessShareLock);
914 return NULL;
917 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
920 * Start the trigger definition. Note that the trigger's name should never
921 * be schema-qualified, but the trigger rel's name may be.
923 initStringInfo(&buf);
925 tgname = NameStr(trigrec->tgname);
926 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
927 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
928 quote_identifier(tgname));
930 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
931 appendStringInfoString(&buf, "BEFORE");
932 else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
933 appendStringInfoString(&buf, "AFTER");
934 else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
935 appendStringInfoString(&buf, "INSTEAD OF");
936 else
937 elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
939 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
941 appendStringInfoString(&buf, " INSERT");
942 findx++;
944 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
946 if (findx > 0)
947 appendStringInfoString(&buf, " OR DELETE");
948 else
949 appendStringInfoString(&buf, " DELETE");
950 findx++;
952 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
954 if (findx > 0)
955 appendStringInfoString(&buf, " OR UPDATE");
956 else
957 appendStringInfoString(&buf, " UPDATE");
958 findx++;
959 /* tgattr is first var-width field, so OK to access directly */
960 if (trigrec->tgattr.dim1 > 0)
962 int i;
964 appendStringInfoString(&buf, " OF ");
965 for (i = 0; i < trigrec->tgattr.dim1; i++)
967 char *attname;
969 if (i > 0)
970 appendStringInfoString(&buf, ", ");
971 attname = get_attname(trigrec->tgrelid,
972 trigrec->tgattr.values[i], false);
973 appendStringInfoString(&buf, quote_identifier(attname));
977 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
979 if (findx > 0)
980 appendStringInfoString(&buf, " OR TRUNCATE");
981 else
982 appendStringInfoString(&buf, " TRUNCATE");
983 findx++;
987 * In non-pretty mode, always schema-qualify the target table name for
988 * safety. In pretty mode, schema-qualify only if not visible.
990 appendStringInfo(&buf, " ON %s ",
991 pretty ?
992 generate_relation_name(trigrec->tgrelid, NIL) :
993 generate_qualified_relation_name(trigrec->tgrelid));
995 if (OidIsValid(trigrec->tgconstraint))
997 if (OidIsValid(trigrec->tgconstrrelid))
998 appendStringInfo(&buf, "FROM %s ",
999 generate_relation_name(trigrec->tgconstrrelid, NIL));
1000 if (!trigrec->tgdeferrable)
1001 appendStringInfoString(&buf, "NOT ");
1002 appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
1003 if (trigrec->tginitdeferred)
1004 appendStringInfoString(&buf, "DEFERRED ");
1005 else
1006 appendStringInfoString(&buf, "IMMEDIATE ");
1009 value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
1010 tgrel->rd_att, &isnull);
1011 if (!isnull)
1012 tgoldtable = NameStr(*DatumGetName(value));
1013 else
1014 tgoldtable = NULL;
1015 value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
1016 tgrel->rd_att, &isnull);
1017 if (!isnull)
1018 tgnewtable = NameStr(*DatumGetName(value));
1019 else
1020 tgnewtable = NULL;
1021 if (tgoldtable != NULL || tgnewtable != NULL)
1023 appendStringInfoString(&buf, "REFERENCING ");
1024 if (tgoldtable != NULL)
1025 appendStringInfo(&buf, "OLD TABLE AS %s ",
1026 quote_identifier(tgoldtable));
1027 if (tgnewtable != NULL)
1028 appendStringInfo(&buf, "NEW TABLE AS %s ",
1029 quote_identifier(tgnewtable));
1032 if (TRIGGER_FOR_ROW(trigrec->tgtype))
1033 appendStringInfoString(&buf, "FOR EACH ROW ");
1034 else
1035 appendStringInfoString(&buf, "FOR EACH STATEMENT ");
1037 /* If the trigger has a WHEN qualification, add that */
1038 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
1039 tgrel->rd_att, &isnull);
1040 if (!isnull)
1042 Node *qual;
1043 char relkind;
1044 deparse_context context;
1045 deparse_namespace dpns;
1046 RangeTblEntry *oldrte;
1047 RangeTblEntry *newrte;
1049 appendStringInfoString(&buf, "WHEN (");
1051 qual = stringToNode(TextDatumGetCString(value));
1053 relkind = get_rel_relkind(trigrec->tgrelid);
1055 /* Build minimal OLD and NEW RTEs for the rel */
1056 oldrte = makeNode(RangeTblEntry);
1057 oldrte->rtekind = RTE_RELATION;
1058 oldrte->relid = trigrec->tgrelid;
1059 oldrte->relkind = relkind;
1060 oldrte->rellockmode = AccessShareLock;
1061 oldrte->alias = makeAlias("old", NIL);
1062 oldrte->eref = oldrte->alias;
1063 oldrte->lateral = false;
1064 oldrte->inh = false;
1065 oldrte->inFromCl = true;
1067 newrte = makeNode(RangeTblEntry);
1068 newrte->rtekind = RTE_RELATION;
1069 newrte->relid = trigrec->tgrelid;
1070 newrte->relkind = relkind;
1071 newrte->rellockmode = AccessShareLock;
1072 newrte->alias = makeAlias("new", NIL);
1073 newrte->eref = newrte->alias;
1074 newrte->lateral = false;
1075 newrte->inh = false;
1076 newrte->inFromCl = true;
1078 /* Build two-element rtable */
1079 memset(&dpns, 0, sizeof(dpns));
1080 dpns.rtable = list_make2(oldrte, newrte);
1081 dpns.subplans = NIL;
1082 dpns.ctes = NIL;
1083 dpns.appendrels = NULL;
1084 set_rtable_names(&dpns, NIL, NULL);
1085 set_simple_column_names(&dpns);
1087 /* Set up context with one-deep namespace stack */
1088 context.buf = &buf;
1089 context.namespaces = list_make1(&dpns);
1090 context.resultDesc = NULL;
1091 context.targetList = NIL;
1092 context.windowClause = NIL;
1093 context.varprefix = true;
1094 context.prettyFlags = GET_PRETTY_FLAGS(pretty);
1095 context.wrapColumn = WRAP_COLUMN_DEFAULT;
1096 context.indentLevel = PRETTYINDENT_STD;
1097 context.colNamesVisible = true;
1098 context.inGroupBy = false;
1099 context.varInOrderBy = false;
1100 context.appendparents = NULL;
1102 get_rule_expr(qual, &context, false);
1104 appendStringInfoString(&buf, ") ");
1107 appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
1108 generate_function_name(trigrec->tgfoid, 0,
1109 NIL, NULL,
1110 false, NULL, false));
1112 if (trigrec->tgnargs > 0)
1114 char *p;
1115 int i;
1117 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
1118 tgrel->rd_att, &isnull);
1119 if (isnull)
1120 elog(ERROR, "tgargs is null for trigger %u", trigid);
1121 p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
1122 for (i = 0; i < trigrec->tgnargs; i++)
1124 if (i > 0)
1125 appendStringInfoString(&buf, ", ");
1126 simple_quote_literal(&buf, p);
1127 /* advance p to next string embedded in tgargs */
1128 while (*p)
1129 p++;
1130 p++;
1134 /* We deliberately do not put semi-colon at end */
1135 appendStringInfoChar(&buf, ')');
1137 /* Clean up */
1138 systable_endscan(tgscan);
1140 table_close(tgrel, AccessShareLock);
1142 return buf.data;
1145 /* ----------
1146 * pg_get_indexdef - Get the definition of an index
1148 * In the extended version, there is a colno argument as well as pretty bool.
1149 * if colno == 0, we want a complete index definition.
1150 * if colno > 0, we only want the Nth index key's variable or expression.
1152 * Note that the SQL-function versions of this omit any info about the
1153 * index tablespace; this is intentional because pg_dump wants it that way.
1154 * However pg_get_indexdef_string() includes the index tablespace.
1155 * ----------
1157 Datum
1158 pg_get_indexdef(PG_FUNCTION_ARGS)
1160 Oid indexrelid = PG_GETARG_OID(0);
1161 int prettyFlags;
1162 char *res;
1164 prettyFlags = PRETTYFLAG_INDENT;
1166 res = pg_get_indexdef_worker(indexrelid, 0, NULL,
1167 false, false,
1168 false, false,
1169 prettyFlags, true);
1171 if (res == NULL)
1172 PG_RETURN_NULL();
1174 PG_RETURN_TEXT_P(string_to_text(res));
1177 Datum
1178 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
1180 Oid indexrelid = PG_GETARG_OID(0);
1181 int32 colno = PG_GETARG_INT32(1);
1182 bool pretty = PG_GETARG_BOOL(2);
1183 int prettyFlags;
1184 char *res;
1186 prettyFlags = GET_PRETTY_FLAGS(pretty);
1188 res = pg_get_indexdef_worker(indexrelid, colno, NULL,
1189 colno != 0, false,
1190 false, false,
1191 prettyFlags, true);
1193 if (res == NULL)
1194 PG_RETURN_NULL();
1196 PG_RETURN_TEXT_P(string_to_text(res));
1200 * Internal version for use by ALTER TABLE.
1201 * Includes a tablespace clause in the result.
1202 * Returns a palloc'd C string; no pretty-printing.
1204 char *
1205 pg_get_indexdef_string(Oid indexrelid)
1207 return pg_get_indexdef_worker(indexrelid, 0, NULL,
1208 false, false,
1209 true, true,
1210 0, false);
1213 /* Internal version that just reports the key-column definitions */
1214 char *
1215 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1217 int prettyFlags;
1219 prettyFlags = GET_PRETTY_FLAGS(pretty);
1221 return pg_get_indexdef_worker(indexrelid, 0, NULL,
1222 true, true,
1223 false, false,
1224 prettyFlags, false);
1227 /* Internal version, extensible with flags to control its behavior */
1228 char *
1229 pg_get_indexdef_columns_extended(Oid indexrelid, bits16 flags)
1231 bool pretty = ((flags & RULE_INDEXDEF_PRETTY) != 0);
1232 bool keys_only = ((flags & RULE_INDEXDEF_KEYS_ONLY) != 0);
1233 int prettyFlags;
1235 prettyFlags = GET_PRETTY_FLAGS(pretty);
1237 return pg_get_indexdef_worker(indexrelid, 0, NULL,
1238 true, keys_only,
1239 false, false,
1240 prettyFlags, false);
1244 * Internal workhorse to decompile an index definition.
1246 * This is now used for exclusion constraints as well: if excludeOps is not
1247 * NULL then it points to an array of exclusion operator OIDs.
1249 static char *
1250 pg_get_indexdef_worker(Oid indexrelid, int colno,
1251 const Oid *excludeOps,
1252 bool attrsOnly, bool keysOnly,
1253 bool showTblSpc, bool inherits,
1254 int prettyFlags, bool missing_ok)
1256 /* might want a separate isConstraint parameter later */
1257 bool isConstraint = (excludeOps != NULL);
1258 HeapTuple ht_idx;
1259 HeapTuple ht_idxrel;
1260 HeapTuple ht_am;
1261 Form_pg_index idxrec;
1262 Form_pg_class idxrelrec;
1263 Form_pg_am amrec;
1264 IndexAmRoutine *amroutine;
1265 List *indexprs;
1266 ListCell *indexpr_item;
1267 List *context;
1268 Oid indrelid;
1269 int keyno;
1270 Datum indcollDatum;
1271 Datum indclassDatum;
1272 Datum indoptionDatum;
1273 oidvector *indcollation;
1274 oidvector *indclass;
1275 int2vector *indoption;
1276 StringInfoData buf;
1277 char *str;
1278 char *sep;
1281 * Fetch the pg_index tuple by the Oid of the index
1283 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1284 if (!HeapTupleIsValid(ht_idx))
1286 if (missing_ok)
1287 return NULL;
1288 elog(ERROR, "cache lookup failed for index %u", indexrelid);
1290 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1292 indrelid = idxrec->indrelid;
1293 Assert(indexrelid == idxrec->indexrelid);
1295 /* Must get indcollation, indclass, and indoption the hard way */
1296 indcollDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1297 Anum_pg_index_indcollation);
1298 indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1300 indclassDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1301 Anum_pg_index_indclass);
1302 indclass = (oidvector *) DatumGetPointer(indclassDatum);
1304 indoptionDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1305 Anum_pg_index_indoption);
1306 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1309 * Fetch the pg_class tuple of the index relation
1311 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1312 if (!HeapTupleIsValid(ht_idxrel))
1313 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1314 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1317 * Fetch the pg_am tuple of the index' access method
1319 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1320 if (!HeapTupleIsValid(ht_am))
1321 elog(ERROR, "cache lookup failed for access method %u",
1322 idxrelrec->relam);
1323 amrec = (Form_pg_am) GETSTRUCT(ht_am);
1325 /* Fetch the index AM's API struct */
1326 amroutine = GetIndexAmRoutine(amrec->amhandler);
1329 * Get the index expressions, if any. (NOTE: we do not use the relcache
1330 * versions of the expressions and predicate, because we want to display
1331 * non-const-folded expressions.)
1333 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
1335 Datum exprsDatum;
1336 char *exprsString;
1338 exprsDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1339 Anum_pg_index_indexprs);
1340 exprsString = TextDatumGetCString(exprsDatum);
1341 indexprs = (List *) stringToNode(exprsString);
1342 pfree(exprsString);
1344 else
1345 indexprs = NIL;
1347 indexpr_item = list_head(indexprs);
1349 context = deparse_context_for(get_relation_name(indrelid), indrelid);
1352 * Start the index definition. Note that the index's name should never be
1353 * schema-qualified, but the indexed rel's name may be.
1355 initStringInfo(&buf);
1357 if (!attrsOnly)
1359 if (!isConstraint)
1360 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
1361 idxrec->indisunique ? "UNIQUE " : "",
1362 quote_identifier(NameStr(idxrelrec->relname)),
1363 idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
1364 && !inherits ? "ONLY " : "",
1365 (prettyFlags & PRETTYFLAG_SCHEMA) ?
1366 generate_relation_name(indrelid, NIL) :
1367 generate_qualified_relation_name(indrelid),
1368 quote_identifier(NameStr(amrec->amname)));
1369 else /* currently, must be EXCLUDE constraint */
1370 appendStringInfo(&buf, "EXCLUDE USING %s (",
1371 quote_identifier(NameStr(amrec->amname)));
1375 * Report the indexed attributes
1377 sep = "";
1378 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1380 AttrNumber attnum = idxrec->indkey.values[keyno];
1381 Oid keycoltype;
1382 Oid keycolcollation;
1385 * Ignore non-key attributes if told to.
1387 if (keysOnly && keyno >= idxrec->indnkeyatts)
1388 break;
1390 /* Otherwise, print INCLUDE to divide key and non-key attrs. */
1391 if (!colno && keyno == idxrec->indnkeyatts)
1393 appendStringInfoString(&buf, ") INCLUDE (");
1394 sep = "";
1397 if (!colno)
1398 appendStringInfoString(&buf, sep);
1399 sep = ", ";
1401 if (attnum != 0)
1403 /* Simple index column */
1404 char *attname;
1405 int32 keycoltypmod;
1407 attname = get_attname(indrelid, attnum, false);
1408 if (!colno || colno == keyno + 1)
1409 appendStringInfoString(&buf, quote_identifier(attname));
1410 get_atttypetypmodcoll(indrelid, attnum,
1411 &keycoltype, &keycoltypmod,
1412 &keycolcollation);
1414 else
1416 /* expressional index */
1417 Node *indexkey;
1419 if (indexpr_item == NULL)
1420 elog(ERROR, "too few entries in indexprs list");
1421 indexkey = (Node *) lfirst(indexpr_item);
1422 indexpr_item = lnext(indexprs, indexpr_item);
1423 /* Deparse */
1424 str = deparse_expression_pretty(indexkey, context, false, false,
1425 prettyFlags, 0);
1426 if (!colno || colno == keyno + 1)
1428 /* Need parens if it's not a bare function call */
1429 if (looks_like_function(indexkey))
1430 appendStringInfoString(&buf, str);
1431 else
1432 appendStringInfo(&buf, "(%s)", str);
1434 keycoltype = exprType(indexkey);
1435 keycolcollation = exprCollation(indexkey);
1438 /* Print additional decoration for (selected) key columns */
1439 if (!attrsOnly && keyno < idxrec->indnkeyatts &&
1440 (!colno || colno == keyno + 1))
1442 int16 opt = indoption->values[keyno];
1443 Oid indcoll = indcollation->values[keyno];
1444 Datum attoptions = get_attoptions(indexrelid, keyno + 1);
1445 bool has_options = attoptions != (Datum) 0;
1447 /* Add collation, if not default for column */
1448 if (OidIsValid(indcoll) && indcoll != keycolcollation)
1449 appendStringInfo(&buf, " COLLATE %s",
1450 generate_collation_name((indcoll)));
1452 /* Add the operator class name, if not default */
1453 get_opclass_name(indclass->values[keyno],
1454 has_options ? InvalidOid : keycoltype, &buf);
1456 if (has_options)
1458 appendStringInfoString(&buf, " (");
1459 get_reloptions(&buf, attoptions);
1460 appendStringInfoChar(&buf, ')');
1463 /* Add options if relevant */
1464 if (amroutine->amcanorder)
1466 /* if it supports sort ordering, report DESC and NULLS opts */
1467 if (opt & INDOPTION_DESC)
1469 appendStringInfoString(&buf, " DESC");
1470 /* NULLS FIRST is the default in this case */
1471 if (!(opt & INDOPTION_NULLS_FIRST))
1472 appendStringInfoString(&buf, " NULLS LAST");
1474 else
1476 if (opt & INDOPTION_NULLS_FIRST)
1477 appendStringInfoString(&buf, " NULLS FIRST");
1481 /* Add the exclusion operator if relevant */
1482 if (excludeOps != NULL)
1483 appendStringInfo(&buf, " WITH %s",
1484 generate_operator_name(excludeOps[keyno],
1485 keycoltype,
1486 keycoltype));
1490 if (!attrsOnly)
1492 appendStringInfoChar(&buf, ')');
1494 if (idxrec->indnullsnotdistinct)
1495 appendStringInfoString(&buf, " NULLS NOT DISTINCT");
1498 * If it has options, append "WITH (options)"
1500 str = flatten_reloptions(indexrelid);
1501 if (str)
1503 appendStringInfo(&buf, " WITH (%s)", str);
1504 pfree(str);
1508 * Print tablespace, but only if requested
1510 if (showTblSpc)
1512 Oid tblspc;
1514 tblspc = get_rel_tablespace(indexrelid);
1515 if (OidIsValid(tblspc))
1517 if (isConstraint)
1518 appendStringInfoString(&buf, " USING INDEX");
1519 appendStringInfo(&buf, " TABLESPACE %s",
1520 quote_identifier(get_tablespace_name(tblspc)));
1525 * If it's a partial index, decompile and append the predicate
1527 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
1529 Node *node;
1530 Datum predDatum;
1531 char *predString;
1533 /* Convert text string to node tree */
1534 predDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
1535 Anum_pg_index_indpred);
1536 predString = TextDatumGetCString(predDatum);
1537 node = (Node *) stringToNode(predString);
1538 pfree(predString);
1540 /* Deparse */
1541 str = deparse_expression_pretty(node, context, false, false,
1542 prettyFlags, 0);
1543 if (isConstraint)
1544 appendStringInfo(&buf, " WHERE (%s)", str);
1545 else
1546 appendStringInfo(&buf, " WHERE %s", str);
1550 /* Clean up */
1551 ReleaseSysCache(ht_idx);
1552 ReleaseSysCache(ht_idxrel);
1553 ReleaseSysCache(ht_am);
1555 return buf.data;
1558 /* ----------
1559 * pg_get_querydef
1561 * Public entry point to deparse one query parsetree.
1562 * The pretty flags are determined by GET_PRETTY_FLAGS(pretty).
1564 * The result is a palloc'd C string.
1565 * ----------
1567 char *
1568 pg_get_querydef(Query *query, bool pretty)
1570 StringInfoData buf;
1571 int prettyFlags;
1573 prettyFlags = GET_PRETTY_FLAGS(pretty);
1575 initStringInfo(&buf);
1577 get_query_def(query, &buf, NIL, NULL, true,
1578 prettyFlags, WRAP_COLUMN_DEFAULT, 0);
1580 return buf.data;
1584 * pg_get_statisticsobjdef
1585 * Get the definition of an extended statistics object
1587 Datum
1588 pg_get_statisticsobjdef(PG_FUNCTION_ARGS)
1590 Oid statextid = PG_GETARG_OID(0);
1591 char *res;
1593 res = pg_get_statisticsobj_worker(statextid, false, true);
1595 if (res == NULL)
1596 PG_RETURN_NULL();
1598 PG_RETURN_TEXT_P(string_to_text(res));
1602 * Internal version for use by ALTER TABLE.
1603 * Includes a tablespace clause in the result.
1604 * Returns a palloc'd C string; no pretty-printing.
1606 char *
1607 pg_get_statisticsobjdef_string(Oid statextid)
1609 return pg_get_statisticsobj_worker(statextid, false, false);
1613 * pg_get_statisticsobjdef_columns
1614 * Get columns and expressions for an extended statistics object
1616 Datum
1617 pg_get_statisticsobjdef_columns(PG_FUNCTION_ARGS)
1619 Oid statextid = PG_GETARG_OID(0);
1620 char *res;
1622 res = pg_get_statisticsobj_worker(statextid, true, true);
1624 if (res == NULL)
1625 PG_RETURN_NULL();
1627 PG_RETURN_TEXT_P(string_to_text(res));
1631 * Internal workhorse to decompile an extended statistics object.
1633 static char *
1634 pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
1636 Form_pg_statistic_ext statextrec;
1637 HeapTuple statexttup;
1638 StringInfoData buf;
1639 int colno;
1640 char *nsp;
1641 ArrayType *arr;
1642 char *enabled;
1643 Datum datum;
1644 bool ndistinct_enabled;
1645 bool dependencies_enabled;
1646 bool mcv_enabled;
1647 int i;
1648 List *context;
1649 ListCell *lc;
1650 List *exprs = NIL;
1651 bool has_exprs;
1652 int ncolumns;
1654 statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1656 if (!HeapTupleIsValid(statexttup))
1658 if (missing_ok)
1659 return NULL;
1660 elog(ERROR, "cache lookup failed for statistics object %u", statextid);
1663 /* has the statistics expressions? */
1664 has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1666 statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1669 * Get the statistics expressions, if any. (NOTE: we do not use the
1670 * relcache versions of the expressions, because we want to display
1671 * non-const-folded expressions.)
1673 if (has_exprs)
1675 Datum exprsDatum;
1676 char *exprsString;
1678 exprsDatum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1679 Anum_pg_statistic_ext_stxexprs);
1680 exprsString = TextDatumGetCString(exprsDatum);
1681 exprs = (List *) stringToNode(exprsString);
1682 pfree(exprsString);
1684 else
1685 exprs = NIL;
1687 /* count the number of columns (attributes and expressions) */
1688 ncolumns = statextrec->stxkeys.dim1 + list_length(exprs);
1690 initStringInfo(&buf);
1692 if (!columns_only)
1694 nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
1695 appendStringInfo(&buf, "CREATE STATISTICS %s",
1696 quote_qualified_identifier(nsp,
1697 NameStr(statextrec->stxname)));
1700 * Decode the stxkind column so that we know which stats types to
1701 * print.
1703 datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1704 Anum_pg_statistic_ext_stxkind);
1705 arr = DatumGetArrayTypeP(datum);
1706 if (ARR_NDIM(arr) != 1 ||
1707 ARR_HASNULL(arr) ||
1708 ARR_ELEMTYPE(arr) != CHAROID)
1709 elog(ERROR, "stxkind is not a 1-D char array");
1710 enabled = (char *) ARR_DATA_PTR(arr);
1712 ndistinct_enabled = false;
1713 dependencies_enabled = false;
1714 mcv_enabled = false;
1716 for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1718 if (enabled[i] == STATS_EXT_NDISTINCT)
1719 ndistinct_enabled = true;
1720 else if (enabled[i] == STATS_EXT_DEPENDENCIES)
1721 dependencies_enabled = true;
1722 else if (enabled[i] == STATS_EXT_MCV)
1723 mcv_enabled = true;
1725 /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */
1729 * If any option is disabled, then we'll need to append the types
1730 * clause to show which options are enabled. We omit the types clause
1731 * on purpose when all options are enabled, so a pg_dump/pg_restore
1732 * will create all statistics types on a newer postgres version, if
1733 * the statistics had all options enabled on the original version.
1735 * But if the statistics is defined on just a single column, it has to
1736 * be an expression statistics. In that case we don't need to specify
1737 * kinds.
1739 if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) &&
1740 (ncolumns > 1))
1742 bool gotone = false;
1744 appendStringInfoString(&buf, " (");
1746 if (ndistinct_enabled)
1748 appendStringInfoString(&buf, "ndistinct");
1749 gotone = true;
1752 if (dependencies_enabled)
1754 appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
1755 gotone = true;
1758 if (mcv_enabled)
1759 appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
1761 appendStringInfoChar(&buf, ')');
1764 appendStringInfoString(&buf, " ON ");
1767 /* decode simple column references */
1768 for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
1770 AttrNumber attnum = statextrec->stxkeys.values[colno];
1771 char *attname;
1773 if (colno > 0)
1774 appendStringInfoString(&buf, ", ");
1776 attname = get_attname(statextrec->stxrelid, attnum, false);
1778 appendStringInfoString(&buf, quote_identifier(attname));
1781 context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1782 statextrec->stxrelid);
1784 foreach(lc, exprs)
1786 Node *expr = (Node *) lfirst(lc);
1787 char *str;
1788 int prettyFlags = PRETTYFLAG_PAREN;
1790 str = deparse_expression_pretty(expr, context, false, false,
1791 prettyFlags, 0);
1793 if (colno > 0)
1794 appendStringInfoString(&buf, ", ");
1796 /* Need parens if it's not a bare function call */
1797 if (looks_like_function(expr))
1798 appendStringInfoString(&buf, str);
1799 else
1800 appendStringInfo(&buf, "(%s)", str);
1802 colno++;
1805 if (!columns_only)
1806 appendStringInfo(&buf, " FROM %s",
1807 generate_relation_name(statextrec->stxrelid, NIL));
1809 ReleaseSysCache(statexttup);
1811 return buf.data;
1815 * Generate text array of expressions for statistics object.
1817 Datum
1818 pg_get_statisticsobjdef_expressions(PG_FUNCTION_ARGS)
1820 Oid statextid = PG_GETARG_OID(0);
1821 Form_pg_statistic_ext statextrec;
1822 HeapTuple statexttup;
1823 Datum datum;
1824 List *context;
1825 ListCell *lc;
1826 List *exprs = NIL;
1827 bool has_exprs;
1828 char *tmp;
1829 ArrayBuildState *astate = NULL;
1831 statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1833 if (!HeapTupleIsValid(statexttup))
1834 PG_RETURN_NULL();
1836 /* Does the stats object have expressions? */
1837 has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1839 /* no expressions? we're done */
1840 if (!has_exprs)
1842 ReleaseSysCache(statexttup);
1843 PG_RETURN_NULL();
1846 statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1849 * Get the statistics expressions, and deparse them into text values.
1851 datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
1852 Anum_pg_statistic_ext_stxexprs);
1853 tmp = TextDatumGetCString(datum);
1854 exprs = (List *) stringToNode(tmp);
1855 pfree(tmp);
1857 context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1858 statextrec->stxrelid);
1860 foreach(lc, exprs)
1862 Node *expr = (Node *) lfirst(lc);
1863 char *str;
1864 int prettyFlags = PRETTYFLAG_INDENT;
1866 str = deparse_expression_pretty(expr, context, false, false,
1867 prettyFlags, 0);
1869 astate = accumArrayResult(astate,
1870 PointerGetDatum(cstring_to_text(str)),
1871 false,
1872 TEXTOID,
1873 CurrentMemoryContext);
1876 ReleaseSysCache(statexttup);
1878 PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
1882 * pg_get_partkeydef
1884 * Returns the partition key specification, ie, the following:
1886 * { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
1888 Datum
1889 pg_get_partkeydef(PG_FUNCTION_ARGS)
1891 Oid relid = PG_GETARG_OID(0);
1892 char *res;
1894 res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
1896 if (res == NULL)
1897 PG_RETURN_NULL();
1899 PG_RETURN_TEXT_P(string_to_text(res));
1902 /* Internal version that just reports the column definitions */
1903 char *
1904 pg_get_partkeydef_columns(Oid relid, bool pretty)
1906 int prettyFlags;
1908 prettyFlags = GET_PRETTY_FLAGS(pretty);
1910 return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
1914 * Internal workhorse to decompile a partition key definition.
1916 static char *
1917 pg_get_partkeydef_worker(Oid relid, int prettyFlags,
1918 bool attrsOnly, bool missing_ok)
1920 Form_pg_partitioned_table form;
1921 HeapTuple tuple;
1922 oidvector *partclass;
1923 oidvector *partcollation;
1924 List *partexprs;
1925 ListCell *partexpr_item;
1926 List *context;
1927 Datum datum;
1928 StringInfoData buf;
1929 int keyno;
1930 char *str;
1931 char *sep;
1933 tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
1934 if (!HeapTupleIsValid(tuple))
1936 if (missing_ok)
1937 return NULL;
1938 elog(ERROR, "cache lookup failed for partition key of %u", relid);
1941 form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
1943 Assert(form->partrelid == relid);
1945 /* Must get partclass and partcollation the hard way */
1946 datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1947 Anum_pg_partitioned_table_partclass);
1948 partclass = (oidvector *) DatumGetPointer(datum);
1950 datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1951 Anum_pg_partitioned_table_partcollation);
1952 partcollation = (oidvector *) DatumGetPointer(datum);
1956 * Get the expressions, if any. (NOTE: we do not use the relcache
1957 * versions of the expressions, because we want to display
1958 * non-const-folded expressions.)
1960 if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
1962 Datum exprsDatum;
1963 char *exprsString;
1965 exprsDatum = SysCacheGetAttrNotNull(PARTRELID, tuple,
1966 Anum_pg_partitioned_table_partexprs);
1967 exprsString = TextDatumGetCString(exprsDatum);
1968 partexprs = (List *) stringToNode(exprsString);
1970 if (!IsA(partexprs, List))
1971 elog(ERROR, "unexpected node type found in partexprs: %d",
1972 (int) nodeTag(partexprs));
1974 pfree(exprsString);
1976 else
1977 partexprs = NIL;
1979 partexpr_item = list_head(partexprs);
1980 context = deparse_context_for(get_relation_name(relid), relid);
1982 initStringInfo(&buf);
1984 switch (form->partstrat)
1986 case PARTITION_STRATEGY_HASH:
1987 if (!attrsOnly)
1988 appendStringInfoString(&buf, "HASH");
1989 break;
1990 case PARTITION_STRATEGY_LIST:
1991 if (!attrsOnly)
1992 appendStringInfoString(&buf, "LIST");
1993 break;
1994 case PARTITION_STRATEGY_RANGE:
1995 if (!attrsOnly)
1996 appendStringInfoString(&buf, "RANGE");
1997 break;
1998 default:
1999 elog(ERROR, "unexpected partition strategy: %d",
2000 (int) form->partstrat);
2003 if (!attrsOnly)
2004 appendStringInfoString(&buf, " (");
2005 sep = "";
2006 for (keyno = 0; keyno < form->partnatts; keyno++)
2008 AttrNumber attnum = form->partattrs.values[keyno];
2009 Oid keycoltype;
2010 Oid keycolcollation;
2011 Oid partcoll;
2013 appendStringInfoString(&buf, sep);
2014 sep = ", ";
2015 if (attnum != 0)
2017 /* Simple attribute reference */
2018 char *attname;
2019 int32 keycoltypmod;
2021 attname = get_attname(relid, attnum, false);
2022 appendStringInfoString(&buf, quote_identifier(attname));
2023 get_atttypetypmodcoll(relid, attnum,
2024 &keycoltype, &keycoltypmod,
2025 &keycolcollation);
2027 else
2029 /* Expression */
2030 Node *partkey;
2032 if (partexpr_item == NULL)
2033 elog(ERROR, "too few entries in partexprs list");
2034 partkey = (Node *) lfirst(partexpr_item);
2035 partexpr_item = lnext(partexprs, partexpr_item);
2037 /* Deparse */
2038 str = deparse_expression_pretty(partkey, context, false, false,
2039 prettyFlags, 0);
2040 /* Need parens if it's not a bare function call */
2041 if (looks_like_function(partkey))
2042 appendStringInfoString(&buf, str);
2043 else
2044 appendStringInfo(&buf, "(%s)", str);
2046 keycoltype = exprType(partkey);
2047 keycolcollation = exprCollation(partkey);
2050 /* Add collation, if not default for column */
2051 partcoll = partcollation->values[keyno];
2052 if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
2053 appendStringInfo(&buf, " COLLATE %s",
2054 generate_collation_name((partcoll)));
2056 /* Add the operator class name, if not default */
2057 if (!attrsOnly)
2058 get_opclass_name(partclass->values[keyno], keycoltype, &buf);
2061 if (!attrsOnly)
2062 appendStringInfoChar(&buf, ')');
2064 /* Clean up */
2065 ReleaseSysCache(tuple);
2067 return buf.data;
2071 * pg_get_partition_constraintdef
2073 * Returns partition constraint expression as a string for the input relation
2075 Datum
2076 pg_get_partition_constraintdef(PG_FUNCTION_ARGS)
2078 Oid relationId = PG_GETARG_OID(0);
2079 Expr *constr_expr;
2080 int prettyFlags;
2081 List *context;
2082 char *consrc;
2084 constr_expr = get_partition_qual_relid(relationId);
2086 /* Quick exit if no partition constraint */
2087 if (constr_expr == NULL)
2088 PG_RETURN_NULL();
2091 * Deparse and return the constraint expression.
2093 prettyFlags = PRETTYFLAG_INDENT;
2094 context = deparse_context_for(get_relation_name(relationId), relationId);
2095 consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
2096 false, prettyFlags, 0);
2098 PG_RETURN_TEXT_P(string_to_text(consrc));
2102 * pg_get_partconstrdef_string
2104 * Returns the partition constraint as a C-string for the input relation, with
2105 * the given alias. No pretty-printing.
2107 char *
2108 pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
2110 Expr *constr_expr;
2111 List *context;
2113 constr_expr = get_partition_qual_relid(partitionId);
2114 context = deparse_context_for(aliasname, partitionId);
2116 return deparse_expression((Node *) constr_expr, context, true, false);
2120 * pg_get_constraintdef
2122 * Returns the definition for the constraint, ie, everything that needs to
2123 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
2125 Datum
2126 pg_get_constraintdef(PG_FUNCTION_ARGS)
2128 Oid constraintId = PG_GETARG_OID(0);
2129 int prettyFlags;
2130 char *res;
2132 prettyFlags = PRETTYFLAG_INDENT;
2134 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2136 if (res == NULL)
2137 PG_RETURN_NULL();
2139 PG_RETURN_TEXT_P(string_to_text(res));
2142 Datum
2143 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
2145 Oid constraintId = PG_GETARG_OID(0);
2146 bool pretty = PG_GETARG_BOOL(1);
2147 int prettyFlags;
2148 char *res;
2150 prettyFlags = GET_PRETTY_FLAGS(pretty);
2152 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2154 if (res == NULL)
2155 PG_RETURN_NULL();
2157 PG_RETURN_TEXT_P(string_to_text(res));
2161 * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
2163 char *
2164 pg_get_constraintdef_command(Oid constraintId)
2166 return pg_get_constraintdef_worker(constraintId, true, 0, false);
2170 * As of 9.4, we now use an MVCC snapshot for this.
2172 static char *
2173 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
2174 int prettyFlags, bool missing_ok)
2176 HeapTuple tup;
2177 Form_pg_constraint conForm;
2178 StringInfoData buf;
2179 SysScanDesc scandesc;
2180 ScanKeyData scankey[1];
2181 Snapshot snapshot = RegisterSnapshot(GetTransactionSnapshot());
2182 Relation relation = table_open(ConstraintRelationId, AccessShareLock);
2184 ScanKeyInit(&scankey[0],
2185 Anum_pg_constraint_oid,
2186 BTEqualStrategyNumber, F_OIDEQ,
2187 ObjectIdGetDatum(constraintId));
2189 scandesc = systable_beginscan(relation,
2190 ConstraintOidIndexId,
2191 true,
2192 snapshot,
2194 scankey);
2197 * We later use the tuple with SysCacheGetAttr() as if we had obtained it
2198 * via SearchSysCache, which works fine.
2200 tup = systable_getnext(scandesc);
2202 UnregisterSnapshot(snapshot);
2204 if (!HeapTupleIsValid(tup))
2206 if (missing_ok)
2208 systable_endscan(scandesc);
2209 table_close(relation, AccessShareLock);
2210 return NULL;
2212 elog(ERROR, "could not find tuple for constraint %u", constraintId);
2215 conForm = (Form_pg_constraint) GETSTRUCT(tup);
2217 initStringInfo(&buf);
2219 if (fullCommand)
2221 if (OidIsValid(conForm->conrelid))
2224 * Currently, callers want ALTER TABLE (without ONLY) for CHECK
2225 * constraints, and other types of constraints don't inherit
2226 * anyway so it doesn't matter whether we say ONLY or not. Someday
2227 * we might need to let callers specify whether to put ONLY in the
2228 * command.
2230 appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
2231 generate_qualified_relation_name(conForm->conrelid),
2232 quote_identifier(NameStr(conForm->conname)));
2234 else
2236 /* Must be a domain constraint */
2237 Assert(OidIsValid(conForm->contypid));
2238 appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
2239 generate_qualified_type_name(conForm->contypid),
2240 quote_identifier(NameStr(conForm->conname)));
2244 switch (conForm->contype)
2246 case CONSTRAINT_FOREIGN:
2248 Datum val;
2249 bool isnull;
2250 const char *string;
2252 /* Start off the constraint definition */
2253 appendStringInfoString(&buf, "FOREIGN KEY (");
2255 /* Fetch and build referencing-column list */
2256 val = SysCacheGetAttrNotNull(CONSTROID, tup,
2257 Anum_pg_constraint_conkey);
2259 decompile_column_index_array(val, conForm->conrelid, &buf);
2261 /* add foreign relation name */
2262 appendStringInfo(&buf, ") REFERENCES %s(",
2263 generate_relation_name(conForm->confrelid,
2264 NIL));
2266 /* Fetch and build referenced-column list */
2267 val = SysCacheGetAttrNotNull(CONSTROID, tup,
2268 Anum_pg_constraint_confkey);
2270 decompile_column_index_array(val, conForm->confrelid, &buf);
2272 appendStringInfoChar(&buf, ')');
2274 /* Add match type */
2275 switch (conForm->confmatchtype)
2277 case FKCONSTR_MATCH_FULL:
2278 string = " MATCH FULL";
2279 break;
2280 case FKCONSTR_MATCH_PARTIAL:
2281 string = " MATCH PARTIAL";
2282 break;
2283 case FKCONSTR_MATCH_SIMPLE:
2284 string = "";
2285 break;
2286 default:
2287 elog(ERROR, "unrecognized confmatchtype: %d",
2288 conForm->confmatchtype);
2289 string = ""; /* keep compiler quiet */
2290 break;
2292 appendStringInfoString(&buf, string);
2294 /* Add ON UPDATE and ON DELETE clauses, if needed */
2295 switch (conForm->confupdtype)
2297 case FKCONSTR_ACTION_NOACTION:
2298 string = NULL; /* suppress default */
2299 break;
2300 case FKCONSTR_ACTION_RESTRICT:
2301 string = "RESTRICT";
2302 break;
2303 case FKCONSTR_ACTION_CASCADE:
2304 string = "CASCADE";
2305 break;
2306 case FKCONSTR_ACTION_SETNULL:
2307 string = "SET NULL";
2308 break;
2309 case FKCONSTR_ACTION_SETDEFAULT:
2310 string = "SET DEFAULT";
2311 break;
2312 default:
2313 elog(ERROR, "unrecognized confupdtype: %d",
2314 conForm->confupdtype);
2315 string = NULL; /* keep compiler quiet */
2316 break;
2318 if (string)
2319 appendStringInfo(&buf, " ON UPDATE %s", string);
2321 switch (conForm->confdeltype)
2323 case FKCONSTR_ACTION_NOACTION:
2324 string = NULL; /* suppress default */
2325 break;
2326 case FKCONSTR_ACTION_RESTRICT:
2327 string = "RESTRICT";
2328 break;
2329 case FKCONSTR_ACTION_CASCADE:
2330 string = "CASCADE";
2331 break;
2332 case FKCONSTR_ACTION_SETNULL:
2333 string = "SET NULL";
2334 break;
2335 case FKCONSTR_ACTION_SETDEFAULT:
2336 string = "SET DEFAULT";
2337 break;
2338 default:
2339 elog(ERROR, "unrecognized confdeltype: %d",
2340 conForm->confdeltype);
2341 string = NULL; /* keep compiler quiet */
2342 break;
2344 if (string)
2345 appendStringInfo(&buf, " ON DELETE %s", string);
2348 * Add columns specified to SET NULL or SET DEFAULT if
2349 * provided.
2351 val = SysCacheGetAttr(CONSTROID, tup,
2352 Anum_pg_constraint_confdelsetcols, &isnull);
2353 if (!isnull)
2355 appendStringInfoString(&buf, " (");
2356 decompile_column_index_array(val, conForm->conrelid, &buf);
2357 appendStringInfoChar(&buf, ')');
2360 break;
2362 case CONSTRAINT_PRIMARY:
2363 case CONSTRAINT_UNIQUE:
2365 Datum val;
2366 Oid indexId;
2367 int keyatts;
2368 HeapTuple indtup;
2370 /* Start off the constraint definition */
2371 if (conForm->contype == CONSTRAINT_PRIMARY)
2372 appendStringInfoString(&buf, "PRIMARY KEY ");
2373 else
2374 appendStringInfoString(&buf, "UNIQUE ");
2376 indexId = conForm->conindid;
2378 indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2379 if (!HeapTupleIsValid(indtup))
2380 elog(ERROR, "cache lookup failed for index %u", indexId);
2381 if (conForm->contype == CONSTRAINT_UNIQUE &&
2382 ((Form_pg_index) GETSTRUCT(indtup))->indnullsnotdistinct)
2383 appendStringInfoString(&buf, "NULLS NOT DISTINCT ");
2385 appendStringInfoChar(&buf, '(');
2387 /* Fetch and build target column list */
2388 val = SysCacheGetAttrNotNull(CONSTROID, tup,
2389 Anum_pg_constraint_conkey);
2391 keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2393 appendStringInfoChar(&buf, ')');
2395 /* Build including column list (from pg_index.indkeys) */
2396 val = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2397 Anum_pg_index_indnatts);
2398 if (DatumGetInt32(val) > keyatts)
2400 Datum cols;
2401 Datum *keys;
2402 int nKeys;
2403 int j;
2405 appendStringInfoString(&buf, " INCLUDE (");
2407 cols = SysCacheGetAttrNotNull(INDEXRELID, indtup,
2408 Anum_pg_index_indkey);
2410 deconstruct_array_builtin(DatumGetArrayTypeP(cols), INT2OID,
2411 &keys, NULL, &nKeys);
2413 for (j = keyatts; j < nKeys; j++)
2415 char *colName;
2417 colName = get_attname(conForm->conrelid,
2418 DatumGetInt16(keys[j]), false);
2419 if (j > keyatts)
2420 appendStringInfoString(&buf, ", ");
2421 appendStringInfoString(&buf, quote_identifier(colName));
2424 appendStringInfoChar(&buf, ')');
2426 ReleaseSysCache(indtup);
2428 /* XXX why do we only print these bits if fullCommand? */
2429 if (fullCommand && OidIsValid(indexId))
2431 char *options = flatten_reloptions(indexId);
2432 Oid tblspc;
2434 if (options)
2436 appendStringInfo(&buf, " WITH (%s)", options);
2437 pfree(options);
2441 * Print the tablespace, unless it's the database default.
2442 * This is to help ALTER TABLE usage of this facility,
2443 * which needs this behavior to recreate exact catalog
2444 * state.
2446 tblspc = get_rel_tablespace(indexId);
2447 if (OidIsValid(tblspc))
2448 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2449 quote_identifier(get_tablespace_name(tblspc)));
2452 break;
2454 case CONSTRAINT_CHECK:
2456 Datum val;
2457 char *conbin;
2458 char *consrc;
2459 Node *expr;
2460 List *context;
2462 /* Fetch constraint expression in parsetree form */
2463 val = SysCacheGetAttrNotNull(CONSTROID, tup,
2464 Anum_pg_constraint_conbin);
2466 conbin = TextDatumGetCString(val);
2467 expr = stringToNode(conbin);
2469 /* Set up deparsing context for Var nodes in constraint */
2470 if (conForm->conrelid != InvalidOid)
2472 /* relation constraint */
2473 context = deparse_context_for(get_relation_name(conForm->conrelid),
2474 conForm->conrelid);
2476 else
2478 /* domain constraint --- can't have Vars */
2479 context = NIL;
2482 consrc = deparse_expression_pretty(expr, context, false, false,
2483 prettyFlags, 0);
2486 * Now emit the constraint definition, adding NO INHERIT if
2487 * necessary.
2489 * There are cases where the constraint expression will be
2490 * fully parenthesized and we don't need the outer parens ...
2491 * but there are other cases where we do need 'em. Be
2492 * conservative for now.
2494 * Note that simply checking for leading '(' and trailing ')'
2495 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2497 appendStringInfo(&buf, "CHECK (%s)%s",
2498 consrc,
2499 conForm->connoinherit ? " NO INHERIT" : "");
2500 break;
2502 case CONSTRAINT_TRIGGER:
2505 * There isn't an ALTER TABLE syntax for creating a user-defined
2506 * constraint trigger, but it seems better to print something than
2507 * throw an error; if we throw error then this function couldn't
2508 * safely be applied to all rows of pg_constraint.
2510 appendStringInfoString(&buf, "TRIGGER");
2511 break;
2512 case CONSTRAINT_EXCLUSION:
2514 Oid indexOid = conForm->conindid;
2515 Datum val;
2516 Datum *elems;
2517 int nElems;
2518 int i;
2519 Oid *operators;
2521 /* Extract operator OIDs from the pg_constraint tuple */
2522 val = SysCacheGetAttrNotNull(CONSTROID, tup,
2523 Anum_pg_constraint_conexclop);
2525 deconstruct_array_builtin(DatumGetArrayTypeP(val), OIDOID,
2526 &elems, NULL, &nElems);
2528 operators = (Oid *) palloc(nElems * sizeof(Oid));
2529 for (i = 0; i < nElems; i++)
2530 operators[i] = DatumGetObjectId(elems[i]);
2532 /* pg_get_indexdef_worker does the rest */
2533 /* suppress tablespace because pg_dump wants it that way */
2534 appendStringInfoString(&buf,
2535 pg_get_indexdef_worker(indexOid,
2537 operators,
2538 false,
2539 false,
2540 false,
2541 false,
2542 prettyFlags,
2543 false));
2544 break;
2546 default:
2547 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2548 break;
2551 if (conForm->condeferrable)
2552 appendStringInfoString(&buf, " DEFERRABLE");
2553 if (conForm->condeferred)
2554 appendStringInfoString(&buf, " INITIALLY DEFERRED");
2555 if (!conForm->convalidated)
2556 appendStringInfoString(&buf, " NOT VALID");
2558 /* Cleanup */
2559 systable_endscan(scandesc);
2560 table_close(relation, AccessShareLock);
2562 return buf.data;
2567 * Convert an int16[] Datum into a comma-separated list of column names
2568 * for the indicated relation; append the list to buf. Returns the number
2569 * of keys.
2571 static int
2572 decompile_column_index_array(Datum column_index_array, Oid relId,
2573 StringInfo buf)
2575 Datum *keys;
2576 int nKeys;
2577 int j;
2579 /* Extract data from array of int16 */
2580 deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID,
2581 &keys, NULL, &nKeys);
2583 for (j = 0; j < nKeys; j++)
2585 char *colName;
2587 colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2589 if (j == 0)
2590 appendStringInfoString(buf, quote_identifier(colName));
2591 else
2592 appendStringInfo(buf, ", %s", quote_identifier(colName));
2595 return nKeys;
2599 /* ----------
2600 * pg_get_expr - Decompile an expression tree
2602 * Input: an expression tree in nodeToString form, and a relation OID
2604 * Output: reverse-listed expression
2606 * Currently, the expression can only refer to a single relation, namely
2607 * the one specified by the second parameter. This is sufficient for
2608 * partial indexes, column default expressions, etc. We also support
2609 * Var-free expressions, for which the OID can be InvalidOid.
2611 * If the OID is nonzero but not actually valid, don't throw an error,
2612 * just return NULL. This is a bit questionable, but it's what we've
2613 * done historically, and it can help avoid unwanted failures when
2614 * examining catalog entries for just-deleted relations.
2616 * We expect this function to work, or throw a reasonably clean error,
2617 * for any node tree that can appear in a catalog pg_node_tree column.
2618 * Query trees, such as those appearing in pg_rewrite.ev_action, are
2619 * not supported. Nor are expressions in more than one relation, which
2620 * can appear in places like pg_rewrite.ev_qual.
2621 * ----------
2623 Datum
2624 pg_get_expr(PG_FUNCTION_ARGS)
2626 text *expr = PG_GETARG_TEXT_PP(0);
2627 Oid relid = PG_GETARG_OID(1);
2628 text *result;
2629 int prettyFlags;
2631 prettyFlags = PRETTYFLAG_INDENT;
2633 result = pg_get_expr_worker(expr, relid, prettyFlags);
2634 if (result)
2635 PG_RETURN_TEXT_P(result);
2636 else
2637 PG_RETURN_NULL();
2640 Datum
2641 pg_get_expr_ext(PG_FUNCTION_ARGS)
2643 text *expr = PG_GETARG_TEXT_PP(0);
2644 Oid relid = PG_GETARG_OID(1);
2645 bool pretty = PG_GETARG_BOOL(2);
2646 text *result;
2647 int prettyFlags;
2649 prettyFlags = GET_PRETTY_FLAGS(pretty);
2651 result = pg_get_expr_worker(expr, relid, prettyFlags);
2652 if (result)
2653 PG_RETURN_TEXT_P(result);
2654 else
2655 PG_RETURN_NULL();
2658 static text *
2659 pg_get_expr_worker(text *expr, Oid relid, int prettyFlags)
2661 Node *node;
2662 Node *tst;
2663 Relids relids;
2664 List *context;
2665 char *exprstr;
2666 Relation rel = NULL;
2667 char *str;
2669 /* Convert input pg_node_tree (really TEXT) object to C string */
2670 exprstr = text_to_cstring(expr);
2672 /* Convert expression to node tree */
2673 node = (Node *) stringToNode(exprstr);
2675 pfree(exprstr);
2678 * Throw error if the input is a querytree rather than an expression tree.
2679 * While we could support queries here, there seems no very good reason
2680 * to. In most such catalog columns, we'll see a List of Query nodes, or
2681 * even nested Lists, so drill down to a non-List node before checking.
2683 tst = node;
2684 while (tst && IsA(tst, List))
2685 tst = linitial((List *) tst);
2686 if (tst && IsA(tst, Query))
2687 ereport(ERROR,
2688 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2689 errmsg("input is a query, not an expression")));
2692 * Throw error if the expression contains Vars we won't be able to
2693 * deparse.
2695 relids = pull_varnos(NULL, node);
2696 if (OidIsValid(relid))
2698 if (!bms_is_subset(relids, bms_make_singleton(1)))
2699 ereport(ERROR,
2700 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2701 errmsg("expression contains variables of more than one relation")));
2703 else
2705 if (!bms_is_empty(relids))
2706 ereport(ERROR,
2707 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2708 errmsg("expression contains variables")));
2712 * Prepare deparse context if needed. If we are deparsing with a relid,
2713 * we need to transiently open and lock the rel, to make sure it won't go
2714 * away underneath us. (set_relation_column_names would lock it anyway,
2715 * so this isn't really introducing any new behavior.)
2717 if (OidIsValid(relid))
2719 rel = try_relation_open(relid, AccessShareLock);
2720 if (rel == NULL)
2721 return NULL;
2722 context = deparse_context_for(RelationGetRelationName(rel), relid);
2724 else
2725 context = NIL;
2727 /* Deparse */
2728 str = deparse_expression_pretty(node, context, false, false,
2729 prettyFlags, 0);
2731 if (rel != NULL)
2732 relation_close(rel, AccessShareLock);
2734 return string_to_text(str);
2738 /* ----------
2739 * pg_get_userbyid - Get a user name by roleid and
2740 * fallback to 'unknown (OID=n)'
2741 * ----------
2743 Datum
2744 pg_get_userbyid(PG_FUNCTION_ARGS)
2746 Oid roleid = PG_GETARG_OID(0);
2747 Name result;
2748 HeapTuple roletup;
2749 Form_pg_authid role_rec;
2752 * Allocate space for the result
2754 result = (Name) palloc(NAMEDATALEN);
2755 memset(NameStr(*result), 0, NAMEDATALEN);
2758 * Get the pg_authid entry and print the result
2760 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2761 if (HeapTupleIsValid(roletup))
2763 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2764 *result = role_rec->rolname;
2765 ReleaseSysCache(roletup);
2767 else
2768 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2770 PG_RETURN_NAME(result);
2775 * pg_get_serial_sequence
2776 * Get the name of the sequence used by an identity or serial column,
2777 * formatted suitably for passing to setval, nextval or currval.
2778 * First parameter is not treated as double-quoted, second parameter
2779 * is --- see documentation for reason.
2781 Datum
2782 pg_get_serial_sequence(PG_FUNCTION_ARGS)
2784 text *tablename = PG_GETARG_TEXT_PP(0);
2785 text *columnname = PG_GETARG_TEXT_PP(1);
2786 RangeVar *tablerv;
2787 Oid tableOid;
2788 char *column;
2789 AttrNumber attnum;
2790 Oid sequenceId = InvalidOid;
2791 Relation depRel;
2792 ScanKeyData key[3];
2793 SysScanDesc scan;
2794 HeapTuple tup;
2796 /* Look up table name. Can't lock it - we might not have privileges. */
2797 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2798 tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2800 /* Get the number of the column */
2801 column = text_to_cstring(columnname);
2803 attnum = get_attnum(tableOid, column);
2804 if (attnum == InvalidAttrNumber)
2805 ereport(ERROR,
2806 (errcode(ERRCODE_UNDEFINED_COLUMN),
2807 errmsg("column \"%s\" of relation \"%s\" does not exist",
2808 column, tablerv->relname)));
2810 /* Search the dependency table for the dependent sequence */
2811 depRel = table_open(DependRelationId, AccessShareLock);
2813 ScanKeyInit(&key[0],
2814 Anum_pg_depend_refclassid,
2815 BTEqualStrategyNumber, F_OIDEQ,
2816 ObjectIdGetDatum(RelationRelationId));
2817 ScanKeyInit(&key[1],
2818 Anum_pg_depend_refobjid,
2819 BTEqualStrategyNumber, F_OIDEQ,
2820 ObjectIdGetDatum(tableOid));
2821 ScanKeyInit(&key[2],
2822 Anum_pg_depend_refobjsubid,
2823 BTEqualStrategyNumber, F_INT4EQ,
2824 Int32GetDatum(attnum));
2826 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2827 NULL, 3, key);
2829 while (HeapTupleIsValid(tup = systable_getnext(scan)))
2831 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2834 * Look for an auto dependency (serial column) or internal dependency
2835 * (identity column) of a sequence on a column. (We need the relkind
2836 * test because indexes can also have auto dependencies on columns.)
2838 if (deprec->classid == RelationRelationId &&
2839 deprec->objsubid == 0 &&
2840 (deprec->deptype == DEPENDENCY_AUTO ||
2841 deprec->deptype == DEPENDENCY_INTERNAL) &&
2842 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2844 sequenceId = deprec->objid;
2845 break;
2849 systable_endscan(scan);
2850 table_close(depRel, AccessShareLock);
2852 if (OidIsValid(sequenceId))
2854 char *result;
2856 result = generate_qualified_relation_name(sequenceId);
2858 PG_RETURN_TEXT_P(string_to_text(result));
2861 PG_RETURN_NULL();
2866 * pg_get_functiondef
2867 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2868 * the specified function.
2870 * Note: if you change the output format of this function, be careful not
2871 * to break psql's rules (in \ef and \sf) for identifying the start of the
2872 * function body. To wit: the function body starts on a line that begins with
2873 * "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
2875 Datum
2876 pg_get_functiondef(PG_FUNCTION_ARGS)
2878 Oid funcid = PG_GETARG_OID(0);
2879 StringInfoData buf;
2880 StringInfoData dq;
2881 HeapTuple proctup;
2882 Form_pg_proc proc;
2883 bool isfunction;
2884 Datum tmp;
2885 bool isnull;
2886 const char *prosrc;
2887 const char *name;
2888 const char *nsp;
2889 float4 procost;
2890 int oldlen;
2892 initStringInfo(&buf);
2894 /* Look up the function */
2895 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2896 if (!HeapTupleIsValid(proctup))
2897 PG_RETURN_NULL();
2899 proc = (Form_pg_proc) GETSTRUCT(proctup);
2900 name = NameStr(proc->proname);
2902 if (proc->prokind == PROKIND_AGGREGATE)
2903 ereport(ERROR,
2904 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2905 errmsg("\"%s\" is an aggregate function", name)));
2907 isfunction = (proc->prokind != PROKIND_PROCEDURE);
2910 * We always qualify the function name, to ensure the right function gets
2911 * replaced.
2913 nsp = get_namespace_name_or_temp(proc->pronamespace);
2914 appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2915 isfunction ? "FUNCTION" : "PROCEDURE",
2916 quote_qualified_identifier(nsp, name));
2917 (void) print_function_arguments(&buf, proctup, false, true);
2918 appendStringInfoString(&buf, ")\n");
2919 if (isfunction)
2921 appendStringInfoString(&buf, " RETURNS ");
2922 print_function_rettype(&buf, proctup);
2923 appendStringInfoChar(&buf, '\n');
2926 print_function_trftypes(&buf, proctup);
2928 appendStringInfo(&buf, " LANGUAGE %s\n",
2929 quote_identifier(get_language_name(proc->prolang, false)));
2931 /* Emit some miscellaneous options on one line */
2932 oldlen = buf.len;
2934 if (proc->prokind == PROKIND_WINDOW)
2935 appendStringInfoString(&buf, " WINDOW");
2936 switch (proc->provolatile)
2938 case PROVOLATILE_IMMUTABLE:
2939 appendStringInfoString(&buf, " IMMUTABLE");
2940 break;
2941 case PROVOLATILE_STABLE:
2942 appendStringInfoString(&buf, " STABLE");
2943 break;
2944 case PROVOLATILE_VOLATILE:
2945 break;
2948 switch (proc->proparallel)
2950 case PROPARALLEL_SAFE:
2951 appendStringInfoString(&buf, " PARALLEL SAFE");
2952 break;
2953 case PROPARALLEL_RESTRICTED:
2954 appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2955 break;
2956 case PROPARALLEL_UNSAFE:
2957 break;
2960 if (proc->proisstrict)
2961 appendStringInfoString(&buf, " STRICT");
2962 if (proc->prosecdef)
2963 appendStringInfoString(&buf, " SECURITY DEFINER");
2964 if (proc->proleakproof)
2965 appendStringInfoString(&buf, " LEAKPROOF");
2967 /* This code for the default cost and rows should match functioncmds.c */
2968 if (proc->prolang == INTERNALlanguageId ||
2969 proc->prolang == ClanguageId)
2970 procost = 1;
2971 else
2972 procost = 100;
2973 if (proc->procost != procost)
2974 appendStringInfo(&buf, " COST %g", proc->procost);
2976 if (proc->prorows > 0 && proc->prorows != 1000)
2977 appendStringInfo(&buf, " ROWS %g", proc->prorows);
2979 if (proc->prosupport)
2981 Oid argtypes[1];
2984 * We should qualify the support function's name if it wouldn't be
2985 * resolved by lookup in the current search path.
2987 argtypes[0] = INTERNALOID;
2988 appendStringInfo(&buf, " SUPPORT %s",
2989 generate_function_name(proc->prosupport, 1,
2990 NIL, argtypes,
2991 false, NULL, false));
2994 if (oldlen != buf.len)
2995 appendStringInfoChar(&buf, '\n');
2997 /* Emit any proconfig options, one per line */
2998 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
2999 if (!isnull)
3001 ArrayType *a = DatumGetArrayTypeP(tmp);
3002 int i;
3004 Assert(ARR_ELEMTYPE(a) == TEXTOID);
3005 Assert(ARR_NDIM(a) == 1);
3006 Assert(ARR_LBOUND(a)[0] == 1);
3008 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
3010 Datum d;
3012 d = array_ref(a, 1, &i,
3013 -1 /* varlenarray */ ,
3014 -1 /* TEXT's typlen */ ,
3015 false /* TEXT's typbyval */ ,
3016 TYPALIGN_INT /* TEXT's typalign */ ,
3017 &isnull);
3018 if (!isnull)
3020 char *configitem = TextDatumGetCString(d);
3021 char *pos;
3023 pos = strchr(configitem, '=');
3024 if (pos == NULL)
3025 continue;
3026 *pos++ = '\0';
3028 appendStringInfo(&buf, " SET %s TO ",
3029 quote_identifier(configitem));
3032 * Variables that are marked GUC_LIST_QUOTE were already fully
3033 * quoted by flatten_set_variable_args() before they were put
3034 * into the proconfig array. However, because the quoting
3035 * rules used there aren't exactly like SQL's, we have to
3036 * break the list value apart and then quote the elements as
3037 * string literals. (The elements may be double-quoted as-is,
3038 * but we can't just feed them to the SQL parser; it would do
3039 * the wrong thing with elements that are zero-length or
3040 * longer than NAMEDATALEN.)
3042 * Variables that are not so marked should just be emitted as
3043 * simple string literals. If the variable is not known to
3044 * guc.c, we'll do that; this makes it unsafe to use
3045 * GUC_LIST_QUOTE for extension variables.
3047 if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
3049 List *namelist;
3050 ListCell *lc;
3052 /* Parse string into list of identifiers */
3053 if (!SplitGUCList(pos, ',', &namelist))
3055 /* this shouldn't fail really */
3056 elog(ERROR, "invalid list syntax in proconfig item");
3058 foreach(lc, namelist)
3060 char *curname = (char *) lfirst(lc);
3062 simple_quote_literal(&buf, curname);
3063 if (lnext(namelist, lc))
3064 appendStringInfoString(&buf, ", ");
3067 else
3068 simple_quote_literal(&buf, pos);
3069 appendStringInfoChar(&buf, '\n');
3074 /* And finally the function definition ... */
3075 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3076 if (proc->prolang == SQLlanguageId && !isnull)
3078 print_function_sqlbody(&buf, proctup);
3080 else
3082 appendStringInfoString(&buf, "AS ");
3084 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
3085 if (!isnull)
3087 simple_quote_literal(&buf, TextDatumGetCString(tmp));
3088 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
3091 tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosrc);
3092 prosrc = TextDatumGetCString(tmp);
3095 * We always use dollar quoting. Figure out a suitable delimiter.
3097 * Since the user is likely to be editing the function body string, we
3098 * shouldn't use a short delimiter that he might easily create a
3099 * conflict with. Hence prefer "$function$"/"$procedure$", but extend
3100 * if needed.
3102 initStringInfo(&dq);
3103 appendStringInfoChar(&dq, '$');
3104 appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
3105 while (strstr(prosrc, dq.data) != NULL)
3106 appendStringInfoChar(&dq, 'x');
3107 appendStringInfoChar(&dq, '$');
3109 appendBinaryStringInfo(&buf, dq.data, dq.len);
3110 appendStringInfoString(&buf, prosrc);
3111 appendBinaryStringInfo(&buf, dq.data, dq.len);
3114 appendStringInfoChar(&buf, '\n');
3116 ReleaseSysCache(proctup);
3118 PG_RETURN_TEXT_P(string_to_text(buf.data));
3122 * pg_get_function_arguments
3123 * Get a nicely-formatted list of arguments for a function.
3124 * This is everything that would go between the parentheses in
3125 * CREATE FUNCTION.
3127 Datum
3128 pg_get_function_arguments(PG_FUNCTION_ARGS)
3130 Oid funcid = PG_GETARG_OID(0);
3131 StringInfoData buf;
3132 HeapTuple proctup;
3134 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3135 if (!HeapTupleIsValid(proctup))
3136 PG_RETURN_NULL();
3138 initStringInfo(&buf);
3140 (void) print_function_arguments(&buf, proctup, false, true);
3142 ReleaseSysCache(proctup);
3144 PG_RETURN_TEXT_P(string_to_text(buf.data));
3148 * pg_get_function_identity_arguments
3149 * Get a formatted list of arguments for a function.
3150 * This is everything that would go between the parentheses in
3151 * ALTER FUNCTION, etc. In particular, don't print defaults.
3153 Datum
3154 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
3156 Oid funcid = PG_GETARG_OID(0);
3157 StringInfoData buf;
3158 HeapTuple proctup;
3160 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3161 if (!HeapTupleIsValid(proctup))
3162 PG_RETURN_NULL();
3164 initStringInfo(&buf);
3166 (void) print_function_arguments(&buf, proctup, false, false);
3168 ReleaseSysCache(proctup);
3170 PG_RETURN_TEXT_P(string_to_text(buf.data));
3174 * pg_get_function_result
3175 * Get a nicely-formatted version of the result type of a function.
3176 * This is what would appear after RETURNS in CREATE FUNCTION.
3178 Datum
3179 pg_get_function_result(PG_FUNCTION_ARGS)
3181 Oid funcid = PG_GETARG_OID(0);
3182 StringInfoData buf;
3183 HeapTuple proctup;
3185 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3186 if (!HeapTupleIsValid(proctup))
3187 PG_RETURN_NULL();
3189 if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
3191 ReleaseSysCache(proctup);
3192 PG_RETURN_NULL();
3195 initStringInfo(&buf);
3197 print_function_rettype(&buf, proctup);
3199 ReleaseSysCache(proctup);
3201 PG_RETURN_TEXT_P(string_to_text(buf.data));
3205 * Guts of pg_get_function_result: append the function's return type
3206 * to the specified buffer.
3208 static void
3209 print_function_rettype(StringInfo buf, HeapTuple proctup)
3211 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3212 int ntabargs = 0;
3213 StringInfoData rbuf;
3215 initStringInfo(&rbuf);
3217 if (proc->proretset)
3219 /* It might be a table function; try to print the arguments */
3220 appendStringInfoString(&rbuf, "TABLE(");
3221 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
3222 if (ntabargs > 0)
3223 appendStringInfoChar(&rbuf, ')');
3224 else
3225 resetStringInfo(&rbuf);
3228 if (ntabargs == 0)
3230 /* Not a table function, so do the normal thing */
3231 if (proc->proretset)
3232 appendStringInfoString(&rbuf, "SETOF ");
3233 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
3236 appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
3240 * Common code for pg_get_function_arguments and pg_get_function_result:
3241 * append the desired subset of arguments to buf. We print only TABLE
3242 * arguments when print_table_args is true, and all the others when it's false.
3243 * We print argument defaults only if print_defaults is true.
3244 * Function return value is the number of arguments printed.
3246 static int
3247 print_function_arguments(StringInfo buf, HeapTuple proctup,
3248 bool print_table_args, bool print_defaults)
3250 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3251 int numargs;
3252 Oid *argtypes;
3253 char **argnames;
3254 char *argmodes;
3255 int insertorderbyat = -1;
3256 int argsprinted;
3257 int inputargno;
3258 int nlackdefaults;
3259 List *argdefaults = NIL;
3260 ListCell *nextargdefault = NULL;
3261 int i;
3263 numargs = get_func_arg_info(proctup,
3264 &argtypes, &argnames, &argmodes);
3266 nlackdefaults = numargs;
3267 if (print_defaults && proc->pronargdefaults > 0)
3269 Datum proargdefaults;
3270 bool isnull;
3272 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3273 Anum_pg_proc_proargdefaults,
3274 &isnull);
3275 if (!isnull)
3277 char *str;
3279 str = TextDatumGetCString(proargdefaults);
3280 argdefaults = castNode(List, stringToNode(str));
3281 pfree(str);
3282 nextargdefault = list_head(argdefaults);
3283 /* nlackdefaults counts only *input* arguments lacking defaults */
3284 nlackdefaults = proc->pronargs - list_length(argdefaults);
3288 /* Check for special treatment of ordered-set aggregates */
3289 if (proc->prokind == PROKIND_AGGREGATE)
3291 HeapTuple aggtup;
3292 Form_pg_aggregate agg;
3294 aggtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(proc->oid));
3295 if (!HeapTupleIsValid(aggtup))
3296 elog(ERROR, "cache lookup failed for aggregate %u",
3297 proc->oid);
3298 agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3299 if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3300 insertorderbyat = agg->aggnumdirectargs;
3301 ReleaseSysCache(aggtup);
3304 argsprinted = 0;
3305 inputargno = 0;
3306 for (i = 0; i < numargs; i++)
3308 Oid argtype = argtypes[i];
3309 char *argname = argnames ? argnames[i] : NULL;
3310 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3311 const char *modename;
3312 bool isinput;
3314 switch (argmode)
3316 case PROARGMODE_IN:
3319 * For procedures, explicitly mark all argument modes, so as
3320 * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
3322 if (proc->prokind == PROKIND_PROCEDURE)
3323 modename = "IN ";
3324 else
3325 modename = "";
3326 isinput = true;
3327 break;
3328 case PROARGMODE_INOUT:
3329 modename = "INOUT ";
3330 isinput = true;
3331 break;
3332 case PROARGMODE_OUT:
3333 modename = "OUT ";
3334 isinput = false;
3335 break;
3336 case PROARGMODE_VARIADIC:
3337 modename = "VARIADIC ";
3338 isinput = true;
3339 break;
3340 case PROARGMODE_TABLE:
3341 modename = "";
3342 isinput = false;
3343 break;
3344 default:
3345 elog(ERROR, "invalid parameter mode '%c'", argmode);
3346 modename = NULL; /* keep compiler quiet */
3347 isinput = false;
3348 break;
3350 if (isinput)
3351 inputargno++; /* this is a 1-based counter */
3353 if (print_table_args != (argmode == PROARGMODE_TABLE))
3354 continue;
3356 if (argsprinted == insertorderbyat)
3358 if (argsprinted)
3359 appendStringInfoChar(buf, ' ');
3360 appendStringInfoString(buf, "ORDER BY ");
3362 else if (argsprinted)
3363 appendStringInfoString(buf, ", ");
3365 appendStringInfoString(buf, modename);
3366 if (argname && argname[0])
3367 appendStringInfo(buf, "%s ", quote_identifier(argname));
3368 appendStringInfoString(buf, format_type_be(argtype));
3369 if (print_defaults && isinput && inputargno > nlackdefaults)
3371 Node *expr;
3373 Assert(nextargdefault != NULL);
3374 expr = (Node *) lfirst(nextargdefault);
3375 nextargdefault = lnext(argdefaults, nextargdefault);
3377 appendStringInfo(buf, " DEFAULT %s",
3378 deparse_expression(expr, NIL, false, false));
3380 argsprinted++;
3382 /* nasty hack: print the last arg twice for variadic ordered-set agg */
3383 if (argsprinted == insertorderbyat && i == numargs - 1)
3385 i--;
3386 /* aggs shouldn't have defaults anyway, but just to be sure ... */
3387 print_defaults = false;
3391 return argsprinted;
3394 static bool
3395 is_input_argument(int nth, const char *argmodes)
3397 return (!argmodes
3398 || argmodes[nth] == PROARGMODE_IN
3399 || argmodes[nth] == PROARGMODE_INOUT
3400 || argmodes[nth] == PROARGMODE_VARIADIC);
3404 * Append used transformed types to specified buffer
3406 static void
3407 print_function_trftypes(StringInfo buf, HeapTuple proctup)
3409 Oid *trftypes;
3410 int ntypes;
3412 ntypes = get_func_trftypes(proctup, &trftypes);
3413 if (ntypes > 0)
3415 int i;
3417 appendStringInfoString(buf, " TRANSFORM ");
3418 for (i = 0; i < ntypes; i++)
3420 if (i != 0)
3421 appendStringInfoString(buf, ", ");
3422 appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3424 appendStringInfoChar(buf, '\n');
3429 * Get textual representation of a function argument's default value. The
3430 * second argument of this function is the argument number among all arguments
3431 * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3432 * how information_schema.sql uses it.
3434 Datum
3435 pg_get_function_arg_default(PG_FUNCTION_ARGS)
3437 Oid funcid = PG_GETARG_OID(0);
3438 int32 nth_arg = PG_GETARG_INT32(1);
3439 HeapTuple proctup;
3440 Form_pg_proc proc;
3441 int numargs;
3442 Oid *argtypes;
3443 char **argnames;
3444 char *argmodes;
3445 int i;
3446 List *argdefaults;
3447 Node *node;
3448 char *str;
3449 int nth_inputarg;
3450 Datum proargdefaults;
3451 bool isnull;
3452 int nth_default;
3454 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3455 if (!HeapTupleIsValid(proctup))
3456 PG_RETURN_NULL();
3458 numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3459 if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3461 ReleaseSysCache(proctup);
3462 PG_RETURN_NULL();
3465 nth_inputarg = 0;
3466 for (i = 0; i < nth_arg; i++)
3467 if (is_input_argument(i, argmodes))
3468 nth_inputarg++;
3470 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3471 Anum_pg_proc_proargdefaults,
3472 &isnull);
3473 if (isnull)
3475 ReleaseSysCache(proctup);
3476 PG_RETURN_NULL();
3479 str = TextDatumGetCString(proargdefaults);
3480 argdefaults = castNode(List, stringToNode(str));
3481 pfree(str);
3483 proc = (Form_pg_proc) GETSTRUCT(proctup);
3486 * Calculate index into proargdefaults: proargdefaults corresponds to the
3487 * last N input arguments, where N = pronargdefaults.
3489 nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3491 if (nth_default < 0 || nth_default >= list_length(argdefaults))
3493 ReleaseSysCache(proctup);
3494 PG_RETURN_NULL();
3496 node = list_nth(argdefaults, nth_default);
3497 str = deparse_expression(node, NIL, false, false);
3499 ReleaseSysCache(proctup);
3501 PG_RETURN_TEXT_P(string_to_text(str));
3504 static void
3505 print_function_sqlbody(StringInfo buf, HeapTuple proctup)
3507 int numargs;
3508 Oid *argtypes;
3509 char **argnames;
3510 char *argmodes;
3511 deparse_namespace dpns = {0};
3512 Datum tmp;
3513 Node *n;
3515 dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
3516 numargs = get_func_arg_info(proctup,
3517 &argtypes, &argnames, &argmodes);
3518 dpns.numargs = numargs;
3519 dpns.argnames = argnames;
3521 tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosqlbody);
3522 n = stringToNode(TextDatumGetCString(tmp));
3524 if (IsA(n, List))
3526 List *stmts;
3527 ListCell *lc;
3529 stmts = linitial(castNode(List, n));
3531 appendStringInfoString(buf, "BEGIN ATOMIC\n");
3533 foreach(lc, stmts)
3535 Query *query = lfirst_node(Query, lc);
3537 /* It seems advisable to get at least AccessShareLock on rels */
3538 AcquireRewriteLocks(query, false, false);
3539 get_query_def(query, buf, list_make1(&dpns), NULL, false,
3540 PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1);
3541 appendStringInfoChar(buf, ';');
3542 appendStringInfoChar(buf, '\n');
3545 appendStringInfoString(buf, "END");
3547 else
3549 Query *query = castNode(Query, n);
3551 /* It seems advisable to get at least AccessShareLock on rels */
3552 AcquireRewriteLocks(query, false, false);
3553 get_query_def(query, buf, list_make1(&dpns), NULL, false,
3554 0, WRAP_COLUMN_DEFAULT, 0);
3558 Datum
3559 pg_get_function_sqlbody(PG_FUNCTION_ARGS)
3561 Oid funcid = PG_GETARG_OID(0);
3562 StringInfoData buf;
3563 HeapTuple proctup;
3564 bool isnull;
3566 initStringInfo(&buf);
3568 /* Look up the function */
3569 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3570 if (!HeapTupleIsValid(proctup))
3571 PG_RETURN_NULL();
3573 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3574 if (isnull)
3576 ReleaseSysCache(proctup);
3577 PG_RETURN_NULL();
3580 print_function_sqlbody(&buf, proctup);
3582 ReleaseSysCache(proctup);
3584 PG_RETURN_TEXT_P(cstring_to_text_with_len(buf.data, buf.len));
3589 * deparse_expression - General utility for deparsing expressions
3591 * calls deparse_expression_pretty with all prettyPrinting disabled
3593 char *
3594 deparse_expression(Node *expr, List *dpcontext,
3595 bool forceprefix, bool showimplicit)
3597 return deparse_expression_pretty(expr, dpcontext, forceprefix,
3598 showimplicit, 0, 0);
3601 /* ----------
3602 * deparse_expression_pretty - General utility for deparsing expressions
3604 * expr is the node tree to be deparsed. It must be a transformed expression
3605 * tree (ie, not the raw output of gram.y).
3607 * dpcontext is a list of deparse_namespace nodes representing the context
3608 * for interpreting Vars in the node tree. It can be NIL if no Vars are
3609 * expected.
3611 * forceprefix is true to force all Vars to be prefixed with their table names.
3613 * showimplicit is true to force all implicit casts to be shown explicitly.
3615 * Tries to pretty up the output according to prettyFlags and startIndent.
3617 * The result is a palloc'd string.
3618 * ----------
3620 static char *
3621 deparse_expression_pretty(Node *expr, List *dpcontext,
3622 bool forceprefix, bool showimplicit,
3623 int prettyFlags, int startIndent)
3625 StringInfoData buf;
3626 deparse_context context;
3628 initStringInfo(&buf);
3629 context.buf = &buf;
3630 context.namespaces = dpcontext;
3631 context.resultDesc = NULL;
3632 context.targetList = NIL;
3633 context.windowClause = NIL;
3634 context.varprefix = forceprefix;
3635 context.prettyFlags = prettyFlags;
3636 context.wrapColumn = WRAP_COLUMN_DEFAULT;
3637 context.indentLevel = startIndent;
3638 context.colNamesVisible = true;
3639 context.inGroupBy = false;
3640 context.varInOrderBy = false;
3641 context.appendparents = NULL;
3643 get_rule_expr(expr, &context, showimplicit);
3645 return buf.data;
3648 /* ----------
3649 * deparse_context_for - Build deparse context for a single relation
3651 * Given the reference name (alias) and OID of a relation, build deparsing
3652 * context for an expression referencing only that relation (as varno 1,
3653 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
3654 * ----------
3656 List *
3657 deparse_context_for(const char *aliasname, Oid relid)
3659 deparse_namespace *dpns;
3660 RangeTblEntry *rte;
3662 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3664 /* Build a minimal RTE for the rel */
3665 rte = makeNode(RangeTblEntry);
3666 rte->rtekind = RTE_RELATION;
3667 rte->relid = relid;
3668 rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3669 rte->rellockmode = AccessShareLock;
3670 rte->alias = makeAlias(aliasname, NIL);
3671 rte->eref = rte->alias;
3672 rte->lateral = false;
3673 rte->inh = false;
3674 rte->inFromCl = true;
3676 /* Build one-element rtable */
3677 dpns->rtable = list_make1(rte);
3678 dpns->subplans = NIL;
3679 dpns->ctes = NIL;
3680 dpns->appendrels = NULL;
3681 set_rtable_names(dpns, NIL, NULL);
3682 set_simple_column_names(dpns);
3684 /* Return a one-deep namespace stack */
3685 return list_make1(dpns);
3689 * deparse_context_for_plan_tree - Build deparse context for a Plan tree
3691 * When deparsing an expression in a Plan tree, we use the plan's rangetable
3692 * to resolve names of simple Vars. The initialization of column names for
3693 * this is rather expensive if the rangetable is large, and it'll be the same
3694 * for every expression in the Plan tree; so we do it just once and re-use
3695 * the result of this function for each expression. (Note that the result
3696 * is not usable until set_deparse_context_plan() is applied to it.)
3698 * In addition to the PlannedStmt, pass the per-RTE alias names
3699 * assigned by a previous call to select_rtable_names_for_explain.
3701 List *
3702 deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
3704 deparse_namespace *dpns;
3706 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3708 /* Initialize fields that stay the same across the whole plan tree */
3709 dpns->rtable = pstmt->rtable;
3710 dpns->rtable_names = rtable_names;
3711 dpns->subplans = pstmt->subplans;
3712 dpns->ctes = NIL;
3713 if (pstmt->appendRelations)
3715 /* Set up the array, indexed by child relid */
3716 int ntables = list_length(dpns->rtable);
3717 ListCell *lc;
3719 dpns->appendrels = (AppendRelInfo **)
3720 palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3721 foreach(lc, pstmt->appendRelations)
3723 AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3724 Index crelid = appinfo->child_relid;
3726 Assert(crelid > 0 && crelid <= ntables);
3727 Assert(dpns->appendrels[crelid] == NULL);
3728 dpns->appendrels[crelid] = appinfo;
3731 else
3732 dpns->appendrels = NULL; /* don't need it */
3735 * Set up column name aliases. We will get rather bogus results for join
3736 * RTEs, but that doesn't matter because plan trees don't contain any join
3737 * alias Vars.
3739 set_simple_column_names(dpns);
3741 /* Return a one-deep namespace stack */
3742 return list_make1(dpns);
3746 * set_deparse_context_plan - Specify Plan node containing expression
3748 * When deparsing an expression in a Plan tree, we might have to resolve
3749 * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
3750 * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
3751 * can be resolved by drilling down into the left and right child plans.
3752 * Similarly, INDEX_VAR references can be resolved by reference to the
3753 * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
3754 * ForeignScan and CustomScan nodes. (Note that we don't currently support
3755 * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
3756 * for those, we can only deparse the indexqualorig fields, which won't
3757 * contain INDEX_VAR Vars.)
3759 * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
3760 * the most-closely-nested first. This is needed to resolve PARAM_EXEC
3761 * Params. Note we assume that all the Plan nodes share the same rtable.
3763 * Once this function has been called, deparse_expression() can be called on
3764 * subsidiary expression(s) of the specified Plan node. To deparse
3765 * expressions of a different Plan node in the same Plan tree, re-call this
3766 * function to identify the new parent Plan node.
3768 * The result is the same List passed in; this is a notational convenience.
3770 List *
3771 set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
3773 deparse_namespace *dpns;
3775 /* Should always have one-entry namespace list for Plan deparsing */
3776 Assert(list_length(dpcontext) == 1);
3777 dpns = (deparse_namespace *) linitial(dpcontext);
3779 /* Set our attention on the specific plan node passed in */
3780 dpns->ancestors = ancestors;
3781 set_deparse_plan(dpns, plan);
3783 return dpcontext;
3787 * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
3789 * Determine the relation aliases we'll use during an EXPLAIN operation.
3790 * This is just a frontend to set_rtable_names. We have to expose the aliases
3791 * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
3793 List *
3794 select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
3796 deparse_namespace dpns;
3798 memset(&dpns, 0, sizeof(dpns));
3799 dpns.rtable = rtable;
3800 dpns.subplans = NIL;
3801 dpns.ctes = NIL;
3802 dpns.appendrels = NULL;
3803 set_rtable_names(&dpns, NIL, rels_used);
3804 /* We needn't bother computing column aliases yet */
3806 return dpns.rtable_names;
3810 * set_rtable_names: select RTE aliases to be used in printing a query
3812 * We fill in dpns->rtable_names with a list of names that is one-for-one with
3813 * the already-filled dpns->rtable list. Each RTE name is unique among those
3814 * in the new namespace plus any ancestor namespaces listed in
3815 * parent_namespaces.
3817 * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
3819 * Note that this function is only concerned with relation names, not column
3820 * names.
3822 static void
3823 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
3824 Bitmapset *rels_used)
3826 HASHCTL hash_ctl;
3827 HTAB *names_hash;
3828 NameHashEntry *hentry;
3829 bool found;
3830 int rtindex;
3831 ListCell *lc;
3833 dpns->rtable_names = NIL;
3834 /* nothing more to do if empty rtable */
3835 if (dpns->rtable == NIL)
3836 return;
3839 * We use a hash table to hold known names, so that this process is O(N)
3840 * not O(N^2) for N names.
3842 hash_ctl.keysize = NAMEDATALEN;
3843 hash_ctl.entrysize = sizeof(NameHashEntry);
3844 hash_ctl.hcxt = CurrentMemoryContext;
3845 names_hash = hash_create("set_rtable_names names",
3846 list_length(dpns->rtable),
3847 &hash_ctl,
3848 HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
3850 /* Preload the hash table with names appearing in parent_namespaces */
3851 foreach(lc, parent_namespaces)
3853 deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
3854 ListCell *lc2;
3856 foreach(lc2, olddpns->rtable_names)
3858 char *oldname = (char *) lfirst(lc2);
3860 if (oldname == NULL)
3861 continue;
3862 hentry = (NameHashEntry *) hash_search(names_hash,
3863 oldname,
3864 HASH_ENTER,
3865 &found);
3866 /* we do not complain about duplicate names in parent namespaces */
3867 hentry->counter = 0;
3871 /* Now we can scan the rtable */
3872 rtindex = 1;
3873 foreach(lc, dpns->rtable)
3875 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3876 char *refname;
3878 /* Just in case this takes an unreasonable amount of time ... */
3879 CHECK_FOR_INTERRUPTS();
3881 if (rels_used && !bms_is_member(rtindex, rels_used))
3883 /* Ignore unreferenced RTE */
3884 refname = NULL;
3886 else if (rte->alias)
3888 /* If RTE has a user-defined alias, prefer that */
3889 refname = rte->alias->aliasname;
3891 else if (rte->rtekind == RTE_RELATION)
3893 /* Use the current actual name of the relation */
3894 refname = get_rel_name(rte->relid);
3896 else if (rte->rtekind == RTE_JOIN)
3898 /* Unnamed join has no refname */
3899 refname = NULL;
3901 else
3903 /* Otherwise use whatever the parser assigned */
3904 refname = rte->eref->aliasname;
3908 * If the selected name isn't unique, append digits to make it so, and
3909 * make a new hash entry for it once we've got a unique name. For a
3910 * very long input name, we might have to truncate to stay within
3911 * NAMEDATALEN.
3913 if (refname)
3915 hentry = (NameHashEntry *) hash_search(names_hash,
3916 refname,
3917 HASH_ENTER,
3918 &found);
3919 if (found)
3921 /* Name already in use, must choose a new one */
3922 int refnamelen = strlen(refname);
3923 char *modname = (char *) palloc(refnamelen + 16);
3924 NameHashEntry *hentry2;
3928 hentry->counter++;
3929 for (;;)
3931 memcpy(modname, refname, refnamelen);
3932 sprintf(modname + refnamelen, "_%d", hentry->counter);
3933 if (strlen(modname) < NAMEDATALEN)
3934 break;
3935 /* drop chars from refname to keep all the digits */
3936 refnamelen = pg_mbcliplen(refname, refnamelen,
3937 refnamelen - 1);
3939 hentry2 = (NameHashEntry *) hash_search(names_hash,
3940 modname,
3941 HASH_ENTER,
3942 &found);
3943 } while (found);
3944 hentry2->counter = 0; /* init new hash entry */
3945 refname = modname;
3947 else
3949 /* Name not previously used, need only initialize hentry */
3950 hentry->counter = 0;
3954 dpns->rtable_names = lappend(dpns->rtable_names, refname);
3955 rtindex++;
3958 hash_destroy(names_hash);
3962 * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
3964 * For convenience, this is defined to initialize the deparse_namespace struct
3965 * from scratch.
3967 static void
3968 set_deparse_for_query(deparse_namespace *dpns, Query *query,
3969 List *parent_namespaces)
3971 ListCell *lc;
3972 ListCell *lc2;
3974 /* Initialize *dpns and fill rtable/ctes links */
3975 memset(dpns, 0, sizeof(deparse_namespace));
3976 dpns->rtable = query->rtable;
3977 dpns->subplans = NIL;
3978 dpns->ctes = query->cteList;
3979 dpns->appendrels = NULL;
3981 /* Assign a unique relation alias to each RTE */
3982 set_rtable_names(dpns, parent_namespaces, NULL);
3984 /* Initialize dpns->rtable_columns to contain zeroed structs */
3985 dpns->rtable_columns = NIL;
3986 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3987 dpns->rtable_columns = lappend(dpns->rtable_columns,
3988 palloc0(sizeof(deparse_columns)));
3990 /* If it's a utility query, it won't have a jointree */
3991 if (query->jointree)
3993 /* Detect whether global uniqueness of USING names is needed */
3994 dpns->unique_using =
3995 has_dangerous_join_using(dpns, (Node *) query->jointree);
3998 * Select names for columns merged by USING, via a recursive pass over
3999 * the query jointree.
4001 set_using_names(dpns, (Node *) query->jointree, NIL);
4005 * Now assign remaining column aliases for each RTE. We do this in a
4006 * linear scan of the rtable, so as to process RTEs whether or not they
4007 * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
4008 * etc). JOIN RTEs must be processed after their children, but this is
4009 * okay because they appear later in the rtable list than their children
4010 * (cf Asserts in identify_join_columns()).
4012 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4014 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4015 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4017 if (rte->rtekind == RTE_JOIN)
4018 set_join_column_names(dpns, rte, colinfo);
4019 else
4020 set_relation_column_names(dpns, rte, colinfo);
4025 * set_simple_column_names: fill in column aliases for non-query situations
4027 * This handles EXPLAIN and cases where we only have relation RTEs. Without
4028 * a join tree, we can't do anything smart about join RTEs, but we don't
4029 * need to (note that EXPLAIN should never see join alias Vars anyway).
4030 * If we do hit a join RTE we'll just process it like a non-table base RTE.
4032 static void
4033 set_simple_column_names(deparse_namespace *dpns)
4035 ListCell *lc;
4036 ListCell *lc2;
4038 /* Initialize dpns->rtable_columns to contain zeroed structs */
4039 dpns->rtable_columns = NIL;
4040 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
4041 dpns->rtable_columns = lappend(dpns->rtable_columns,
4042 palloc0(sizeof(deparse_columns)));
4044 /* Assign unique column aliases within each RTE */
4045 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
4047 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
4048 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
4050 set_relation_column_names(dpns, rte, colinfo);
4055 * has_dangerous_join_using: search jointree for unnamed JOIN USING
4057 * Merged columns of a JOIN USING may act differently from either of the input
4058 * columns, either because they are merged with COALESCE (in a FULL JOIN) or
4059 * because an implicit coercion of the underlying input column is required.
4060 * In such a case the column must be referenced as a column of the JOIN not as
4061 * a column of either input. And this is problematic if the join is unnamed
4062 * (alias-less): we cannot qualify the column's name with an RTE name, since
4063 * there is none. (Forcibly assigning an alias to the join is not a solution,
4064 * since that will prevent legal references to tables below the join.)
4065 * To ensure that every column in the query is unambiguously referenceable,
4066 * we must assign such merged columns names that are globally unique across
4067 * the whole query, aliasing other columns out of the way as necessary.
4069 * Because the ensuing re-aliasing is fairly damaging to the readability of
4070 * the query, we don't do this unless we have to. So, we must pre-scan
4071 * the join tree to see if we have to, before starting set_using_names().
4073 static bool
4074 has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
4076 if (IsA(jtnode, RangeTblRef))
4078 /* nothing to do here */
4080 else if (IsA(jtnode, FromExpr))
4082 FromExpr *f = (FromExpr *) jtnode;
4083 ListCell *lc;
4085 foreach(lc, f->fromlist)
4087 if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
4088 return true;
4091 else if (IsA(jtnode, JoinExpr))
4093 JoinExpr *j = (JoinExpr *) jtnode;
4095 /* Is it an unnamed JOIN with USING? */
4096 if (j->alias == NULL && j->usingClause)
4099 * Yes, so check each join alias var to see if any of them are not
4100 * simple references to underlying columns. If so, we have a
4101 * dangerous situation and must pick unique aliases.
4103 RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
4105 /* We need only examine the merged columns */
4106 for (int i = 0; i < jrte->joinmergedcols; i++)
4108 Node *aliasvar = list_nth(jrte->joinaliasvars, i);
4110 if (!IsA(aliasvar, Var))
4111 return true;
4115 /* Nope, but inspect children */
4116 if (has_dangerous_join_using(dpns, j->larg))
4117 return true;
4118 if (has_dangerous_join_using(dpns, j->rarg))
4119 return true;
4121 else
4122 elog(ERROR, "unrecognized node type: %d",
4123 (int) nodeTag(jtnode));
4124 return false;
4128 * set_using_names: select column aliases to be used for merged USING columns
4130 * We do this during a recursive descent of the query jointree.
4131 * dpns->unique_using must already be set to determine the global strategy.
4133 * Column alias info is saved in the dpns->rtable_columns list, which is
4134 * assumed to be filled with pre-zeroed deparse_columns structs.
4136 * parentUsing is a list of all USING aliases assigned in parent joins of
4137 * the current jointree node. (The passed-in list must not be modified.)
4139 static void
4140 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
4142 if (IsA(jtnode, RangeTblRef))
4144 /* nothing to do now */
4146 else if (IsA(jtnode, FromExpr))
4148 FromExpr *f = (FromExpr *) jtnode;
4149 ListCell *lc;
4151 foreach(lc, f->fromlist)
4152 set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
4154 else if (IsA(jtnode, JoinExpr))
4156 JoinExpr *j = (JoinExpr *) jtnode;
4157 RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
4158 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
4159 int *leftattnos;
4160 int *rightattnos;
4161 deparse_columns *leftcolinfo;
4162 deparse_columns *rightcolinfo;
4163 int i;
4164 ListCell *lc;
4166 /* Get info about the shape of the join */
4167 identify_join_columns(j, rte, colinfo);
4168 leftattnos = colinfo->leftattnos;
4169 rightattnos = colinfo->rightattnos;
4171 /* Look up the not-yet-filled-in child deparse_columns structs */
4172 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4173 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4176 * If this join is unnamed, then we cannot substitute new aliases at
4177 * this level, so any name requirements pushed down to here must be
4178 * pushed down again to the children.
4180 if (rte->alias == NULL)
4182 for (i = 0; i < colinfo->num_cols; i++)
4184 char *colname = colinfo->colnames[i];
4186 if (colname == NULL)
4187 continue;
4189 /* Push down to left column, unless it's a system column */
4190 if (leftattnos[i] > 0)
4192 expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4193 leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4196 /* Same on the righthand side */
4197 if (rightattnos[i] > 0)
4199 expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4200 rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4206 * If there's a USING clause, select the USING column names and push
4207 * those names down to the children. We have two strategies:
4209 * If dpns->unique_using is true, we force all USING names to be
4210 * unique across the whole query level. In principle we'd only need
4211 * the names of dangerous USING columns to be globally unique, but to
4212 * safely assign all USING names in a single pass, we have to enforce
4213 * the same uniqueness rule for all of them. However, if a USING
4214 * column's name has been pushed down from the parent, we should use
4215 * it as-is rather than making a uniqueness adjustment. This is
4216 * necessary when we're at an unnamed join, and it creates no risk of
4217 * ambiguity. Also, if there's a user-written output alias for a
4218 * merged column, we prefer to use that rather than the input name;
4219 * this simplifies the logic and seems likely to lead to less aliasing
4220 * overall.
4222 * If dpns->unique_using is false, we only need USING names to be
4223 * unique within their own join RTE. We still need to honor
4224 * pushed-down names, though.
4226 * Though significantly different in results, these two strategies are
4227 * implemented by the same code, with only the difference of whether
4228 * to put assigned names into dpns->using_names.
4230 if (j->usingClause)
4232 /* Copy the input parentUsing list so we don't modify it */
4233 parentUsing = list_copy(parentUsing);
4235 /* USING names must correspond to the first join output columns */
4236 expand_colnames_array_to(colinfo, list_length(j->usingClause));
4237 i = 0;
4238 foreach(lc, j->usingClause)
4240 char *colname = strVal(lfirst(lc));
4242 /* Assert it's a merged column */
4243 Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
4245 /* Adopt passed-down name if any, else select unique name */
4246 if (colinfo->colnames[i] != NULL)
4247 colname = colinfo->colnames[i];
4248 else
4250 /* Prefer user-written output alias if any */
4251 if (rte->alias && i < list_length(rte->alias->colnames))
4252 colname = strVal(list_nth(rte->alias->colnames, i));
4253 /* Make it appropriately unique */
4254 colname = make_colname_unique(colname, dpns, colinfo);
4255 if (dpns->unique_using)
4256 dpns->using_names = lappend(dpns->using_names,
4257 colname);
4258 /* Save it as output column name, too */
4259 colinfo->colnames[i] = colname;
4262 /* Remember selected names for use later */
4263 colinfo->usingNames = lappend(colinfo->usingNames, colname);
4264 parentUsing = lappend(parentUsing, colname);
4266 /* Push down to left column, unless it's a system column */
4267 if (leftattnos[i] > 0)
4269 expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4270 leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4273 /* Same on the righthand side */
4274 if (rightattnos[i] > 0)
4276 expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4277 rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4280 i++;
4284 /* Mark child deparse_columns structs with correct parentUsing info */
4285 leftcolinfo->parentUsing = parentUsing;
4286 rightcolinfo->parentUsing = parentUsing;
4288 /* Now recursively assign USING column names in children */
4289 set_using_names(dpns, j->larg, parentUsing);
4290 set_using_names(dpns, j->rarg, parentUsing);
4292 else
4293 elog(ERROR, "unrecognized node type: %d",
4294 (int) nodeTag(jtnode));
4298 * set_relation_column_names: select column aliases for a non-join RTE
4300 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4301 * If any colnames entries are already filled in, those override local
4302 * choices.
4304 static void
4305 set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
4306 deparse_columns *colinfo)
4308 int ncolumns;
4309 char **real_colnames;
4310 bool changed_any;
4311 int noldcolumns;
4312 int i;
4313 int j;
4316 * Construct an array of the current "real" column names of the RTE.
4317 * real_colnames[] will be indexed by physical column number, with NULL
4318 * entries for dropped columns.
4320 if (rte->rtekind == RTE_RELATION)
4322 /* Relation --- look to the system catalogs for up-to-date info */
4323 Relation rel;
4324 TupleDesc tupdesc;
4326 rel = relation_open(rte->relid, AccessShareLock);
4327 tupdesc = RelationGetDescr(rel);
4329 ncolumns = tupdesc->natts;
4330 real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4332 for (i = 0; i < ncolumns; i++)
4334 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
4336 if (attr->attisdropped)
4337 real_colnames[i] = NULL;
4338 else
4339 real_colnames[i] = pstrdup(NameStr(attr->attname));
4341 relation_close(rel, AccessShareLock);
4343 else
4345 /* Otherwise get the column names from eref or expandRTE() */
4346 List *colnames;
4347 ListCell *lc;
4350 * Functions returning composites have the annoying property that some
4351 * of the composite type's columns might have been dropped since the
4352 * query was parsed. If possible, use expandRTE() to handle that
4353 * case, since it has the tedious logic needed to find out about
4354 * dropped columns. However, if we're explaining a plan, then we
4355 * don't have rte->functions because the planner thinks that won't be
4356 * needed later, and that breaks expandRTE(). So in that case we have
4357 * to rely on rte->eref, which may lead us to report a dropped
4358 * column's old name; that seems close enough for EXPLAIN's purposes.
4360 * For non-RELATION, non-FUNCTION RTEs, we can just look at rte->eref,
4361 * which should be sufficiently up-to-date: no other RTE types can
4362 * have columns get dropped from under them after parsing.
4364 if (rte->rtekind == RTE_FUNCTION && rte->functions != NIL)
4366 /* Since we're not creating Vars, rtindex etc. don't matter */
4367 expandRTE(rte, 1, 0, -1, true /* include dropped */ ,
4368 &colnames, NULL);
4370 else
4371 colnames = rte->eref->colnames;
4373 ncolumns = list_length(colnames);
4374 real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4376 i = 0;
4377 foreach(lc, colnames)
4380 * If the column name we find here is an empty string, then it's a
4381 * dropped column, so change to NULL.
4383 char *cname = strVal(lfirst(lc));
4385 if (cname[0] == '\0')
4386 cname = NULL;
4387 real_colnames[i] = cname;
4388 i++;
4393 * Ensure colinfo->colnames has a slot for each column. (It could be long
4394 * enough already, if we pushed down a name for the last column.) Note:
4395 * it's possible that there are now more columns than there were when the
4396 * query was parsed, ie colnames could be longer than rte->eref->colnames.
4397 * We must assign unique aliases to the new columns too, else there could
4398 * be unresolved conflicts when the view/rule is reloaded.
4400 expand_colnames_array_to(colinfo, ncolumns);
4401 Assert(colinfo->num_cols == ncolumns);
4404 * Make sufficiently large new_colnames and is_new_col arrays, too.
4406 * Note: because we leave colinfo->num_new_cols zero until after the loop,
4407 * colname_is_unique will not consult that array, which is fine because it
4408 * would only be duplicate effort.
4410 colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
4411 colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
4414 * Scan the columns, select a unique alias for each one, and store it in
4415 * colinfo->colnames and colinfo->new_colnames. The former array has NULL
4416 * entries for dropped columns, the latter omits them. Also mark
4417 * new_colnames entries as to whether they are new since parse time; this
4418 * is the case for entries beyond the length of rte->eref->colnames.
4420 noldcolumns = list_length(rte->eref->colnames);
4421 changed_any = false;
4422 j = 0;
4423 for (i = 0; i < ncolumns; i++)
4425 char *real_colname = real_colnames[i];
4426 char *colname = colinfo->colnames[i];
4428 /* Skip dropped columns */
4429 if (real_colname == NULL)
4431 Assert(colname == NULL); /* colnames[i] is already NULL */
4432 continue;
4435 /* If alias already assigned, that's what to use */
4436 if (colname == NULL)
4438 /* If user wrote an alias, prefer that over real column name */
4439 if (rte->alias && i < list_length(rte->alias->colnames))
4440 colname = strVal(list_nth(rte->alias->colnames, i));
4441 else
4442 colname = real_colname;
4444 /* Unique-ify and insert into colinfo */
4445 colname = make_colname_unique(colname, dpns, colinfo);
4447 colinfo->colnames[i] = colname;
4450 /* Put names of non-dropped columns in new_colnames[] too */
4451 colinfo->new_colnames[j] = colname;
4452 /* And mark them as new or not */
4453 colinfo->is_new_col[j] = (i >= noldcolumns);
4454 j++;
4456 /* Remember if any assigned aliases differ from "real" name */
4457 if (!changed_any && strcmp(colname, real_colname) != 0)
4458 changed_any = true;
4462 * Set correct length for new_colnames[] array. (Note: if columns have
4463 * been added, colinfo->num_cols includes them, which is not really quite
4464 * right but is harmless, since any new columns must be at the end where
4465 * they won't affect varattnos of pre-existing columns.)
4467 colinfo->num_new_cols = j;
4470 * For a relation RTE, we need only print the alias column names if any
4471 * are different from the underlying "real" names. For a function RTE,
4472 * always emit a complete column alias list; this is to protect against
4473 * possible instability of the default column names (eg, from altering
4474 * parameter names). For tablefunc RTEs, we never print aliases, because
4475 * the column names are part of the clause itself. For other RTE types,
4476 * print if we changed anything OR if there were user-written column
4477 * aliases (since the latter would be part of the underlying "reality").
4479 if (rte->rtekind == RTE_RELATION)
4480 colinfo->printaliases = changed_any;
4481 else if (rte->rtekind == RTE_FUNCTION)
4482 colinfo->printaliases = true;
4483 else if (rte->rtekind == RTE_TABLEFUNC)
4484 colinfo->printaliases = false;
4485 else if (rte->alias && rte->alias->colnames != NIL)
4486 colinfo->printaliases = true;
4487 else
4488 colinfo->printaliases = changed_any;
4492 * set_join_column_names: select column aliases for a join RTE
4494 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4495 * If any colnames entries are already filled in, those override local
4496 * choices. Also, names for USING columns were already chosen by
4497 * set_using_names(). We further expect that column alias selection has been
4498 * completed for both input RTEs.
4500 static void
4501 set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
4502 deparse_columns *colinfo)
4504 deparse_columns *leftcolinfo;
4505 deparse_columns *rightcolinfo;
4506 bool changed_any;
4507 int noldcolumns;
4508 int nnewcolumns;
4509 Bitmapset *leftmerged = NULL;
4510 Bitmapset *rightmerged = NULL;
4511 int i;
4512 int j;
4513 int ic;
4514 int jc;
4516 /* Look up the previously-filled-in child deparse_columns structs */
4517 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4518 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4521 * Ensure colinfo->colnames has a slot for each column. (It could be long
4522 * enough already, if we pushed down a name for the last column.) Note:
4523 * it's possible that one or both inputs now have more columns than there
4524 * were when the query was parsed, but we'll deal with that below. We
4525 * only need entries in colnames for pre-existing columns.
4527 noldcolumns = list_length(rte->eref->colnames);
4528 expand_colnames_array_to(colinfo, noldcolumns);
4529 Assert(colinfo->num_cols == noldcolumns);
4532 * Scan the join output columns, select an alias for each one, and store
4533 * it in colinfo->colnames. If there are USING columns, set_using_names()
4534 * already selected their names, so we can start the loop at the first
4535 * non-merged column.
4537 changed_any = false;
4538 for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
4540 char *colname = colinfo->colnames[i];
4541 char *real_colname;
4543 /* Join column must refer to at least one input column */
4544 Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
4546 /* Get the child column name */
4547 if (colinfo->leftattnos[i] > 0)
4548 real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
4549 else if (colinfo->rightattnos[i] > 0)
4550 real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
4551 else
4553 /* We're joining system columns --- use eref name */
4554 real_colname = strVal(list_nth(rte->eref->colnames, i));
4557 /* If child col has been dropped, no need to assign a join colname */
4558 if (real_colname == NULL)
4560 colinfo->colnames[i] = NULL;
4561 continue;
4564 /* In an unnamed join, just report child column names as-is */
4565 if (rte->alias == NULL)
4567 colinfo->colnames[i] = real_colname;
4568 continue;
4571 /* If alias already assigned, that's what to use */
4572 if (colname == NULL)
4574 /* If user wrote an alias, prefer that over real column name */
4575 if (rte->alias && i < list_length(rte->alias->colnames))
4576 colname = strVal(list_nth(rte->alias->colnames, i));
4577 else
4578 colname = real_colname;
4580 /* Unique-ify and insert into colinfo */
4581 colname = make_colname_unique(colname, dpns, colinfo);
4583 colinfo->colnames[i] = colname;
4586 /* Remember if any assigned aliases differ from "real" name */
4587 if (!changed_any && strcmp(colname, real_colname) != 0)
4588 changed_any = true;
4592 * Calculate number of columns the join would have if it were re-parsed
4593 * now, and create storage for the new_colnames and is_new_col arrays.
4595 * Note: colname_is_unique will be consulting new_colnames[] during the
4596 * loops below, so its not-yet-filled entries must be zeroes.
4598 nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
4599 list_length(colinfo->usingNames);
4600 colinfo->num_new_cols = nnewcolumns;
4601 colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
4602 colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
4605 * Generating the new_colnames array is a bit tricky since any new columns
4606 * added since parse time must be inserted in the right places. This code
4607 * must match the parser, which will order a join's columns as merged
4608 * columns first (in USING-clause order), then non-merged columns from the
4609 * left input (in attnum order), then non-merged columns from the right
4610 * input (ditto). If one of the inputs is itself a join, its columns will
4611 * be ordered according to the same rule, which means newly-added columns
4612 * might not be at the end. We can figure out what's what by consulting
4613 * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
4615 * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
4616 * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
4617 * meanings for the current child RTE.
4620 /* Handle merged columns; they are first and can't be new */
4621 i = j = 0;
4622 while (i < noldcolumns &&
4623 colinfo->leftattnos[i] != 0 &&
4624 colinfo->rightattnos[i] != 0)
4626 /* column name is already determined and known unique */
4627 colinfo->new_colnames[j] = colinfo->colnames[i];
4628 colinfo->is_new_col[j] = false;
4630 /* build bitmapsets of child attnums of merged columns */
4631 if (colinfo->leftattnos[i] > 0)
4632 leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
4633 if (colinfo->rightattnos[i] > 0)
4634 rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
4636 i++, j++;
4639 /* Handle non-merged left-child columns */
4640 ic = 0;
4641 for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
4643 char *child_colname = leftcolinfo->new_colnames[jc];
4645 if (!leftcolinfo->is_new_col[jc])
4647 /* Advance ic to next non-dropped old column of left child */
4648 while (ic < leftcolinfo->num_cols &&
4649 leftcolinfo->colnames[ic] == NULL)
4650 ic++;
4651 Assert(ic < leftcolinfo->num_cols);
4652 ic++;
4653 /* If it is a merged column, we already processed it */
4654 if (bms_is_member(ic, leftmerged))
4655 continue;
4656 /* Else, advance i to the corresponding existing join column */
4657 while (i < colinfo->num_cols &&
4658 colinfo->colnames[i] == NULL)
4659 i++;
4660 Assert(i < colinfo->num_cols);
4661 Assert(ic == colinfo->leftattnos[i]);
4662 /* Use the already-assigned name of this column */
4663 colinfo->new_colnames[j] = colinfo->colnames[i];
4664 i++;
4666 else
4669 * Unique-ify the new child column name and assign, unless we're
4670 * in an unnamed join, in which case just copy
4672 if (rte->alias != NULL)
4674 colinfo->new_colnames[j] =
4675 make_colname_unique(child_colname, dpns, colinfo);
4676 if (!changed_any &&
4677 strcmp(colinfo->new_colnames[j], child_colname) != 0)
4678 changed_any = true;
4680 else
4681 colinfo->new_colnames[j] = child_colname;
4684 colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
4685 j++;
4688 /* Handle non-merged right-child columns in exactly the same way */
4689 ic = 0;
4690 for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
4692 char *child_colname = rightcolinfo->new_colnames[jc];
4694 if (!rightcolinfo->is_new_col[jc])
4696 /* Advance ic to next non-dropped old column of right child */
4697 while (ic < rightcolinfo->num_cols &&
4698 rightcolinfo->colnames[ic] == NULL)
4699 ic++;
4700 Assert(ic < rightcolinfo->num_cols);
4701 ic++;
4702 /* If it is a merged column, we already processed it */
4703 if (bms_is_member(ic, rightmerged))
4704 continue;
4705 /* Else, advance i to the corresponding existing join column */
4706 while (i < colinfo->num_cols &&
4707 colinfo->colnames[i] == NULL)
4708 i++;
4709 Assert(i < colinfo->num_cols);
4710 Assert(ic == colinfo->rightattnos[i]);
4711 /* Use the already-assigned name of this column */
4712 colinfo->new_colnames[j] = colinfo->colnames[i];
4713 i++;
4715 else
4718 * Unique-ify the new child column name and assign, unless we're
4719 * in an unnamed join, in which case just copy
4721 if (rte->alias != NULL)
4723 colinfo->new_colnames[j] =
4724 make_colname_unique(child_colname, dpns, colinfo);
4725 if (!changed_any &&
4726 strcmp(colinfo->new_colnames[j], child_colname) != 0)
4727 changed_any = true;
4729 else
4730 colinfo->new_colnames[j] = child_colname;
4733 colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
4734 j++;
4737 /* Assert we processed the right number of columns */
4738 #ifdef USE_ASSERT_CHECKING
4739 while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
4740 i++;
4741 Assert(i == colinfo->num_cols);
4742 Assert(j == nnewcolumns);
4743 #endif
4746 * For a named join, print column aliases if we changed any from the child
4747 * names. Unnamed joins cannot print aliases.
4749 if (rte->alias != NULL)
4750 colinfo->printaliases = changed_any;
4751 else
4752 colinfo->printaliases = false;
4756 * colname_is_unique: is colname distinct from already-chosen column names?
4758 * dpns is query-wide info, colinfo is for the column's RTE
4760 static bool
4761 colname_is_unique(const char *colname, deparse_namespace *dpns,
4762 deparse_columns *colinfo)
4764 int i;
4765 ListCell *lc;
4767 /* Check against already-assigned column aliases within RTE */
4768 for (i = 0; i < colinfo->num_cols; i++)
4770 char *oldname = colinfo->colnames[i];
4772 if (oldname && strcmp(oldname, colname) == 0)
4773 return false;
4777 * If we're building a new_colnames array, check that too (this will be
4778 * partially but not completely redundant with the previous checks)
4780 for (i = 0; i < colinfo->num_new_cols; i++)
4782 char *oldname = colinfo->new_colnames[i];
4784 if (oldname && strcmp(oldname, colname) == 0)
4785 return false;
4788 /* Also check against USING-column names that must be globally unique */
4789 foreach(lc, dpns->using_names)
4791 char *oldname = (char *) lfirst(lc);
4793 if (strcmp(oldname, colname) == 0)
4794 return false;
4797 /* Also check against names already assigned for parent-join USING cols */
4798 foreach(lc, colinfo->parentUsing)
4800 char *oldname = (char *) lfirst(lc);
4802 if (strcmp(oldname, colname) == 0)
4803 return false;
4806 return true;
4810 * make_colname_unique: modify colname if necessary to make it unique
4812 * dpns is query-wide info, colinfo is for the column's RTE
4814 static char *
4815 make_colname_unique(char *colname, deparse_namespace *dpns,
4816 deparse_columns *colinfo)
4819 * If the selected name isn't unique, append digits to make it so. For a
4820 * very long input name, we might have to truncate to stay within
4821 * NAMEDATALEN.
4823 if (!colname_is_unique(colname, dpns, colinfo))
4825 int colnamelen = strlen(colname);
4826 char *modname = (char *) palloc(colnamelen + 16);
4827 int i = 0;
4831 i++;
4832 for (;;)
4834 memcpy(modname, colname, colnamelen);
4835 sprintf(modname + colnamelen, "_%d", i);
4836 if (strlen(modname) < NAMEDATALEN)
4837 break;
4838 /* drop chars from colname to keep all the digits */
4839 colnamelen = pg_mbcliplen(colname, colnamelen,
4840 colnamelen - 1);
4842 } while (!colname_is_unique(modname, dpns, colinfo));
4843 colname = modname;
4845 return colname;
4849 * expand_colnames_array_to: make colinfo->colnames at least n items long
4851 * Any added array entries are initialized to zero.
4853 static void
4854 expand_colnames_array_to(deparse_columns *colinfo, int n)
4856 if (n > colinfo->num_cols)
4858 if (colinfo->colnames == NULL)
4859 colinfo->colnames = palloc0_array(char *, n);
4860 else
4861 colinfo->colnames = repalloc0_array(colinfo->colnames, char *, colinfo->num_cols, n);
4862 colinfo->num_cols = n;
4867 * identify_join_columns: figure out where columns of a join come from
4869 * Fills the join-specific fields of the colinfo struct, except for
4870 * usingNames which is filled later.
4872 static void
4873 identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
4874 deparse_columns *colinfo)
4876 int numjoincols;
4877 int jcolno;
4878 int rcolno;
4879 ListCell *lc;
4881 /* Extract left/right child RT indexes */
4882 if (IsA(j->larg, RangeTblRef))
4883 colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
4884 else if (IsA(j->larg, JoinExpr))
4885 colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
4886 else
4887 elog(ERROR, "unrecognized node type in jointree: %d",
4888 (int) nodeTag(j->larg));
4889 if (IsA(j->rarg, RangeTblRef))
4890 colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
4891 else if (IsA(j->rarg, JoinExpr))
4892 colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
4893 else
4894 elog(ERROR, "unrecognized node type in jointree: %d",
4895 (int) nodeTag(j->rarg));
4897 /* Assert children will be processed earlier than join in second pass */
4898 Assert(colinfo->leftrti < j->rtindex);
4899 Assert(colinfo->rightrti < j->rtindex);
4901 /* Initialize result arrays with zeroes */
4902 numjoincols = list_length(jrte->joinaliasvars);
4903 Assert(numjoincols == list_length(jrte->eref->colnames));
4904 colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
4905 colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
4908 * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
4909 * Recall that the column(s) merged due to USING are the first column(s)
4910 * of the join output. We need not do anything special while scanning
4911 * joinleftcols, but while scanning joinrightcols we must distinguish
4912 * merged from unmerged columns.
4914 jcolno = 0;
4915 foreach(lc, jrte->joinleftcols)
4917 int leftattno = lfirst_int(lc);
4919 colinfo->leftattnos[jcolno++] = leftattno;
4921 rcolno = 0;
4922 foreach(lc, jrte->joinrightcols)
4924 int rightattno = lfirst_int(lc);
4926 if (rcolno < jrte->joinmergedcols) /* merged column? */
4927 colinfo->rightattnos[rcolno] = rightattno;
4928 else
4929 colinfo->rightattnos[jcolno++] = rightattno;
4930 rcolno++;
4932 Assert(jcolno == numjoincols);
4936 * get_rtable_name: convenience function to get a previously assigned RTE alias
4938 * The RTE must belong to the topmost namespace level in "context".
4940 static char *
4941 get_rtable_name(int rtindex, deparse_context *context)
4943 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
4945 Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4946 return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4950 * set_deparse_plan: set up deparse_namespace to parse subexpressions
4951 * of a given Plan node
4953 * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
4954 * and index_tlist fields. Caller must already have adjusted the ancestors
4955 * list if necessary. Note that the rtable, subplans, and ctes fields do
4956 * not need to change when shifting attention to different plan nodes in a
4957 * single plan tree.
4959 static void
4960 set_deparse_plan(deparse_namespace *dpns, Plan *plan)
4962 dpns->plan = plan;
4965 * We special-case Append and MergeAppend to pretend that the first child
4966 * plan is the OUTER referent; we have to interpret OUTER Vars in their
4967 * tlists according to one of the children, and the first one is the most
4968 * natural choice.
4970 if (IsA(plan, Append))
4971 dpns->outer_plan = linitial(((Append *) plan)->appendplans);
4972 else if (IsA(plan, MergeAppend))
4973 dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
4974 else
4975 dpns->outer_plan = outerPlan(plan);
4977 if (dpns->outer_plan)
4978 dpns->outer_tlist = dpns->outer_plan->targetlist;
4979 else
4980 dpns->outer_tlist = NIL;
4983 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
4984 * use OUTER because that could someday conflict with the normal meaning.)
4985 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
4986 * For a WorkTableScan, locate the parent RecursiveUnion plan node and use
4987 * that as INNER referent.
4989 * For MERGE, pretend the ModifyTable's source plan (its outer plan) is
4990 * INNER referent. This is the join from the target relation to the data
4991 * source, and all INNER_VAR Vars in other parts of the query refer to its
4992 * targetlist.
4994 * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
4995 * excluded expression's tlist. (Similar to the SubqueryScan we don't want
4996 * to reuse OUTER, it's used for RETURNING in some modify table cases,
4997 * although not INSERT .. CONFLICT).
4999 if (IsA(plan, SubqueryScan))
5000 dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
5001 else if (IsA(plan, CteScan))
5002 dpns->inner_plan = list_nth(dpns->subplans,
5003 ((CteScan *) plan)->ctePlanId - 1);
5004 else if (IsA(plan, WorkTableScan))
5005 dpns->inner_plan = find_recursive_union(dpns,
5006 (WorkTableScan *) plan);
5007 else if (IsA(plan, ModifyTable))
5009 if (((ModifyTable *) plan)->operation == CMD_MERGE)
5010 dpns->inner_plan = outerPlan(plan);
5011 else
5012 dpns->inner_plan = plan;
5014 else
5015 dpns->inner_plan = innerPlan(plan);
5017 if (IsA(plan, ModifyTable) && ((ModifyTable *) plan)->operation == CMD_INSERT)
5018 dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
5019 else if (dpns->inner_plan)
5020 dpns->inner_tlist = dpns->inner_plan->targetlist;
5021 else
5022 dpns->inner_tlist = NIL;
5024 /* Set up referent for INDEX_VAR Vars, if needed */
5025 if (IsA(plan, IndexOnlyScan))
5026 dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
5027 else if (IsA(plan, ForeignScan))
5028 dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
5029 else if (IsA(plan, CustomScan))
5030 dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
5031 else
5032 dpns->index_tlist = NIL;
5036 * Locate the ancestor plan node that is the RecursiveUnion generating
5037 * the WorkTableScan's work table. We can match on wtParam, since that
5038 * should be unique within the plan tree.
5040 static Plan *
5041 find_recursive_union(deparse_namespace *dpns, WorkTableScan *wtscan)
5043 ListCell *lc;
5045 foreach(lc, dpns->ancestors)
5047 Plan *ancestor = (Plan *) lfirst(lc);
5049 if (IsA(ancestor, RecursiveUnion) &&
5050 ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
5051 return ancestor;
5053 elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
5054 wtscan->wtParam);
5055 return NULL;
5059 * push_child_plan: temporarily transfer deparsing attention to a child plan
5061 * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
5062 * deparse context in case the referenced expression itself uses
5063 * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
5064 * affecting levelsup issues (although in a Plan tree there really shouldn't
5065 * be any).
5067 * Caller must provide a local deparse_namespace variable to save the
5068 * previous state for pop_child_plan.
5070 static void
5071 push_child_plan(deparse_namespace *dpns, Plan *plan,
5072 deparse_namespace *save_dpns)
5074 /* Save state for restoration later */
5075 *save_dpns = *dpns;
5077 /* Link current plan node into ancestors list */
5078 dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
5080 /* Set attention on selected child */
5081 set_deparse_plan(dpns, plan);
5085 * pop_child_plan: undo the effects of push_child_plan
5087 static void
5088 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
5090 List *ancestors;
5092 /* Get rid of ancestors list cell added by push_child_plan */
5093 ancestors = list_delete_first(dpns->ancestors);
5095 /* Restore fields changed by push_child_plan */
5096 *dpns = *save_dpns;
5098 /* Make sure dpns->ancestors is right (may be unnecessary) */
5099 dpns->ancestors = ancestors;
5103 * push_ancestor_plan: temporarily transfer deparsing attention to an
5104 * ancestor plan
5106 * When expanding a Param reference, we must adjust the deparse context
5107 * to match the plan node that contains the expression being printed;
5108 * otherwise we'd fail if that expression itself contains a Param or
5109 * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
5111 * The target ancestor is conveniently identified by the ListCell holding it
5112 * in dpns->ancestors.
5114 * Caller must provide a local deparse_namespace variable to save the
5115 * previous state for pop_ancestor_plan.
5117 static void
5118 push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
5119 deparse_namespace *save_dpns)
5121 Plan *plan = (Plan *) lfirst(ancestor_cell);
5123 /* Save state for restoration later */
5124 *save_dpns = *dpns;
5126 /* Build a new ancestor list with just this node's ancestors */
5127 dpns->ancestors =
5128 list_copy_tail(dpns->ancestors,
5129 list_cell_number(dpns->ancestors, ancestor_cell) + 1);
5131 /* Set attention on selected ancestor */
5132 set_deparse_plan(dpns, plan);
5136 * pop_ancestor_plan: undo the effects of push_ancestor_plan
5138 static void
5139 pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
5141 /* Free the ancestor list made in push_ancestor_plan */
5142 list_free(dpns->ancestors);
5144 /* Restore fields changed by push_ancestor_plan */
5145 *dpns = *save_dpns;
5149 /* ----------
5150 * make_ruledef - reconstruct the CREATE RULE command
5151 * for a given pg_rewrite tuple
5152 * ----------
5154 static void
5155 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
5156 int prettyFlags)
5158 char *rulename;
5159 char ev_type;
5160 Oid ev_class;
5161 bool is_instead;
5162 char *ev_qual;
5163 char *ev_action;
5164 List *actions;
5165 Relation ev_relation;
5166 TupleDesc viewResultDesc = NULL;
5167 int fno;
5168 Datum dat;
5169 bool isnull;
5172 * Get the attribute values from the rules tuple
5174 fno = SPI_fnumber(rulettc, "rulename");
5175 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5176 Assert(!isnull);
5177 rulename = NameStr(*(DatumGetName(dat)));
5179 fno = SPI_fnumber(rulettc, "ev_type");
5180 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5181 Assert(!isnull);
5182 ev_type = DatumGetChar(dat);
5184 fno = SPI_fnumber(rulettc, "ev_class");
5185 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5186 Assert(!isnull);
5187 ev_class = DatumGetObjectId(dat);
5189 fno = SPI_fnumber(rulettc, "is_instead");
5190 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5191 Assert(!isnull);
5192 is_instead = DatumGetBool(dat);
5194 fno = SPI_fnumber(rulettc, "ev_qual");
5195 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5196 Assert(ev_qual != NULL);
5198 fno = SPI_fnumber(rulettc, "ev_action");
5199 ev_action = SPI_getvalue(ruletup, rulettc, fno);
5200 Assert(ev_action != NULL);
5201 actions = (List *) stringToNode(ev_action);
5202 if (actions == NIL)
5203 elog(ERROR, "invalid empty ev_action list");
5205 ev_relation = table_open(ev_class, AccessShareLock);
5208 * Build the rules definition text
5210 appendStringInfo(buf, "CREATE RULE %s AS",
5211 quote_identifier(rulename));
5213 if (prettyFlags & PRETTYFLAG_INDENT)
5214 appendStringInfoString(buf, "\n ON ");
5215 else
5216 appendStringInfoString(buf, " ON ");
5218 /* The event the rule is fired for */
5219 switch (ev_type)
5221 case '1':
5222 appendStringInfoString(buf, "SELECT");
5223 viewResultDesc = RelationGetDescr(ev_relation);
5224 break;
5226 case '2':
5227 appendStringInfoString(buf, "UPDATE");
5228 break;
5230 case '3':
5231 appendStringInfoString(buf, "INSERT");
5232 break;
5234 case '4':
5235 appendStringInfoString(buf, "DELETE");
5236 break;
5238 default:
5239 ereport(ERROR,
5240 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5241 errmsg("rule \"%s\" has unsupported event type %d",
5242 rulename, ev_type)));
5243 break;
5246 /* The relation the rule is fired on */
5247 appendStringInfo(buf, " TO %s",
5248 (prettyFlags & PRETTYFLAG_SCHEMA) ?
5249 generate_relation_name(ev_class, NIL) :
5250 generate_qualified_relation_name(ev_class));
5252 /* If the rule has an event qualification, add it */
5253 if (strcmp(ev_qual, "<>") != 0)
5255 Node *qual;
5256 Query *query;
5257 deparse_context context;
5258 deparse_namespace dpns;
5260 if (prettyFlags & PRETTYFLAG_INDENT)
5261 appendStringInfoString(buf, "\n ");
5262 appendStringInfoString(buf, " WHERE ");
5264 qual = stringToNode(ev_qual);
5267 * We need to make a context for recognizing any Vars in the qual
5268 * (which can only be references to OLD and NEW). Use the rtable of
5269 * the first query in the action list for this purpose.
5271 query = (Query *) linitial(actions);
5274 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
5275 * into the SELECT, and that's what we need to look at. (Ugly kluge
5276 * ... try to fix this when we redesign querytrees.)
5278 query = getInsertSelectQuery(query, NULL);
5280 /* Must acquire locks right away; see notes in get_query_def() */
5281 AcquireRewriteLocks(query, false, false);
5283 context.buf = buf;
5284 context.namespaces = list_make1(&dpns);
5285 context.resultDesc = NULL;
5286 context.targetList = NIL;
5287 context.windowClause = NIL;
5288 context.varprefix = (list_length(query->rtable) != 1);
5289 context.prettyFlags = prettyFlags;
5290 context.wrapColumn = WRAP_COLUMN_DEFAULT;
5291 context.indentLevel = PRETTYINDENT_STD;
5292 context.colNamesVisible = true;
5293 context.inGroupBy = false;
5294 context.varInOrderBy = false;
5295 context.appendparents = NULL;
5297 set_deparse_for_query(&dpns, query, NIL);
5299 get_rule_expr(qual, &context, false);
5302 appendStringInfoString(buf, " DO ");
5304 /* The INSTEAD keyword (if so) */
5305 if (is_instead)
5306 appendStringInfoString(buf, "INSTEAD ");
5308 /* Finally the rules actions */
5309 if (list_length(actions) > 1)
5311 ListCell *action;
5312 Query *query;
5314 appendStringInfoChar(buf, '(');
5315 foreach(action, actions)
5317 query = (Query *) lfirst(action);
5318 get_query_def(query, buf, NIL, viewResultDesc, true,
5319 prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5320 if (prettyFlags)
5321 appendStringInfoString(buf, ";\n");
5322 else
5323 appendStringInfoString(buf, "; ");
5325 appendStringInfoString(buf, ");");
5327 else
5329 Query *query;
5331 query = (Query *) linitial(actions);
5332 get_query_def(query, buf, NIL, viewResultDesc, true,
5333 prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5334 appendStringInfoChar(buf, ';');
5337 table_close(ev_relation, AccessShareLock);
5341 /* ----------
5342 * make_viewdef - reconstruct the SELECT part of a
5343 * view rewrite rule
5344 * ----------
5346 static void
5347 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
5348 int prettyFlags, int wrapColumn)
5350 Query *query;
5351 char ev_type;
5352 Oid ev_class;
5353 bool is_instead;
5354 char *ev_qual;
5355 char *ev_action;
5356 List *actions;
5357 Relation ev_relation;
5358 int fno;
5359 Datum dat;
5360 bool isnull;
5363 * Get the attribute values from the rules tuple
5365 fno = SPI_fnumber(rulettc, "ev_type");
5366 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5367 Assert(!isnull);
5368 ev_type = DatumGetChar(dat);
5370 fno = SPI_fnumber(rulettc, "ev_class");
5371 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5372 Assert(!isnull);
5373 ev_class = DatumGetObjectId(dat);
5375 fno = SPI_fnumber(rulettc, "is_instead");
5376 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5377 Assert(!isnull);
5378 is_instead = DatumGetBool(dat);
5380 fno = SPI_fnumber(rulettc, "ev_qual");
5381 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5382 Assert(ev_qual != NULL);
5384 fno = SPI_fnumber(rulettc, "ev_action");
5385 ev_action = SPI_getvalue(ruletup, rulettc, fno);
5386 Assert(ev_action != NULL);
5387 actions = (List *) stringToNode(ev_action);
5389 if (list_length(actions) != 1)
5391 /* keep output buffer empty and leave */
5392 return;
5395 query = (Query *) linitial(actions);
5397 if (ev_type != '1' || !is_instead ||
5398 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
5400 /* keep output buffer empty and leave */
5401 return;
5404 ev_relation = table_open(ev_class, AccessShareLock);
5406 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
5407 prettyFlags, wrapColumn, 0);
5408 appendStringInfoChar(buf, ';');
5410 table_close(ev_relation, AccessShareLock);
5414 /* ----------
5415 * get_query_def - Parse back one query parsetree
5417 * query: parsetree to be displayed
5418 * buf: output text is appended to buf
5419 * parentnamespace: list (initially empty) of outer-level deparse_namespace's
5420 * resultDesc: if not NULL, the output tuple descriptor for the view
5421 * represented by a SELECT query. We use the column names from it
5422 * to label SELECT output columns, in preference to names in the query
5423 * colNamesVisible: true if the surrounding context cares about the output
5424 * column names at all (as, for example, an EXISTS() context does not);
5425 * when false, we can suppress dummy column labels such as "?column?"
5426 * prettyFlags: bitmask of PRETTYFLAG_XXX options
5427 * wrapColumn: maximum line length, or -1 to disable wrapping
5428 * startIndent: initial indentation amount
5429 * ----------
5431 static void
5432 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
5433 TupleDesc resultDesc, bool colNamesVisible,
5434 int prettyFlags, int wrapColumn, int startIndent)
5436 deparse_context context;
5437 deparse_namespace dpns;
5439 /* Guard against excessively long or deeply-nested queries */
5440 CHECK_FOR_INTERRUPTS();
5441 check_stack_depth();
5444 * Before we begin to examine the query, acquire locks on referenced
5445 * relations, and fix up deleted columns in JOIN RTEs. This ensures
5446 * consistent results. Note we assume it's OK to scribble on the passed
5447 * querytree!
5449 * We are only deparsing the query (we are not about to execute it), so we
5450 * only need AccessShareLock on the relations it mentions.
5452 AcquireRewriteLocks(query, false, false);
5454 context.buf = buf;
5455 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5456 context.resultDesc = NULL;
5457 context.targetList = NIL;
5458 context.windowClause = NIL;
5459 context.varprefix = (parentnamespace != NIL ||
5460 list_length(query->rtable) != 1);
5461 context.prettyFlags = prettyFlags;
5462 context.wrapColumn = wrapColumn;
5463 context.indentLevel = startIndent;
5464 context.colNamesVisible = colNamesVisible;
5465 context.inGroupBy = false;
5466 context.varInOrderBy = false;
5467 context.appendparents = NULL;
5469 set_deparse_for_query(&dpns, query, parentnamespace);
5471 switch (query->commandType)
5473 case CMD_SELECT:
5474 /* We set context.resultDesc only if it's a SELECT */
5475 context.resultDesc = resultDesc;
5476 get_select_query_def(query, &context);
5477 break;
5479 case CMD_UPDATE:
5480 get_update_query_def(query, &context);
5481 break;
5483 case CMD_INSERT:
5484 get_insert_query_def(query, &context);
5485 break;
5487 case CMD_DELETE:
5488 get_delete_query_def(query, &context);
5489 break;
5491 case CMD_MERGE:
5492 get_merge_query_def(query, &context);
5493 break;
5495 case CMD_NOTHING:
5496 appendStringInfoString(buf, "NOTHING");
5497 break;
5499 case CMD_UTILITY:
5500 get_utility_query_def(query, &context);
5501 break;
5503 default:
5504 elog(ERROR, "unrecognized query command type: %d",
5505 query->commandType);
5506 break;
5510 /* ----------
5511 * get_values_def - Parse back a VALUES list
5512 * ----------
5514 static void
5515 get_values_def(List *values_lists, deparse_context *context)
5517 StringInfo buf = context->buf;
5518 bool first_list = true;
5519 ListCell *vtl;
5521 appendStringInfoString(buf, "VALUES ");
5523 foreach(vtl, values_lists)
5525 List *sublist = (List *) lfirst(vtl);
5526 bool first_col = true;
5527 ListCell *lc;
5529 if (first_list)
5530 first_list = false;
5531 else
5532 appendStringInfoString(buf, ", ");
5534 appendStringInfoChar(buf, '(');
5535 foreach(lc, sublist)
5537 Node *col = (Node *) lfirst(lc);
5539 if (first_col)
5540 first_col = false;
5541 else
5542 appendStringInfoChar(buf, ',');
5545 * Print the value. Whole-row Vars need special treatment.
5547 get_rule_expr_toplevel(col, context, false);
5549 appendStringInfoChar(buf, ')');
5553 /* ----------
5554 * get_with_clause - Parse back a WITH clause
5555 * ----------
5557 static void
5558 get_with_clause(Query *query, deparse_context *context)
5560 StringInfo buf = context->buf;
5561 const char *sep;
5562 ListCell *l;
5564 if (query->cteList == NIL)
5565 return;
5567 if (PRETTY_INDENT(context))
5569 context->indentLevel += PRETTYINDENT_STD;
5570 appendStringInfoChar(buf, ' ');
5573 if (query->hasRecursive)
5574 sep = "WITH RECURSIVE ";
5575 else
5576 sep = "WITH ";
5577 foreach(l, query->cteList)
5579 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
5581 appendStringInfoString(buf, sep);
5582 appendStringInfoString(buf, quote_identifier(cte->ctename));
5583 if (cte->aliascolnames)
5585 bool first = true;
5586 ListCell *col;
5588 appendStringInfoChar(buf, '(');
5589 foreach(col, cte->aliascolnames)
5591 if (first)
5592 first = false;
5593 else
5594 appendStringInfoString(buf, ", ");
5595 appendStringInfoString(buf,
5596 quote_identifier(strVal(lfirst(col))));
5598 appendStringInfoChar(buf, ')');
5600 appendStringInfoString(buf, " AS ");
5601 switch (cte->ctematerialized)
5603 case CTEMaterializeDefault:
5604 break;
5605 case CTEMaterializeAlways:
5606 appendStringInfoString(buf, "MATERIALIZED ");
5607 break;
5608 case CTEMaterializeNever:
5609 appendStringInfoString(buf, "NOT MATERIALIZED ");
5610 break;
5612 appendStringInfoChar(buf, '(');
5613 if (PRETTY_INDENT(context))
5614 appendContextKeyword(context, "", 0, 0, 0);
5615 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5616 true,
5617 context->prettyFlags, context->wrapColumn,
5618 context->indentLevel);
5619 if (PRETTY_INDENT(context))
5620 appendContextKeyword(context, "", 0, 0, 0);
5621 appendStringInfoChar(buf, ')');
5623 if (cte->search_clause)
5625 bool first = true;
5626 ListCell *lc;
5628 appendStringInfo(buf, " SEARCH %s FIRST BY ",
5629 cte->search_clause->search_breadth_first ? "BREADTH" : "DEPTH");
5631 foreach(lc, cte->search_clause->search_col_list)
5633 if (first)
5634 first = false;
5635 else
5636 appendStringInfoString(buf, ", ");
5637 appendStringInfoString(buf,
5638 quote_identifier(strVal(lfirst(lc))));
5641 appendStringInfo(buf, " SET %s", quote_identifier(cte->search_clause->search_seq_column));
5644 if (cte->cycle_clause)
5646 bool first = true;
5647 ListCell *lc;
5649 appendStringInfoString(buf, " CYCLE ");
5651 foreach(lc, cte->cycle_clause->cycle_col_list)
5653 if (first)
5654 first = false;
5655 else
5656 appendStringInfoString(buf, ", ");
5657 appendStringInfoString(buf,
5658 quote_identifier(strVal(lfirst(lc))));
5661 appendStringInfo(buf, " SET %s", quote_identifier(cte->cycle_clause->cycle_mark_column));
5664 Const *cmv = castNode(Const, cte->cycle_clause->cycle_mark_value);
5665 Const *cmd = castNode(Const, cte->cycle_clause->cycle_mark_default);
5667 if (!(cmv->consttype == BOOLOID && !cmv->constisnull && DatumGetBool(cmv->constvalue) == true &&
5668 cmd->consttype == BOOLOID && !cmd->constisnull && DatumGetBool(cmd->constvalue) == false))
5670 appendStringInfoString(buf, " TO ");
5671 get_rule_expr(cte->cycle_clause->cycle_mark_value, context, false);
5672 appendStringInfoString(buf, " DEFAULT ");
5673 get_rule_expr(cte->cycle_clause->cycle_mark_default, context, false);
5677 appendStringInfo(buf, " USING %s", quote_identifier(cte->cycle_clause->cycle_path_column));
5680 sep = ", ";
5683 if (PRETTY_INDENT(context))
5685 context->indentLevel -= PRETTYINDENT_STD;
5686 appendContextKeyword(context, "", 0, 0, 0);
5688 else
5689 appendStringInfoChar(buf, ' ');
5692 /* ----------
5693 * get_select_query_def - Parse back a SELECT parsetree
5694 * ----------
5696 static void
5697 get_select_query_def(Query *query, deparse_context *context)
5699 StringInfo buf = context->buf;
5700 bool force_colno;
5701 ListCell *l;
5703 /* Insert the WITH clause if given */
5704 get_with_clause(query, context);
5706 /* Subroutines may need to consult the SELECT targetlist and windowClause */
5707 context->targetList = query->targetList;
5708 context->windowClause = query->windowClause;
5711 * If the Query node has a setOperations tree, then it's the top level of
5712 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
5713 * fields are interesting in the top query itself.
5715 if (query->setOperations)
5717 get_setop_query(query->setOperations, query, context);
5718 /* ORDER BY clauses must be simple in this case */
5719 force_colno = true;
5721 else
5723 get_basic_select_query(query, context);
5724 force_colno = false;
5727 /* Add the ORDER BY clause if given */
5728 if (query->sortClause != NIL)
5730 appendContextKeyword(context, " ORDER BY ",
5731 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5732 get_rule_orderby(query->sortClause, query->targetList,
5733 force_colno, context);
5737 * Add the LIMIT/OFFSET clauses if given. If non-default options, use the
5738 * standard spelling of LIMIT.
5740 if (query->limitOffset != NULL)
5742 appendContextKeyword(context, " OFFSET ",
5743 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5744 get_rule_expr(query->limitOffset, context, false);
5746 if (query->limitCount != NULL)
5748 if (query->limitOption == LIMIT_OPTION_WITH_TIES)
5750 appendContextKeyword(context, " FETCH FIRST ",
5751 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5752 get_rule_expr(query->limitCount, context, false);
5753 appendStringInfoString(buf, " ROWS WITH TIES");
5755 else
5757 appendContextKeyword(context, " LIMIT ",
5758 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
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);
5767 /* Add FOR [KEY] UPDATE/SHARE clauses if present */
5768 if (query->hasForUpdate)
5770 foreach(l, query->rowMarks)
5772 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
5774 /* don't print implicit clauses */
5775 if (rc->pushedDown)
5776 continue;
5778 switch (rc->strength)
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",
5787 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5788 break;
5789 case LCS_FORSHARE:
5790 appendContextKeyword(context, " FOR SHARE",
5791 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5792 break;
5793 case LCS_FORNOKEYUPDATE:
5794 appendContextKeyword(context, " FOR NO KEY UPDATE",
5795 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5796 break;
5797 case LCS_FORUPDATE:
5798 appendContextKeyword(context, " FOR UPDATE",
5799 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5800 break;
5803 appendStringInfo(buf, " OF %s",
5804 quote_identifier(get_rtable_name(rc->rti,
5805 context)));
5806 if (rc->waitPolicy == LockWaitError)
5807 appendStringInfoString(buf, " NOWAIT");
5808 else if (rc->waitPolicy == LockWaitSkip)
5809 appendStringInfoString(buf, " SKIP LOCKED");
5815 * Detect whether query looks like SELECT ... FROM VALUES(),
5816 * with no need to rename the output columns of the VALUES RTE.
5817 * If so, return the VALUES RTE. Otherwise return NULL.
5819 static RangeTblEntry *
5820 get_simple_values_rte(Query *query, TupleDesc resultDesc)
5822 RangeTblEntry *result = NULL;
5823 ListCell *lc;
5826 * We want to detect a match even if the Query also contains OLD or NEW
5827 * rule RTEs. So the idea is to scan the rtable and see if there is only
5828 * one inFromCl RTE that is a VALUES RTE.
5830 foreach(lc, query->rtable)
5832 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
5834 if (rte->rtekind == RTE_VALUES && rte->inFromCl)
5836 if (result)
5837 return NULL; /* multiple VALUES (probably not possible) */
5838 result = rte;
5840 else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
5841 continue; /* ignore rule entries */
5842 else
5843 return NULL; /* something else -> not simple VALUES */
5847 * We don't need to check the targetlist in any great detail, because
5848 * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
5849 * appear inside auto-generated sub-queries with very restricted
5850 * structure. However, DefineView might have modified the tlist by
5851 * injecting new column aliases, or we might have some other column
5852 * aliases forced by a resultDesc. We can only simplify if the RTE's
5853 * column names match the names that get_target_list() would select.
5855 if (result)
5857 ListCell *lcn;
5858 int colno;
5860 if (list_length(query->targetList) != list_length(result->eref->colnames))
5861 return NULL; /* this probably cannot happen */
5862 colno = 0;
5863 forboth(lc, query->targetList, lcn, result->eref->colnames)
5865 TargetEntry *tle = (TargetEntry *) lfirst(lc);
5866 char *cname = strVal(lfirst(lcn));
5867 char *colname;
5869 if (tle->resjunk)
5870 return NULL; /* this probably cannot happen */
5872 /* compute name that get_target_list would use for column */
5873 colno++;
5874 if (resultDesc && colno <= resultDesc->natts)
5875 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5876 else
5877 colname = tle->resname;
5879 /* does it match the VALUES RTE? */
5880 if (colname == NULL || strcmp(colname, cname) != 0)
5881 return NULL; /* column name has been changed */
5885 return result;
5888 static void
5889 get_basic_select_query(Query *query, deparse_context *context)
5891 StringInfo buf = context->buf;
5892 RangeTblEntry *values_rte;
5893 char *sep;
5894 ListCell *l;
5896 if (PRETTY_INDENT(context))
5898 context->indentLevel += PRETTYINDENT_STD;
5899 appendStringInfoChar(buf, ' ');
5903 * If the query looks like SELECT * FROM (VALUES ...), then print just the
5904 * VALUES part. This reverses what transformValuesClause() did at parse
5905 * time.
5907 values_rte = get_simple_values_rte(query, context->resultDesc);
5908 if (values_rte)
5910 get_values_def(values_rte->values_lists, context);
5911 return;
5915 * Build up the query string - first we say SELECT
5917 if (query->isReturn)
5918 appendStringInfoString(buf, "RETURN");
5919 else
5920 appendStringInfoString(buf, "SELECT");
5922 /* Add the DISTINCT clause if given */
5923 if (query->distinctClause != NIL)
5925 if (query->hasDistinctOn)
5927 appendStringInfoString(buf, " DISTINCT ON (");
5928 sep = "";
5929 foreach(l, query->distinctClause)
5931 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5933 appendStringInfoString(buf, sep);
5934 get_rule_sortgroupclause(srt->tleSortGroupRef, query->targetList,
5935 false, context);
5936 sep = ", ";
5938 appendStringInfoChar(buf, ')');
5940 else
5941 appendStringInfoString(buf, " DISTINCT");
5944 /* Then we tell what to select (the targetlist) */
5945 get_target_list(query->targetList, context);
5947 /* Add the FROM clause if needed */
5948 get_from_clause(query, " FROM ", context);
5950 /* Add the WHERE clause if given */
5951 if (query->jointree->quals != NULL)
5953 appendContextKeyword(context, " WHERE ",
5954 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5955 get_rule_expr(query->jointree->quals, context, false);
5958 /* Add the GROUP BY clause if given */
5959 if (query->groupClause != NULL || query->groupingSets != NULL)
5961 bool save_ingroupby;
5963 appendContextKeyword(context, " GROUP BY ",
5964 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5965 if (query->groupDistinct)
5966 appendStringInfoString(buf, "DISTINCT ");
5968 save_ingroupby = context->inGroupBy;
5969 context->inGroupBy = true;
5971 if (query->groupingSets == NIL)
5973 sep = "";
5974 foreach(l, query->groupClause)
5976 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5978 appendStringInfoString(buf, sep);
5979 get_rule_sortgroupclause(grp->tleSortGroupRef, query->targetList,
5980 false, context);
5981 sep = ", ";
5984 else
5986 sep = "";
5987 foreach(l, query->groupingSets)
5989 GroupingSet *grp = lfirst(l);
5991 appendStringInfoString(buf, sep);
5992 get_rule_groupingset(grp, query->targetList, true, context);
5993 sep = ", ";
5997 context->inGroupBy = save_ingroupby;
6000 /* Add the HAVING clause if given */
6001 if (query->havingQual != NULL)
6003 appendContextKeyword(context, " HAVING ",
6004 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
6005 get_rule_expr(query->havingQual, context, false);
6008 /* Add the WINDOW clause if needed */
6009 if (query->windowClause != NIL)
6010 get_rule_windowclause(query, context);
6013 /* ----------
6014 * get_target_list - Parse back a SELECT target list
6016 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE/MERGE.
6017 * ----------
6019 static void
6020 get_target_list(List *targetList, deparse_context *context)
6022 StringInfo buf = context->buf;
6023 StringInfoData targetbuf;
6024 bool last_was_multiline = false;
6025 char *sep;
6026 int colno;
6027 ListCell *l;
6029 /* we use targetbuf to hold each TLE's text temporarily */
6030 initStringInfo(&targetbuf);
6032 sep = " ";
6033 colno = 0;
6034 foreach(l, targetList)
6036 TargetEntry *tle = (TargetEntry *) lfirst(l);
6037 char *colname;
6038 char *attname;
6040 if (tle->resjunk)
6041 continue; /* ignore junk entries */
6043 appendStringInfoString(buf, sep);
6044 sep = ", ";
6045 colno++;
6048 * Put the new field text into targetbuf so we can decide after we've
6049 * got it whether or not it needs to go on a new line.
6051 resetStringInfo(&targetbuf);
6052 context->buf = &targetbuf;
6055 * We special-case Var nodes rather than using get_rule_expr. This is
6056 * needed because get_rule_expr will display a whole-row Var as
6057 * "foo.*", which is the preferred notation in most contexts, but at
6058 * the top level of a SELECT list it's not right (the parser will
6059 * expand that notation into multiple columns, yielding behavior
6060 * different from a whole-row Var). We need to call get_variable
6061 * directly so that we can tell it to do the right thing, and so that
6062 * we can get the attribute name which is the default AS label.
6064 if (tle->expr && (IsA(tle->expr, Var)))
6066 attname = get_variable((Var *) tle->expr, 0, true, context);
6068 else
6070 get_rule_expr((Node *) tle->expr, context, true);
6073 * When colNamesVisible is true, we should always show the
6074 * assigned column name explicitly. Otherwise, show it only if
6075 * it's not FigureColname's fallback.
6077 attname = context->colNamesVisible ? NULL : "?column?";
6081 * Figure out what the result column should be called. In the context
6082 * of a view, use the view's tuple descriptor (so as to pick up the
6083 * effects of any column RENAME that's been done on the view).
6084 * Otherwise, just use what we can find in the TLE.
6086 if (context->resultDesc && colno <= context->resultDesc->natts)
6087 colname = NameStr(TupleDescAttr(context->resultDesc,
6088 colno - 1)->attname);
6089 else
6090 colname = tle->resname;
6092 /* Show AS unless the column's name is correct as-is */
6093 if (colname) /* resname could be NULL */
6095 if (attname == NULL || strcmp(attname, colname) != 0)
6096 appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
6099 /* Restore context's output buffer */
6100 context->buf = buf;
6102 /* Consider line-wrapping if enabled */
6103 if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
6105 int leading_nl_pos;
6107 /* Does the new field start with a new line? */
6108 if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
6109 leading_nl_pos = 0;
6110 else
6111 leading_nl_pos = -1;
6113 /* If so, we shouldn't add anything */
6114 if (leading_nl_pos >= 0)
6116 /* instead, remove any trailing spaces currently in buf */
6117 removeStringInfoSpaces(buf);
6119 else
6121 char *trailing_nl;
6123 /* Locate the start of the current line in the output buffer */
6124 trailing_nl = strrchr(buf->data, '\n');
6125 if (trailing_nl == NULL)
6126 trailing_nl = buf->data;
6127 else
6128 trailing_nl++;
6131 * Add a newline, plus some indentation, if the new field is
6132 * not the first and either the new field would cause an
6133 * overflow or the last field used more than one line.
6135 if (colno > 1 &&
6136 ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
6137 last_was_multiline))
6138 appendContextKeyword(context, "", -PRETTYINDENT_STD,
6139 PRETTYINDENT_STD, PRETTYINDENT_VAR);
6142 /* Remember this field's multiline status for next iteration */
6143 last_was_multiline =
6144 (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
6147 /* Add the new field */
6148 appendBinaryStringInfo(buf, targetbuf.data, targetbuf.len);
6151 /* clean up */
6152 pfree(targetbuf.data);
6155 static void
6156 get_setop_query(Node *setOp, Query *query, deparse_context *context)
6158 StringInfo buf = context->buf;
6159 bool need_paren;
6161 /* Guard against excessively long or deeply-nested queries */
6162 CHECK_FOR_INTERRUPTS();
6163 check_stack_depth();
6165 if (IsA(setOp, RangeTblRef))
6167 RangeTblRef *rtr = (RangeTblRef *) setOp;
6168 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
6169 Query *subquery = rte->subquery;
6171 Assert(subquery != NULL);
6172 Assert(subquery->setOperations == NULL);
6173 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
6174 need_paren = (subquery->cteList ||
6175 subquery->sortClause ||
6176 subquery->rowMarks ||
6177 subquery->limitOffset ||
6178 subquery->limitCount);
6179 if (need_paren)
6180 appendStringInfoChar(buf, '(');
6181 get_query_def(subquery, buf, context->namespaces,
6182 context->resultDesc, context->colNamesVisible,
6183 context->prettyFlags, context->wrapColumn,
6184 context->indentLevel);
6185 if (need_paren)
6186 appendStringInfoChar(buf, ')');
6188 else if (IsA(setOp, SetOperationStmt))
6190 SetOperationStmt *op = (SetOperationStmt *) setOp;
6191 int subindent;
6192 bool save_colnamesvisible;
6195 * We force parens when nesting two SetOperationStmts, except when the
6196 * lefthand input is another setop of the same kind. Syntactically,
6197 * we could omit parens in rather more cases, but it seems best to use
6198 * parens to flag cases where the setop operator changes. If we use
6199 * parens, we also increase the indentation level for the child query.
6201 * There are some cases in which parens are needed around a leaf query
6202 * too, but those are more easily handled at the next level down (see
6203 * code above).
6205 if (IsA(op->larg, SetOperationStmt))
6207 SetOperationStmt *lop = (SetOperationStmt *) op->larg;
6209 if (op->op == lop->op && op->all == lop->all)
6210 need_paren = false;
6211 else
6212 need_paren = true;
6214 else
6215 need_paren = false;
6217 if (need_paren)
6219 appendStringInfoChar(buf, '(');
6220 subindent = PRETTYINDENT_STD;
6221 appendContextKeyword(context, "", subindent, 0, 0);
6223 else
6224 subindent = 0;
6226 get_setop_query(op->larg, query, context);
6228 if (need_paren)
6229 appendContextKeyword(context, ") ", -subindent, 0, 0);
6230 else if (PRETTY_INDENT(context))
6231 appendContextKeyword(context, "", -subindent, 0, 0);
6232 else
6233 appendStringInfoChar(buf, ' ');
6235 switch (op->op)
6237 case SETOP_UNION:
6238 appendStringInfoString(buf, "UNION ");
6239 break;
6240 case SETOP_INTERSECT:
6241 appendStringInfoString(buf, "INTERSECT ");
6242 break;
6243 case SETOP_EXCEPT:
6244 appendStringInfoString(buf, "EXCEPT ");
6245 break;
6246 default:
6247 elog(ERROR, "unrecognized set op: %d",
6248 (int) op->op);
6250 if (op->all)
6251 appendStringInfoString(buf, "ALL ");
6253 /* Always parenthesize if RHS is another setop */
6254 need_paren = IsA(op->rarg, SetOperationStmt);
6257 * The indentation code here is deliberately a bit different from that
6258 * for the lefthand input, because we want the line breaks in
6259 * different places.
6261 if (need_paren)
6263 appendStringInfoChar(buf, '(');
6264 subindent = PRETTYINDENT_STD;
6266 else
6267 subindent = 0;
6268 appendContextKeyword(context, "", subindent, 0, 0);
6271 * The output column names of the RHS sub-select don't matter.
6273 save_colnamesvisible = context->colNamesVisible;
6274 context->colNamesVisible = false;
6276 get_setop_query(op->rarg, query, context);
6278 context->colNamesVisible = save_colnamesvisible;
6280 if (PRETTY_INDENT(context))
6281 context->indentLevel -= subindent;
6282 if (need_paren)
6283 appendContextKeyword(context, ")", 0, 0, 0);
6285 else
6287 elog(ERROR, "unrecognized node type: %d",
6288 (int) nodeTag(setOp));
6293 * Display a sort/group clause.
6295 * Also returns the expression tree, so caller need not find it again.
6297 static Node *
6298 get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
6299 deparse_context *context)
6301 StringInfo buf = context->buf;
6302 TargetEntry *tle;
6303 Node *expr;
6305 tle = get_sortgroupref_tle(ref, tlist);
6306 expr = (Node *) tle->expr;
6309 * Use column-number form if requested by caller. Otherwise, if
6310 * expression is a constant, force it to be dumped with an explicit cast
6311 * as decoration --- this is because a simple integer constant is
6312 * ambiguous (and will be misinterpreted by findTargetlistEntrySQL92()) if
6313 * we dump it without any decoration. Similarly, if it's just a Var,
6314 * there is risk of misinterpretation if the column name is reassigned in
6315 * the SELECT list, so we may need to force table qualification. And, if
6316 * it's anything more complex than a simple Var, then force extra parens
6317 * around it, to ensure it can't be misinterpreted as a cube() or rollup()
6318 * construct.
6320 if (force_colno)
6322 Assert(!tle->resjunk);
6323 appendStringInfo(buf, "%d", tle->resno);
6325 else if (!expr)
6326 /* do nothing, probably can't happen */ ;
6327 else if (IsA(expr, Const))
6328 get_const_expr((Const *) expr, context, 1);
6329 else if (IsA(expr, Var))
6331 /* Tell get_variable to check for name conflict */
6332 bool save_varinorderby = context->varInOrderBy;
6334 context->varInOrderBy = true;
6335 (void) get_variable((Var *) expr, 0, false, context);
6336 context->varInOrderBy = save_varinorderby;
6338 else
6341 * We must force parens for function-like expressions even if
6342 * PRETTY_PAREN is off, since those are the ones in danger of
6343 * misparsing. For other expressions we need to force them only if
6344 * PRETTY_PAREN is on, since otherwise the expression will output them
6345 * itself. (We can't skip the parens.)
6347 bool need_paren = (PRETTY_PAREN(context)
6348 || IsA(expr, FuncExpr)
6349 || IsA(expr, Aggref)
6350 || IsA(expr, WindowFunc)
6351 || IsA(expr, JsonConstructorExpr));
6353 if (need_paren)
6354 appendStringInfoChar(context->buf, '(');
6355 get_rule_expr(expr, context, true);
6356 if (need_paren)
6357 appendStringInfoChar(context->buf, ')');
6360 return expr;
6364 * Display a GroupingSet
6366 static void
6367 get_rule_groupingset(GroupingSet *gset, List *targetlist,
6368 bool omit_parens, deparse_context *context)
6370 ListCell *l;
6371 StringInfo buf = context->buf;
6372 bool omit_child_parens = true;
6373 char *sep = "";
6375 switch (gset->kind)
6377 case GROUPING_SET_EMPTY:
6378 appendStringInfoString(buf, "()");
6379 return;
6381 case GROUPING_SET_SIMPLE:
6383 if (!omit_parens || list_length(gset->content) != 1)
6384 appendStringInfoChar(buf, '(');
6386 foreach(l, gset->content)
6388 Index ref = lfirst_int(l);
6390 appendStringInfoString(buf, sep);
6391 get_rule_sortgroupclause(ref, targetlist,
6392 false, context);
6393 sep = ", ";
6396 if (!omit_parens || list_length(gset->content) != 1)
6397 appendStringInfoChar(buf, ')');
6399 return;
6401 case GROUPING_SET_ROLLUP:
6402 appendStringInfoString(buf, "ROLLUP(");
6403 break;
6404 case GROUPING_SET_CUBE:
6405 appendStringInfoString(buf, "CUBE(");
6406 break;
6407 case GROUPING_SET_SETS:
6408 appendStringInfoString(buf, "GROUPING SETS (");
6409 omit_child_parens = false;
6410 break;
6413 foreach(l, gset->content)
6415 appendStringInfoString(buf, sep);
6416 get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context);
6417 sep = ", ";
6420 appendStringInfoChar(buf, ')');
6424 * Display an ORDER BY list.
6426 static void
6427 get_rule_orderby(List *orderList, List *targetList,
6428 bool force_colno, deparse_context *context)
6430 StringInfo buf = context->buf;
6431 const char *sep;
6432 ListCell *l;
6434 sep = "";
6435 foreach(l, orderList)
6437 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
6438 Node *sortexpr;
6439 Oid sortcoltype;
6440 TypeCacheEntry *typentry;
6442 appendStringInfoString(buf, sep);
6443 sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList,
6444 force_colno, context);
6445 sortcoltype = exprType(sortexpr);
6446 /* See whether operator is default < or > for datatype */
6447 typentry = lookup_type_cache(sortcoltype,
6448 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
6449 if (srt->sortop == typentry->lt_opr)
6451 /* ASC is default, so emit nothing for it */
6452 if (srt->nulls_first)
6453 appendStringInfoString(buf, " NULLS FIRST");
6455 else if (srt->sortop == typentry->gt_opr)
6457 appendStringInfoString(buf, " DESC");
6458 /* DESC defaults to NULLS FIRST */
6459 if (!srt->nulls_first)
6460 appendStringInfoString(buf, " NULLS LAST");
6462 else
6464 appendStringInfo(buf, " USING %s",
6465 generate_operator_name(srt->sortop,
6466 sortcoltype,
6467 sortcoltype));
6468 /* be specific to eliminate ambiguity */
6469 if (srt->nulls_first)
6470 appendStringInfoString(buf, " NULLS FIRST");
6471 else
6472 appendStringInfoString(buf, " NULLS LAST");
6474 sep = ", ";
6479 * Display a WINDOW clause.
6481 * Note that the windowClause list might contain only anonymous window
6482 * specifications, in which case we should print nothing here.
6484 static void
6485 get_rule_windowclause(Query *query, deparse_context *context)
6487 StringInfo buf = context->buf;
6488 const char *sep;
6489 ListCell *l;
6491 sep = NULL;
6492 foreach(l, query->windowClause)
6494 WindowClause *wc = (WindowClause *) lfirst(l);
6496 if (wc->name == NULL)
6497 continue; /* ignore anonymous windows */
6499 if (sep == NULL)
6500 appendContextKeyword(context, " WINDOW ",
6501 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6502 else
6503 appendStringInfoString(buf, sep);
6505 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
6507 get_rule_windowspec(wc, query->targetList, context);
6509 sep = ", ";
6514 * Display a window definition
6516 static void
6517 get_rule_windowspec(WindowClause *wc, List *targetList,
6518 deparse_context *context)
6520 StringInfo buf = context->buf;
6521 bool needspace = false;
6522 const char *sep;
6523 ListCell *l;
6525 appendStringInfoChar(buf, '(');
6526 if (wc->refname)
6528 appendStringInfoString(buf, quote_identifier(wc->refname));
6529 needspace = true;
6531 /* partition clauses are always inherited, so only print if no refname */
6532 if (wc->partitionClause && !wc->refname)
6534 if (needspace)
6535 appendStringInfoChar(buf, ' ');
6536 appendStringInfoString(buf, "PARTITION BY ");
6537 sep = "";
6538 foreach(l, wc->partitionClause)
6540 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
6542 appendStringInfoString(buf, sep);
6543 get_rule_sortgroupclause(grp->tleSortGroupRef, targetList,
6544 false, context);
6545 sep = ", ";
6547 needspace = true;
6549 /* print ordering clause only if not inherited */
6550 if (wc->orderClause && !wc->copiedOrder)
6552 if (needspace)
6553 appendStringInfoChar(buf, ' ');
6554 appendStringInfoString(buf, "ORDER BY ");
6555 get_rule_orderby(wc->orderClause, targetList, false, context);
6556 needspace = true;
6558 /* framing clause is never inherited, so print unless it's default */
6559 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
6561 if (needspace)
6562 appendStringInfoChar(buf, ' ');
6563 if (wc->frameOptions & FRAMEOPTION_RANGE)
6564 appendStringInfoString(buf, "RANGE ");
6565 else if (wc->frameOptions & FRAMEOPTION_ROWS)
6566 appendStringInfoString(buf, "ROWS ");
6567 else if (wc->frameOptions & FRAMEOPTION_GROUPS)
6568 appendStringInfoString(buf, "GROUPS ");
6569 else
6570 Assert(false);
6571 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
6572 appendStringInfoString(buf, "BETWEEN ");
6573 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
6574 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
6575 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
6576 appendStringInfoString(buf, "CURRENT ROW ");
6577 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET)
6579 get_rule_expr(wc->startOffset, context, false);
6580 if (wc->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
6581 appendStringInfoString(buf, " PRECEDING ");
6582 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
6583 appendStringInfoString(buf, " FOLLOWING ");
6584 else
6585 Assert(false);
6587 else
6588 Assert(false);
6589 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
6591 appendStringInfoString(buf, "AND ");
6592 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
6593 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
6594 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
6595 appendStringInfoString(buf, "CURRENT ROW ");
6596 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET)
6598 get_rule_expr(wc->endOffset, context, false);
6599 if (wc->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
6600 appendStringInfoString(buf, " PRECEDING ");
6601 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
6602 appendStringInfoString(buf, " FOLLOWING ");
6603 else
6604 Assert(false);
6606 else
6607 Assert(false);
6609 if (wc->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
6610 appendStringInfoString(buf, "EXCLUDE CURRENT ROW ");
6611 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
6612 appendStringInfoString(buf, "EXCLUDE GROUP ");
6613 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
6614 appendStringInfoString(buf, "EXCLUDE TIES ");
6615 /* we will now have a trailing space; remove it */
6616 buf->len--;
6618 appendStringInfoChar(buf, ')');
6621 /* ----------
6622 * get_insert_query_def - Parse back an INSERT parsetree
6623 * ----------
6625 static void
6626 get_insert_query_def(Query *query, deparse_context *context)
6628 StringInfo buf = context->buf;
6629 RangeTblEntry *select_rte = NULL;
6630 RangeTblEntry *values_rte = NULL;
6631 RangeTblEntry *rte;
6632 char *sep;
6633 ListCell *l;
6634 List *strippedexprs;
6636 /* Insert the WITH clause if given */
6637 get_with_clause(query, context);
6640 * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6641 * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6643 foreach(l, query->rtable)
6645 rte = (RangeTblEntry *) lfirst(l);
6647 if (rte->rtekind == RTE_SUBQUERY)
6649 if (select_rte)
6650 elog(ERROR, "too many subquery RTEs in INSERT");
6651 select_rte = rte;
6654 if (rte->rtekind == RTE_VALUES)
6656 if (values_rte)
6657 elog(ERROR, "too many values RTEs in INSERT");
6658 values_rte = rte;
6661 if (select_rte && values_rte)
6662 elog(ERROR, "both subquery and values RTEs in INSERT");
6665 * Start the query with INSERT INTO relname
6667 rte = rt_fetch(query->resultRelation, query->rtable);
6668 Assert(rte->rtekind == RTE_RELATION);
6670 if (PRETTY_INDENT(context))
6672 context->indentLevel += PRETTYINDENT_STD;
6673 appendStringInfoChar(buf, ' ');
6675 appendStringInfo(buf, "INSERT INTO %s",
6676 generate_relation_name(rte->relid, NIL));
6678 /* Print the relation alias, if needed; INSERT requires explicit AS */
6679 get_rte_alias(rte, query->resultRelation, true, context);
6681 /* always want a space here */
6682 appendStringInfoChar(buf, ' ');
6685 * Add the insert-column-names list. Any indirection decoration needed on
6686 * the column names can be inferred from the top targetlist.
6688 strippedexprs = NIL;
6689 sep = "";
6690 if (query->targetList)
6691 appendStringInfoChar(buf, '(');
6692 foreach(l, query->targetList)
6694 TargetEntry *tle = (TargetEntry *) lfirst(l);
6696 if (tle->resjunk)
6697 continue; /* ignore junk entries */
6699 appendStringInfoString(buf, sep);
6700 sep = ", ";
6703 * Put out name of target column; look in the catalogs, not at
6704 * tle->resname, since resname will fail to track RENAME.
6706 appendStringInfoString(buf,
6707 quote_identifier(get_attname(rte->relid,
6708 tle->resno,
6709 false)));
6712 * Print any indirection needed (subfields or subscripts), and strip
6713 * off the top-level nodes representing the indirection assignments.
6714 * Add the stripped expressions to strippedexprs. (If it's a
6715 * single-VALUES statement, the stripped expressions are the VALUES to
6716 * print below. Otherwise they're just Vars and not really
6717 * interesting.)
6719 strippedexprs = lappend(strippedexprs,
6720 processIndirection((Node *) tle->expr,
6721 context));
6723 if (query->targetList)
6724 appendStringInfoString(buf, ") ");
6726 if (query->override)
6728 if (query->override == OVERRIDING_SYSTEM_VALUE)
6729 appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6730 else if (query->override == OVERRIDING_USER_VALUE)
6731 appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6734 if (select_rte)
6736 /* Add the SELECT */
6737 get_query_def(select_rte->subquery, buf, context->namespaces, NULL,
6738 false,
6739 context->prettyFlags, context->wrapColumn,
6740 context->indentLevel);
6742 else if (values_rte)
6744 /* Add the multi-VALUES expression lists */
6745 get_values_def(values_rte->values_lists, context);
6747 else if (strippedexprs)
6749 /* Add the single-VALUES expression list */
6750 appendContextKeyword(context, "VALUES (",
6751 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6752 get_rule_list_toplevel(strippedexprs, context, false);
6753 appendStringInfoChar(buf, ')');
6755 else
6757 /* No expressions, so it must be DEFAULT VALUES */
6758 appendStringInfoString(buf, "DEFAULT VALUES");
6761 /* Add ON CONFLICT if present */
6762 if (query->onConflict)
6764 OnConflictExpr *confl = query->onConflict;
6766 appendStringInfoString(buf, " ON CONFLICT");
6768 if (confl->arbiterElems)
6770 /* Add the single-VALUES expression list */
6771 appendStringInfoChar(buf, '(');
6772 get_rule_expr((Node *) confl->arbiterElems, context, false);
6773 appendStringInfoChar(buf, ')');
6775 /* Add a WHERE clause (for partial indexes) if given */
6776 if (confl->arbiterWhere != NULL)
6778 bool save_varprefix;
6781 * Force non-prefixing of Vars, since parser assumes that they
6782 * belong to target relation. WHERE clause does not use
6783 * InferenceElem, so this is separately required.
6785 save_varprefix = context->varprefix;
6786 context->varprefix = false;
6788 appendContextKeyword(context, " WHERE ",
6789 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6790 get_rule_expr(confl->arbiterWhere, context, false);
6792 context->varprefix = save_varprefix;
6795 else if (OidIsValid(confl->constraint))
6797 char *constraint = get_constraint_name(confl->constraint);
6799 if (!constraint)
6800 elog(ERROR, "cache lookup failed for constraint %u",
6801 confl->constraint);
6802 appendStringInfo(buf, " ON CONSTRAINT %s",
6803 quote_identifier(constraint));
6806 if (confl->action == ONCONFLICT_NOTHING)
6808 appendStringInfoString(buf, " DO NOTHING");
6810 else
6812 appendStringInfoString(buf, " DO UPDATE SET ");
6813 /* Deparse targetlist */
6814 get_update_query_targetlist_def(query, confl->onConflictSet,
6815 context, rte);
6817 /* Add a WHERE clause if given */
6818 if (confl->onConflictWhere != NULL)
6820 appendContextKeyword(context, " WHERE ",
6821 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6822 get_rule_expr(confl->onConflictWhere, context, false);
6827 /* Add RETURNING if present */
6828 if (query->returningList)
6830 appendContextKeyword(context, " RETURNING",
6831 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6832 get_target_list(query->returningList, context);
6837 /* ----------
6838 * get_update_query_def - Parse back an UPDATE parsetree
6839 * ----------
6841 static void
6842 get_update_query_def(Query *query, deparse_context *context)
6844 StringInfo buf = context->buf;
6845 RangeTblEntry *rte;
6847 /* Insert the WITH clause if given */
6848 get_with_clause(query, context);
6851 * Start the query with UPDATE relname SET
6853 rte = rt_fetch(query->resultRelation, query->rtable);
6854 Assert(rte->rtekind == RTE_RELATION);
6855 if (PRETTY_INDENT(context))
6857 appendStringInfoChar(buf, ' ');
6858 context->indentLevel += PRETTYINDENT_STD;
6860 appendStringInfo(buf, "UPDATE %s%s",
6861 only_marker(rte),
6862 generate_relation_name(rte->relid, NIL));
6864 /* Print the relation alias, if needed */
6865 get_rte_alias(rte, query->resultRelation, false, context);
6867 appendStringInfoString(buf, " SET ");
6869 /* Deparse targetlist */
6870 get_update_query_targetlist_def(query, query->targetList, context, rte);
6872 /* Add the FROM clause if needed */
6873 get_from_clause(query, " FROM ", context);
6875 /* Add a WHERE clause if given */
6876 if (query->jointree->quals != NULL)
6878 appendContextKeyword(context, " WHERE ",
6879 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6880 get_rule_expr(query->jointree->quals, context, false);
6883 /* Add RETURNING if present */
6884 if (query->returningList)
6886 appendContextKeyword(context, " RETURNING",
6887 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6888 get_target_list(query->returningList, context);
6893 /* ----------
6894 * get_update_query_targetlist_def - Parse back an UPDATE targetlist
6895 * ----------
6897 static void
6898 get_update_query_targetlist_def(Query *query, List *targetList,
6899 deparse_context *context, RangeTblEntry *rte)
6901 StringInfo buf = context->buf;
6902 ListCell *l;
6903 ListCell *next_ma_cell;
6904 int remaining_ma_columns;
6905 const char *sep;
6906 SubLink *cur_ma_sublink;
6907 List *ma_sublinks;
6910 * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks
6911 * into a list. We expect them to appear, in ID order, in resjunk tlist
6912 * entries.
6914 ma_sublinks = NIL;
6915 if (query->hasSubLinks) /* else there can't be any */
6917 foreach(l, targetList)
6919 TargetEntry *tle = (TargetEntry *) lfirst(l);
6921 if (tle->resjunk && IsA(tle->expr, SubLink))
6923 SubLink *sl = (SubLink *) tle->expr;
6925 if (sl->subLinkType == MULTIEXPR_SUBLINK)
6927 ma_sublinks = lappend(ma_sublinks, sl);
6928 Assert(sl->subLinkId == list_length(ma_sublinks));
6933 next_ma_cell = list_head(ma_sublinks);
6934 cur_ma_sublink = NULL;
6935 remaining_ma_columns = 0;
6937 /* Add the comma separated list of 'attname = value' */
6938 sep = "";
6939 foreach(l, targetList)
6941 TargetEntry *tle = (TargetEntry *) lfirst(l);
6942 Node *expr;
6944 if (tle->resjunk)
6945 continue; /* ignore junk entries */
6947 /* Emit separator (OK whether we're in multiassignment or not) */
6948 appendStringInfoString(buf, sep);
6949 sep = ", ";
6952 * Check to see if we're starting a multiassignment group: if so,
6953 * output a left paren.
6955 if (next_ma_cell != NULL && cur_ma_sublink == NULL)
6958 * We must dig down into the expr to see if it's a PARAM_MULTIEXPR
6959 * Param. That could be buried under FieldStores and
6960 * SubscriptingRefs and CoerceToDomains (cf processIndirection()),
6961 * and underneath those there could be an implicit type coercion.
6962 * Because we would ignore implicit type coercions anyway, we
6963 * don't need to be as careful as processIndirection() is about
6964 * descending past implicit CoerceToDomains.
6966 expr = (Node *) tle->expr;
6967 while (expr)
6969 if (IsA(expr, FieldStore))
6971 FieldStore *fstore = (FieldStore *) expr;
6973 expr = (Node *) linitial(fstore->newvals);
6975 else if (IsA(expr, SubscriptingRef))
6977 SubscriptingRef *sbsref = (SubscriptingRef *) expr;
6979 if (sbsref->refassgnexpr == NULL)
6980 break;
6982 expr = (Node *) sbsref->refassgnexpr;
6984 else if (IsA(expr, CoerceToDomain))
6986 CoerceToDomain *cdomain = (CoerceToDomain *) expr;
6988 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
6989 break;
6990 expr = (Node *) cdomain->arg;
6992 else
6993 break;
6995 expr = strip_implicit_coercions(expr);
6997 if (expr && IsA(expr, Param) &&
6998 ((Param *) expr)->paramkind == PARAM_MULTIEXPR)
7000 cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
7001 next_ma_cell = lnext(ma_sublinks, next_ma_cell);
7002 remaining_ma_columns = count_nonjunk_tlist_entries(((Query *) cur_ma_sublink->subselect)->targetList);
7003 Assert(((Param *) expr)->paramid ==
7004 ((cur_ma_sublink->subLinkId << 16) | 1));
7005 appendStringInfoChar(buf, '(');
7010 * Put out name of target column; look in the catalogs, not at
7011 * tle->resname, since resname will fail to track RENAME.
7013 appendStringInfoString(buf,
7014 quote_identifier(get_attname(rte->relid,
7015 tle->resno,
7016 false)));
7019 * Print any indirection needed (subfields or subscripts), and strip
7020 * off the top-level nodes representing the indirection assignments.
7022 expr = processIndirection((Node *) tle->expr, context);
7025 * If we're in a multiassignment, skip printing anything more, unless
7026 * this is the last column; in which case, what we print should be the
7027 * sublink, not the Param.
7029 if (cur_ma_sublink != NULL)
7031 if (--remaining_ma_columns > 0)
7032 continue; /* not the last column of multiassignment */
7033 appendStringInfoChar(buf, ')');
7034 expr = (Node *) cur_ma_sublink;
7035 cur_ma_sublink = NULL;
7038 appendStringInfoString(buf, " = ");
7040 get_rule_expr(expr, context, false);
7045 /* ----------
7046 * get_delete_query_def - Parse back a DELETE parsetree
7047 * ----------
7049 static void
7050 get_delete_query_def(Query *query, deparse_context *context)
7052 StringInfo buf = context->buf;
7053 RangeTblEntry *rte;
7055 /* Insert the WITH clause if given */
7056 get_with_clause(query, context);
7059 * Start the query with DELETE FROM relname
7061 rte = rt_fetch(query->resultRelation, query->rtable);
7062 Assert(rte->rtekind == RTE_RELATION);
7063 if (PRETTY_INDENT(context))
7065 appendStringInfoChar(buf, ' ');
7066 context->indentLevel += PRETTYINDENT_STD;
7068 appendStringInfo(buf, "DELETE FROM %s%s",
7069 only_marker(rte),
7070 generate_relation_name(rte->relid, NIL));
7072 /* Print the relation alias, if needed */
7073 get_rte_alias(rte, query->resultRelation, false, context);
7075 /* Add the USING clause if given */
7076 get_from_clause(query, " USING ", context);
7078 /* Add a WHERE clause if given */
7079 if (query->jointree->quals != NULL)
7081 appendContextKeyword(context, " WHERE ",
7082 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
7083 get_rule_expr(query->jointree->quals, context, false);
7086 /* Add RETURNING if present */
7087 if (query->returningList)
7089 appendContextKeyword(context, " RETURNING",
7090 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
7091 get_target_list(query->returningList, context);
7096 /* ----------
7097 * get_merge_query_def - Parse back a MERGE parsetree
7098 * ----------
7100 static void
7101 get_merge_query_def(Query *query, deparse_context *context)
7103 StringInfo buf = context->buf;
7104 RangeTblEntry *rte;
7105 ListCell *lc;
7106 bool haveNotMatchedBySource;
7108 /* Insert the WITH clause if given */
7109 get_with_clause(query, context);
7112 * Start the query with MERGE INTO relname
7114 rte = rt_fetch(query->resultRelation, query->rtable);
7115 Assert(rte->rtekind == RTE_RELATION);
7116 if (PRETTY_INDENT(context))
7118 appendStringInfoChar(buf, ' ');
7119 context->indentLevel += PRETTYINDENT_STD;
7121 appendStringInfo(buf, "MERGE INTO %s%s",
7122 only_marker(rte),
7123 generate_relation_name(rte->relid, NIL));
7125 /* Print the relation alias, if needed */
7126 get_rte_alias(rte, query->resultRelation, false, context);
7128 /* Print the source relation and join clause */
7129 get_from_clause(query, " USING ", context);
7130 appendContextKeyword(context, " ON ",
7131 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
7132 get_rule_expr(query->mergeJoinCondition, context, false);
7135 * Test for any NOT MATCHED BY SOURCE actions. If there are none, then
7136 * any NOT MATCHED BY TARGET actions are output as "WHEN NOT MATCHED", per
7137 * SQL standard. Otherwise, we have a non-SQL-standard query, so output
7138 * "BY SOURCE" / "BY TARGET" qualifiers for all NOT MATCHED actions, to be
7139 * more explicit.
7141 haveNotMatchedBySource = false;
7142 foreach(lc, query->mergeActionList)
7144 MergeAction *action = lfirst_node(MergeAction, lc);
7146 if (action->matchKind == MERGE_WHEN_NOT_MATCHED_BY_SOURCE)
7148 haveNotMatchedBySource = true;
7149 break;
7153 /* Print each merge action */
7154 foreach(lc, query->mergeActionList)
7156 MergeAction *action = lfirst_node(MergeAction, lc);
7158 appendContextKeyword(context, " WHEN ",
7159 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
7160 switch (action->matchKind)
7162 case MERGE_WHEN_MATCHED:
7163 appendStringInfoString(buf, "MATCHED");
7164 break;
7165 case MERGE_WHEN_NOT_MATCHED_BY_SOURCE:
7166 appendStringInfoString(buf, "NOT MATCHED BY SOURCE");
7167 break;
7168 case MERGE_WHEN_NOT_MATCHED_BY_TARGET:
7169 if (haveNotMatchedBySource)
7170 appendStringInfoString(buf, "NOT MATCHED BY TARGET");
7171 else
7172 appendStringInfoString(buf, "NOT MATCHED");
7173 break;
7174 default:
7175 elog(ERROR, "unrecognized matchKind: %d",
7176 (int) action->matchKind);
7179 if (action->qual)
7181 appendContextKeyword(context, " AND ",
7182 -PRETTYINDENT_STD, PRETTYINDENT_STD, 3);
7183 get_rule_expr(action->qual, context, false);
7185 appendContextKeyword(context, " THEN ",
7186 -PRETTYINDENT_STD, PRETTYINDENT_STD, 3);
7188 if (action->commandType == CMD_INSERT)
7190 /* This generally matches get_insert_query_def() */
7191 List *strippedexprs = NIL;
7192 const char *sep = "";
7193 ListCell *lc2;
7195 appendStringInfoString(buf, "INSERT");
7197 if (action->targetList)
7198 appendStringInfoString(buf, " (");
7199 foreach(lc2, action->targetList)
7201 TargetEntry *tle = (TargetEntry *) lfirst(lc2);
7203 Assert(!tle->resjunk);
7205 appendStringInfoString(buf, sep);
7206 sep = ", ";
7208 appendStringInfoString(buf,
7209 quote_identifier(get_attname(rte->relid,
7210 tle->resno,
7211 false)));
7212 strippedexprs = lappend(strippedexprs,
7213 processIndirection((Node *) tle->expr,
7214 context));
7216 if (action->targetList)
7217 appendStringInfoChar(buf, ')');
7219 if (action->override)
7221 if (action->override == OVERRIDING_SYSTEM_VALUE)
7222 appendStringInfoString(buf, " OVERRIDING SYSTEM VALUE");
7223 else if (action->override == OVERRIDING_USER_VALUE)
7224 appendStringInfoString(buf, " OVERRIDING USER VALUE");
7227 if (strippedexprs)
7229 appendContextKeyword(context, " VALUES (",
7230 -PRETTYINDENT_STD, PRETTYINDENT_STD, 4);
7231 get_rule_list_toplevel(strippedexprs, context, false);
7232 appendStringInfoChar(buf, ')');
7234 else
7235 appendStringInfoString(buf, " DEFAULT VALUES");
7237 else if (action->commandType == CMD_UPDATE)
7239 appendStringInfoString(buf, "UPDATE SET ");
7240 get_update_query_targetlist_def(query, action->targetList,
7241 context, rte);
7243 else if (action->commandType == CMD_DELETE)
7244 appendStringInfoString(buf, "DELETE");
7245 else if (action->commandType == CMD_NOTHING)
7246 appendStringInfoString(buf, "DO NOTHING");
7249 /* Add RETURNING if present */
7250 if (query->returningList)
7252 appendContextKeyword(context, " RETURNING",
7253 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
7254 get_target_list(query->returningList, context);
7259 /* ----------
7260 * get_utility_query_def - Parse back a UTILITY parsetree
7261 * ----------
7263 static void
7264 get_utility_query_def(Query *query, deparse_context *context)
7266 StringInfo buf = context->buf;
7268 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
7270 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
7272 appendContextKeyword(context, "",
7273 0, PRETTYINDENT_STD, 1);
7274 appendStringInfo(buf, "NOTIFY %s",
7275 quote_identifier(stmt->conditionname));
7276 if (stmt->payload)
7278 appendStringInfoString(buf, ", ");
7279 simple_quote_literal(buf, stmt->payload);
7282 else
7284 /* Currently only NOTIFY utility commands can appear in rules */
7285 elog(ERROR, "unexpected utility statement type");
7290 * Display a Var appropriately.
7292 * In some cases (currently only when recursing into an unnamed join)
7293 * the Var's varlevelsup has to be interpreted with respect to a context
7294 * above the current one; levelsup indicates the offset.
7296 * If istoplevel is true, the Var is at the top level of a SELECT's
7297 * targetlist, which means we need special treatment of whole-row Vars.
7298 * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a
7299 * dirty hack to prevent "tab.*" from being expanded into multiple columns.
7300 * (The parser will strip the useless coercion, so no inefficiency is added in
7301 * dump and reload.) We used to print just "tab" in such cases, but that is
7302 * ambiguous and will yield the wrong result if "tab" is also a plain column
7303 * name in the query.
7305 * Returns the attname of the Var, or NULL if the Var has no attname (because
7306 * it is a whole-row Var or a subplan output reference).
7308 static char *
7309 get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
7311 StringInfo buf = context->buf;
7312 RangeTblEntry *rte;
7313 AttrNumber attnum;
7314 int netlevelsup;
7315 deparse_namespace *dpns;
7316 int varno;
7317 AttrNumber varattno;
7318 deparse_columns *colinfo;
7319 char *refname;
7320 char *attname;
7321 bool need_prefix;
7323 /* Find appropriate nesting depth */
7324 netlevelsup = var->varlevelsup + levelsup;
7325 if (netlevelsup >= list_length(context->namespaces))
7326 elog(ERROR, "bogus varlevelsup: %d offset %d",
7327 var->varlevelsup, levelsup);
7328 dpns = (deparse_namespace *) list_nth(context->namespaces,
7329 netlevelsup);
7332 * If we have a syntactic referent for the Var, and we're working from a
7333 * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7334 * on the semantic referent. (Forcing use of the semantic referent when
7335 * printing plan trees is a design choice that's perhaps more motivated by
7336 * backwards compatibility than anything else. But it does have the
7337 * advantage of making plans more explicit.)
7339 if (var->varnosyn > 0 && dpns->plan == NULL)
7341 varno = var->varnosyn;
7342 varattno = var->varattnosyn;
7344 else
7346 varno = var->varno;
7347 varattno = var->varattno;
7351 * Try to find the relevant RTE in this rtable. In a plan tree, it's
7352 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7353 * down into the subplans, or INDEX_VAR, which is resolved similarly. Also
7354 * find the aliases previously assigned for this RTE.
7356 if (varno >= 1 && varno <= list_length(dpns->rtable))
7359 * We might have been asked to map child Vars to some parent relation.
7361 if (context->appendparents && dpns->appendrels)
7363 int pvarno = varno;
7364 AttrNumber pvarattno = varattno;
7365 AppendRelInfo *appinfo = dpns->appendrels[pvarno];
7366 bool found = false;
7368 /* Only map up to inheritance parents, not UNION ALL appendrels */
7369 while (appinfo &&
7370 rt_fetch(appinfo->parent_relid,
7371 dpns->rtable)->rtekind == RTE_RELATION)
7373 found = false;
7374 if (pvarattno > 0) /* system columns stay as-is */
7376 if (pvarattno > appinfo->num_child_cols)
7377 break; /* safety check */
7378 pvarattno = appinfo->parent_colnos[pvarattno - 1];
7379 if (pvarattno == 0)
7380 break; /* Var is local to child */
7383 pvarno = appinfo->parent_relid;
7384 found = true;
7386 /* If the parent is itself a child, continue up. */
7387 Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable));
7388 appinfo = dpns->appendrels[pvarno];
7392 * If we found an ancestral rel, and that rel is included in
7393 * appendparents, print that column not the original one.
7395 if (found && bms_is_member(pvarno, context->appendparents))
7397 varno = pvarno;
7398 varattno = pvarattno;
7402 rte = rt_fetch(varno, dpns->rtable);
7403 refname = (char *) list_nth(dpns->rtable_names, varno - 1);
7404 colinfo = deparse_columns_fetch(varno, dpns);
7405 attnum = varattno;
7407 else
7409 resolve_special_varno((Node *) var, context,
7410 get_special_variable, NULL);
7411 return NULL;
7415 * The planner will sometimes emit Vars referencing resjunk elements of a
7416 * subquery's target list (this is currently only possible if it chooses
7417 * to generate a "physical tlist" for a SubqueryScan or CteScan node).
7418 * Although we prefer to print subquery-referencing Vars using the
7419 * subquery's alias, that's not possible for resjunk items since they have
7420 * no alias. So in that case, drill down to the subplan and print the
7421 * contents of the referenced tlist item. This works because in a plan
7422 * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
7423 * we'll have set dpns->inner_plan to reference the child plan node.
7425 if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
7426 attnum > list_length(rte->eref->colnames) &&
7427 dpns->inner_plan)
7429 TargetEntry *tle;
7430 deparse_namespace save_dpns;
7432 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7433 if (!tle)
7434 elog(ERROR, "invalid attnum %d for relation \"%s\"",
7435 attnum, rte->eref->aliasname);
7437 Assert(netlevelsup == 0);
7438 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7441 * Force parentheses because our caller probably assumed a Var is a
7442 * simple expression.
7444 if (!IsA(tle->expr, Var))
7445 appendStringInfoChar(buf, '(');
7446 get_rule_expr((Node *) tle->expr, context, true);
7447 if (!IsA(tle->expr, Var))
7448 appendStringInfoChar(buf, ')');
7450 pop_child_plan(dpns, &save_dpns);
7451 return NULL;
7455 * If it's an unnamed join, look at the expansion of the alias variable.
7456 * If it's a simple reference to one of the input vars, then recursively
7457 * print the name of that var instead. When it's not a simple reference,
7458 * we have to just print the unqualified join column name. (This can only
7459 * happen with "dangerous" merged columns in a JOIN USING; we took pains
7460 * previously to make the unqualified column name unique in such cases.)
7462 * This wouldn't work in decompiling plan trees, because we don't store
7463 * joinaliasvars lists after planning; but a plan tree should never
7464 * contain a join alias variable.
7466 if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
7468 if (rte->joinaliasvars == NIL)
7469 elog(ERROR, "cannot decompile join alias var in plan tree");
7470 if (attnum > 0)
7472 Var *aliasvar;
7474 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
7475 /* we intentionally don't strip implicit coercions here */
7476 if (aliasvar && IsA(aliasvar, Var))
7478 return get_variable(aliasvar, var->varlevelsup + levelsup,
7479 istoplevel, context);
7484 * Unnamed join has no refname. (Note: since it's unnamed, there is
7485 * no way the user could have referenced it to create a whole-row Var
7486 * for it. So we don't have to cover that case below.)
7488 Assert(refname == NULL);
7491 if (attnum == InvalidAttrNumber)
7492 attname = NULL;
7493 else if (attnum > 0)
7495 /* Get column name to use from the colinfo struct */
7496 if (attnum > colinfo->num_cols)
7497 elog(ERROR, "invalid attnum %d for relation \"%s\"",
7498 attnum, rte->eref->aliasname);
7499 attname = colinfo->colnames[attnum - 1];
7502 * If we find a Var referencing a dropped column, it seems better to
7503 * print something (anything) than to fail. In general this should
7504 * not happen, but it used to be possible for some cases involving
7505 * functions returning named composite types, and perhaps there are
7506 * still bugs out there.
7508 if (attname == NULL)
7509 attname = "?dropped?column?";
7511 else
7513 /* System column - name is fixed, get it from the catalog */
7514 attname = get_rte_attribute_name(rte, attnum);
7517 need_prefix = (context->varprefix || attname == NULL);
7520 * If we're considering a plain Var in an ORDER BY (but not GROUP BY)
7521 * clause, we may need to add a table-name prefix to prevent
7522 * findTargetlistEntrySQL92 from misinterpreting the name as an
7523 * output-column name. To avoid cluttering the output with unnecessary
7524 * prefixes, do so only if there is a name match to a SELECT tlist item
7525 * that is different from the Var.
7527 if (context->varInOrderBy && !context->inGroupBy && !need_prefix)
7529 int colno = 0;
7531 foreach_node(TargetEntry, tle, context->targetList)
7533 char *colname;
7535 if (tle->resjunk)
7536 continue; /* ignore junk entries */
7537 colno++;
7539 /* This must match colname-choosing logic in get_target_list() */
7540 if (context->resultDesc && colno <= context->resultDesc->natts)
7541 colname = NameStr(TupleDescAttr(context->resultDesc,
7542 colno - 1)->attname);
7543 else
7544 colname = tle->resname;
7546 if (colname && strcmp(colname, attname) == 0 &&
7547 !equal(var, tle->expr))
7549 need_prefix = true;
7550 break;
7555 if (refname && need_prefix)
7557 appendStringInfoString(buf, quote_identifier(refname));
7558 appendStringInfoChar(buf, '.');
7560 if (attname)
7561 appendStringInfoString(buf, quote_identifier(attname));
7562 else
7564 appendStringInfoChar(buf, '*');
7565 if (istoplevel)
7566 appendStringInfo(buf, "::%s",
7567 format_type_with_typemod(var->vartype,
7568 var->vartypmod));
7571 return attname;
7575 * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR. This
7576 * routine is actually a callback for resolve_special_varno, which handles
7577 * finding the correct TargetEntry. We get the expression contained in that
7578 * TargetEntry and just need to deparse it, a job we can throw back on
7579 * get_rule_expr.
7581 static void
7582 get_special_variable(Node *node, deparse_context *context, void *callback_arg)
7584 StringInfo buf = context->buf;
7587 * For a non-Var referent, force parentheses because our caller probably
7588 * assumed a Var is a simple expression.
7590 if (!IsA(node, Var))
7591 appendStringInfoChar(buf, '(');
7592 get_rule_expr(node, context, true);
7593 if (!IsA(node, Var))
7594 appendStringInfoChar(buf, ')');
7598 * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR,
7599 * INDEX_VAR) until we find a real Var or some kind of non-Var node; then,
7600 * invoke the callback provided.
7602 static void
7603 resolve_special_varno(Node *node, deparse_context *context,
7604 rsv_callback callback, void *callback_arg)
7606 Var *var;
7607 deparse_namespace *dpns;
7609 /* This function is recursive, so let's be paranoid. */
7610 check_stack_depth();
7612 /* If it's not a Var, invoke the callback. */
7613 if (!IsA(node, Var))
7615 (*callback) (node, context, callback_arg);
7616 return;
7619 /* Find appropriate nesting depth */
7620 var = (Var *) node;
7621 dpns = (deparse_namespace *) list_nth(context->namespaces,
7622 var->varlevelsup);
7625 * If varno is special, recurse. (Don't worry about varnosyn; if we're
7626 * here, we already decided not to use that.)
7628 if (var->varno == OUTER_VAR && dpns->outer_tlist)
7630 TargetEntry *tle;
7631 deparse_namespace save_dpns;
7632 Bitmapset *save_appendparents;
7634 tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
7635 if (!tle)
7636 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
7639 * If we're descending to the first child of an Append or MergeAppend,
7640 * update appendparents. This will affect deparsing of all Vars
7641 * appearing within the eventually-resolved subexpression.
7643 save_appendparents = context->appendparents;
7645 if (IsA(dpns->plan, Append))
7646 context->appendparents = bms_union(context->appendparents,
7647 ((Append *) dpns->plan)->apprelids);
7648 else if (IsA(dpns->plan, MergeAppend))
7649 context->appendparents = bms_union(context->appendparents,
7650 ((MergeAppend *) dpns->plan)->apprelids);
7652 push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7653 resolve_special_varno((Node *) tle->expr, context,
7654 callback, callback_arg);
7655 pop_child_plan(dpns, &save_dpns);
7656 context->appendparents = save_appendparents;
7657 return;
7659 else if (var->varno == INNER_VAR && dpns->inner_tlist)
7661 TargetEntry *tle;
7662 deparse_namespace save_dpns;
7664 tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
7665 if (!tle)
7666 elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
7668 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7669 resolve_special_varno((Node *) tle->expr, context,
7670 callback, callback_arg);
7671 pop_child_plan(dpns, &save_dpns);
7672 return;
7674 else if (var->varno == INDEX_VAR && dpns->index_tlist)
7676 TargetEntry *tle;
7678 tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
7679 if (!tle)
7680 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
7682 resolve_special_varno((Node *) tle->expr, context,
7683 callback, callback_arg);
7684 return;
7686 else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
7687 elog(ERROR, "bogus varno: %d", var->varno);
7689 /* Not special. Just invoke the callback. */
7690 (*callback) (node, context, callback_arg);
7694 * Get the name of a field of an expression of composite type. The
7695 * expression is usually a Var, but we handle other cases too.
7697 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
7699 * This is fairly straightforward when the expression has a named composite
7700 * type; we need only look up the type in the catalogs. However, the type
7701 * could also be RECORD. Since no actual table or view column is allowed to
7702 * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
7703 * or to a subquery output. We drill down to find the ultimate defining
7704 * expression and attempt to infer the field name from it. We ereport if we
7705 * can't determine the name.
7707 * Similarly, a PARAM of type RECORD has to refer to some expression of
7708 * a determinable composite type.
7710 static const char *
7711 get_name_for_var_field(Var *var, int fieldno,
7712 int levelsup, deparse_context *context)
7714 RangeTblEntry *rte;
7715 AttrNumber attnum;
7716 int netlevelsup;
7717 deparse_namespace *dpns;
7718 int varno;
7719 AttrNumber varattno;
7720 TupleDesc tupleDesc;
7721 Node *expr;
7724 * If it's a RowExpr that was expanded from a whole-row Var, use the
7725 * column names attached to it. (We could let get_expr_result_tupdesc()
7726 * handle this, but it's much cheaper to just pull out the name we need.)
7728 if (IsA(var, RowExpr))
7730 RowExpr *r = (RowExpr *) var;
7732 if (fieldno > 0 && fieldno <= list_length(r->colnames))
7733 return strVal(list_nth(r->colnames, fieldno - 1));
7737 * If it's a Param of type RECORD, try to find what the Param refers to.
7739 if (IsA(var, Param))
7741 Param *param = (Param *) var;
7742 ListCell *ancestor_cell;
7744 expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7745 if (expr)
7747 /* Found a match, so recurse to decipher the field name */
7748 deparse_namespace save_dpns;
7749 const char *result;
7751 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7752 result = get_name_for_var_field((Var *) expr, fieldno,
7753 0, context);
7754 pop_ancestor_plan(dpns, &save_dpns);
7755 return result;
7760 * If it's a Var of type RECORD, we have to find what the Var refers to;
7761 * if not, we can use get_expr_result_tupdesc().
7763 if (!IsA(var, Var) ||
7764 var->vartype != RECORDOID)
7766 tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7767 /* Got the tupdesc, so we can extract the field name */
7768 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7769 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7772 /* Find appropriate nesting depth */
7773 netlevelsup = var->varlevelsup + levelsup;
7774 if (netlevelsup >= list_length(context->namespaces))
7775 elog(ERROR, "bogus varlevelsup: %d offset %d",
7776 var->varlevelsup, levelsup);
7777 dpns = (deparse_namespace *) list_nth(context->namespaces,
7778 netlevelsup);
7781 * If we have a syntactic referent for the Var, and we're working from a
7782 * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7783 * on the semantic referent. (See comments in get_variable().)
7785 if (var->varnosyn > 0 && dpns->plan == NULL)
7787 varno = var->varnosyn;
7788 varattno = var->varattnosyn;
7790 else
7792 varno = var->varno;
7793 varattno = var->varattno;
7797 * Try to find the relevant RTE in this rtable. In a plan tree, it's
7798 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7799 * down into the subplans, or INDEX_VAR, which is resolved similarly.
7801 * Note: unlike get_variable and resolve_special_varno, we need not worry
7802 * about inheritance mapping: a child Var should have the same datatype as
7803 * its parent, and here we're really only interested in the Var's type.
7805 if (varno >= 1 && varno <= list_length(dpns->rtable))
7807 rte = rt_fetch(varno, dpns->rtable);
7808 attnum = varattno;
7810 else if (varno == OUTER_VAR && dpns->outer_tlist)
7812 TargetEntry *tle;
7813 deparse_namespace save_dpns;
7814 const char *result;
7816 tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7817 if (!tle)
7818 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7820 Assert(netlevelsup == 0);
7821 push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7823 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7824 levelsup, context);
7826 pop_child_plan(dpns, &save_dpns);
7827 return result;
7829 else if (varno == INNER_VAR && dpns->inner_tlist)
7831 TargetEntry *tle;
7832 deparse_namespace save_dpns;
7833 const char *result;
7835 tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7836 if (!tle)
7837 elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7839 Assert(netlevelsup == 0);
7840 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7842 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7843 levelsup, context);
7845 pop_child_plan(dpns, &save_dpns);
7846 return result;
7848 else if (varno == INDEX_VAR && dpns->index_tlist)
7850 TargetEntry *tle;
7851 const char *result;
7853 tle = get_tle_by_resno(dpns->index_tlist, varattno);
7854 if (!tle)
7855 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7857 Assert(netlevelsup == 0);
7859 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7860 levelsup, context);
7862 return result;
7864 else
7866 elog(ERROR, "bogus varno: %d", varno);
7867 return NULL; /* keep compiler quiet */
7870 if (attnum == InvalidAttrNumber)
7872 /* Var is whole-row reference to RTE, so select the right field */
7873 return get_rte_attribute_name(rte, fieldno);
7877 * This part has essentially the same logic as the parser's
7878 * expandRecordVariable() function, but we are dealing with a different
7879 * representation of the input context, and we only need one field name
7880 * not a TupleDesc. Also, we need special cases for finding subquery and
7881 * CTE subplans when deparsing Plan trees.
7883 expr = (Node *) var; /* default if we can't drill down */
7885 switch (rte->rtekind)
7887 case RTE_RELATION:
7888 case RTE_VALUES:
7889 case RTE_NAMEDTUPLESTORE:
7890 case RTE_RESULT:
7893 * This case should not occur: a column of a table, values list,
7894 * or ENR shouldn't have type RECORD. Fall through and fail (most
7895 * likely) at the bottom.
7897 break;
7898 case RTE_SUBQUERY:
7899 /* Subselect-in-FROM: examine sub-select's output expr */
7901 if (rte->subquery)
7903 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
7904 attnum);
7906 if (ste == NULL || ste->resjunk)
7907 elog(ERROR, "subquery %s does not have attribute %d",
7908 rte->eref->aliasname, attnum);
7909 expr = (Node *) ste->expr;
7910 if (IsA(expr, Var))
7913 * Recurse into the sub-select to see what its Var
7914 * refers to. We have to build an additional level of
7915 * namespace to keep in step with varlevelsup in the
7916 * subselect; furthermore, the subquery RTE might be
7917 * from an outer query level, in which case the
7918 * namespace for the subselect must have that outer
7919 * level as parent namespace.
7921 List *save_nslist = context->namespaces;
7922 List *parent_namespaces;
7923 deparse_namespace mydpns;
7924 const char *result;
7926 parent_namespaces = list_copy_tail(context->namespaces,
7927 netlevelsup);
7929 set_deparse_for_query(&mydpns, rte->subquery,
7930 parent_namespaces);
7932 context->namespaces = lcons(&mydpns, parent_namespaces);
7934 result = get_name_for_var_field((Var *) expr, fieldno,
7935 0, context);
7937 context->namespaces = save_nslist;
7939 return result;
7941 /* else fall through to inspect the expression */
7943 else
7946 * We're deparsing a Plan tree so we don't have complete
7947 * RTE entries (in particular, rte->subquery is NULL). But
7948 * the only place we'd normally see a Var directly
7949 * referencing a SUBQUERY RTE is in a SubqueryScan plan
7950 * node, and we can look into the child plan's tlist
7951 * instead. An exception occurs if the subquery was
7952 * proven empty and optimized away: then we'd find such a
7953 * Var in a childless Result node, and there's nothing in
7954 * the plan tree that would let us figure out what it had
7955 * originally referenced. In that case, fall back on
7956 * printing "fN", analogously to the default column names
7957 * for RowExprs.
7959 TargetEntry *tle;
7960 deparse_namespace save_dpns;
7961 const char *result;
7963 if (!dpns->inner_plan)
7965 char *dummy_name = palloc(32);
7967 Assert(dpns->plan && IsA(dpns->plan, Result));
7968 snprintf(dummy_name, 32, "f%d", fieldno);
7969 return dummy_name;
7971 Assert(dpns->plan && IsA(dpns->plan, SubqueryScan));
7973 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7974 if (!tle)
7975 elog(ERROR, "bogus varattno for subquery var: %d",
7976 attnum);
7977 Assert(netlevelsup == 0);
7978 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7980 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7981 levelsup, context);
7983 pop_child_plan(dpns, &save_dpns);
7984 return result;
7987 break;
7988 case RTE_JOIN:
7989 /* Join RTE --- recursively inspect the alias variable */
7990 if (rte->joinaliasvars == NIL)
7991 elog(ERROR, "cannot decompile join alias var in plan tree");
7992 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7993 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7994 Assert(expr != NULL);
7995 /* we intentionally don't strip implicit coercions here */
7996 if (IsA(expr, Var))
7997 return get_name_for_var_field((Var *) expr, fieldno,
7998 var->varlevelsup + levelsup,
7999 context);
8000 /* else fall through to inspect the expression */
8001 break;
8002 case RTE_FUNCTION:
8003 case RTE_TABLEFUNC:
8006 * We couldn't get here unless a function is declared with one of
8007 * its result columns as RECORD, which is not allowed.
8009 break;
8010 case RTE_CTE:
8011 /* CTE reference: examine subquery's output expr */
8013 CommonTableExpr *cte = NULL;
8014 Index ctelevelsup;
8015 ListCell *lc;
8018 * Try to find the referenced CTE using the namespace stack.
8020 ctelevelsup = rte->ctelevelsup + netlevelsup;
8021 if (ctelevelsup >= list_length(context->namespaces))
8022 lc = NULL;
8023 else
8025 deparse_namespace *ctedpns;
8027 ctedpns = (deparse_namespace *)
8028 list_nth(context->namespaces, ctelevelsup);
8029 foreach(lc, ctedpns->ctes)
8031 cte = (CommonTableExpr *) lfirst(lc);
8032 if (strcmp(cte->ctename, rte->ctename) == 0)
8033 break;
8036 if (lc != NULL)
8038 Query *ctequery = (Query *) cte->ctequery;
8039 TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte),
8040 attnum);
8042 if (ste == NULL || ste->resjunk)
8043 elog(ERROR, "CTE %s does not have attribute %d",
8044 rte->eref->aliasname, attnum);
8045 expr = (Node *) ste->expr;
8046 if (IsA(expr, Var))
8049 * Recurse into the CTE to see what its Var refers to.
8050 * We have to build an additional level of namespace
8051 * to keep in step with varlevelsup in the CTE;
8052 * furthermore it could be an outer CTE (compare
8053 * SUBQUERY case above).
8055 List *save_nslist = context->namespaces;
8056 List *parent_namespaces;
8057 deparse_namespace mydpns;
8058 const char *result;
8060 parent_namespaces = list_copy_tail(context->namespaces,
8061 ctelevelsup);
8063 set_deparse_for_query(&mydpns, ctequery,
8064 parent_namespaces);
8066 context->namespaces = lcons(&mydpns, parent_namespaces);
8068 result = get_name_for_var_field((Var *) expr, fieldno,
8069 0, context);
8071 context->namespaces = save_nslist;
8073 return result;
8075 /* else fall through to inspect the expression */
8077 else
8080 * We're deparsing a Plan tree so we don't have a CTE
8081 * list. But the only places we'd normally see a Var
8082 * directly referencing a CTE RTE are in CteScan or
8083 * WorkTableScan plan nodes. For those cases,
8084 * set_deparse_plan arranged for dpns->inner_plan to be
8085 * the plan node that emits the CTE or RecursiveUnion
8086 * result, and we can look at its tlist instead. As
8087 * above, this can fail if the CTE has been proven empty,
8088 * in which case fall back to "fN".
8090 TargetEntry *tle;
8091 deparse_namespace save_dpns;
8092 const char *result;
8094 if (!dpns->inner_plan)
8096 char *dummy_name = palloc(32);
8098 Assert(dpns->plan && IsA(dpns->plan, Result));
8099 snprintf(dummy_name, 32, "f%d", fieldno);
8100 return dummy_name;
8102 Assert(dpns->plan && (IsA(dpns->plan, CteScan) ||
8103 IsA(dpns->plan, WorkTableScan)));
8105 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
8106 if (!tle)
8107 elog(ERROR, "bogus varattno for subquery var: %d",
8108 attnum);
8109 Assert(netlevelsup == 0);
8110 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
8112 result = get_name_for_var_field((Var *) tle->expr, fieldno,
8113 levelsup, context);
8115 pop_child_plan(dpns, &save_dpns);
8116 return result;
8119 break;
8123 * We now have an expression we can't expand any more, so see if
8124 * get_expr_result_tupdesc() can do anything with it.
8126 tupleDesc = get_expr_result_tupdesc(expr, false);
8127 /* Got the tupdesc, so we can extract the field name */
8128 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
8129 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
8133 * Try to find the referenced expression for a PARAM_EXEC Param that might
8134 * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
8136 * If successful, return the expression and set *dpns_p and *ancestor_cell_p
8137 * appropriately for calling push_ancestor_plan(). If no referent can be
8138 * found, return NULL.
8140 static Node *
8141 find_param_referent(Param *param, deparse_context *context,
8142 deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
8144 /* Initialize output parameters to prevent compiler warnings */
8145 *dpns_p = NULL;
8146 *ancestor_cell_p = NULL;
8149 * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
8150 * SubPlan argument. This will necessarily be in some ancestor of the
8151 * current expression's Plan node.
8153 if (param->paramkind == PARAM_EXEC)
8155 deparse_namespace *dpns;
8156 Plan *child_plan;
8157 ListCell *lc;
8159 dpns = (deparse_namespace *) linitial(context->namespaces);
8160 child_plan = dpns->plan;
8162 foreach(lc, dpns->ancestors)
8164 Node *ancestor = (Node *) lfirst(lc);
8165 ListCell *lc2;
8168 * NestLoops transmit params to their inner child only.
8170 if (IsA(ancestor, NestLoop) &&
8171 child_plan == innerPlan(ancestor))
8173 NestLoop *nl = (NestLoop *) ancestor;
8175 foreach(lc2, nl->nestParams)
8177 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
8179 if (nlp->paramno == param->paramid)
8181 /* Found a match, so return it */
8182 *dpns_p = dpns;
8183 *ancestor_cell_p = lc;
8184 return (Node *) nlp->paramval;
8190 * If ancestor is a SubPlan, check the arguments it provides.
8192 if (IsA(ancestor, SubPlan))
8194 SubPlan *subplan = (SubPlan *) ancestor;
8195 ListCell *lc3;
8196 ListCell *lc4;
8198 forboth(lc3, subplan->parParam, lc4, subplan->args)
8200 int paramid = lfirst_int(lc3);
8201 Node *arg = (Node *) lfirst(lc4);
8203 if (paramid == param->paramid)
8206 * Found a match, so return it. But, since Vars in
8207 * the arg are to be evaluated in the surrounding
8208 * context, we have to point to the next ancestor item
8209 * that is *not* a SubPlan.
8211 ListCell *rest;
8213 for_each_cell(rest, dpns->ancestors,
8214 lnext(dpns->ancestors, lc))
8216 Node *ancestor2 = (Node *) lfirst(rest);
8218 if (!IsA(ancestor2, SubPlan))
8220 *dpns_p = dpns;
8221 *ancestor_cell_p = rest;
8222 return arg;
8225 elog(ERROR, "SubPlan cannot be outermost ancestor");
8229 /* SubPlan isn't a kind of Plan, so skip the rest */
8230 continue;
8234 * We need not consider the ancestor's initPlan list, since
8235 * initplans never have any parParams.
8238 /* No luck, crawl up to next ancestor */
8239 child_plan = (Plan *) ancestor;
8243 /* No referent found */
8244 return NULL;
8248 * Try to find a subplan/initplan that emits the value for a PARAM_EXEC Param.
8250 * If successful, return the generating subplan/initplan and set *column_p
8251 * to the subplan's 0-based output column number.
8252 * Otherwise, return NULL.
8254 static SubPlan *
8255 find_param_generator(Param *param, deparse_context *context, int *column_p)
8257 /* Initialize output parameter to prevent compiler warnings */
8258 *column_p = 0;
8261 * If it's a PARAM_EXEC parameter, search the current plan node as well as
8262 * ancestor nodes looking for a subplan or initplan that emits the value
8263 * for the Param. It could appear in the setParams of an initplan or
8264 * MULTIEXPR_SUBLINK subplan, or in the paramIds of an ancestral SubPlan.
8266 if (param->paramkind == PARAM_EXEC)
8268 SubPlan *result;
8269 deparse_namespace *dpns;
8270 ListCell *lc;
8272 dpns = (deparse_namespace *) linitial(context->namespaces);
8274 /* First check the innermost plan node's initplans */
8275 result = find_param_generator_initplan(param, dpns->plan, column_p);
8276 if (result)
8277 return result;
8280 * The plan's targetlist might contain MULTIEXPR_SUBLINK SubPlans,
8281 * which can be referenced by Params elsewhere in the targetlist.
8282 * (Such Params should always be in the same targetlist, so there's no
8283 * need to do this work at upper plan nodes.)
8285 foreach_node(TargetEntry, tle, dpns->plan->targetlist)
8287 if (tle->expr && IsA(tle->expr, SubPlan))
8289 SubPlan *subplan = (SubPlan *) tle->expr;
8291 if (subplan->subLinkType == MULTIEXPR_SUBLINK)
8293 foreach_int(paramid, subplan->setParam)
8295 if (paramid == param->paramid)
8297 /* Found a match, so return it. */
8298 *column_p = foreach_current_index(paramid);
8299 return subplan;
8306 /* No luck, so check the ancestor nodes */
8307 foreach(lc, dpns->ancestors)
8309 Node *ancestor = (Node *) lfirst(lc);
8312 * If ancestor is a SubPlan, check the paramIds it provides.
8314 if (IsA(ancestor, SubPlan))
8316 SubPlan *subplan = (SubPlan *) ancestor;
8318 foreach_int(paramid, subplan->paramIds)
8320 if (paramid == param->paramid)
8322 /* Found a match, so return it. */
8323 *column_p = foreach_current_index(paramid);
8324 return subplan;
8328 /* SubPlan isn't a kind of Plan, so skip the rest */
8329 continue;
8333 * Otherwise, it's some kind of Plan node, so check its initplans.
8335 result = find_param_generator_initplan(param, (Plan *) ancestor,
8336 column_p);
8337 if (result)
8338 return result;
8340 /* No luck, crawl up to next ancestor */
8344 /* No generator found */
8345 return NULL;
8349 * Subroutine for find_param_generator: search one Plan node's initplans
8351 static SubPlan *
8352 find_param_generator_initplan(Param *param, Plan *plan, int *column_p)
8354 foreach_node(SubPlan, subplan, plan->initPlan)
8356 foreach_int(paramid, subplan->setParam)
8358 if (paramid == param->paramid)
8360 /* Found a match, so return it. */
8361 *column_p = foreach_current_index(paramid);
8362 return subplan;
8366 return NULL;
8370 * Display a Param appropriately.
8372 static void
8373 get_parameter(Param *param, deparse_context *context)
8375 Node *expr;
8376 deparse_namespace *dpns;
8377 ListCell *ancestor_cell;
8378 SubPlan *subplan;
8379 int column;
8382 * If it's a PARAM_EXEC parameter, try to locate the expression from which
8383 * the parameter was computed. This stanza handles only cases in which
8384 * the Param represents an input to the subplan we are currently in.
8386 expr = find_param_referent(param, context, &dpns, &ancestor_cell);
8387 if (expr)
8389 /* Found a match, so print it */
8390 deparse_namespace save_dpns;
8391 bool save_varprefix;
8392 bool need_paren;
8394 /* Switch attention to the ancestor plan node */
8395 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
8398 * Force prefixing of Vars, since they won't belong to the relation
8399 * being scanned in the original plan node.
8401 save_varprefix = context->varprefix;
8402 context->varprefix = true;
8405 * A Param's expansion is typically a Var, Aggref, GroupingFunc, or
8406 * upper-level Param, which wouldn't need extra parentheses.
8407 * Otherwise, insert parens to ensure the expression looks atomic.
8409 need_paren = !(IsA(expr, Var) ||
8410 IsA(expr, Aggref) ||
8411 IsA(expr, GroupingFunc) ||
8412 IsA(expr, Param));
8413 if (need_paren)
8414 appendStringInfoChar(context->buf, '(');
8416 get_rule_expr(expr, context, false);
8418 if (need_paren)
8419 appendStringInfoChar(context->buf, ')');
8421 context->varprefix = save_varprefix;
8423 pop_ancestor_plan(dpns, &save_dpns);
8425 return;
8429 * Alternatively, maybe it's a subplan output, which we print as a
8430 * reference to the subplan. (We could drill down into the subplan and
8431 * print the relevant targetlist expression, but that has been deemed too
8432 * confusing since it would violate normal SQL scope rules. Also, we're
8433 * relying on this reference to show that the testexpr containing the
8434 * Param has anything to do with that subplan at all.)
8436 subplan = find_param_generator(param, context, &column);
8437 if (subplan)
8439 appendStringInfo(context->buf, "(%s%s).col%d",
8440 subplan->useHashTable ? "hashed " : "",
8441 subplan->plan_name, column + 1);
8443 return;
8447 * If it's an external parameter, see if the outermost namespace provides
8448 * function argument names.
8450 if (param->paramkind == PARAM_EXTERN && context->namespaces != NIL)
8452 dpns = llast(context->namespaces);
8453 if (dpns->argnames &&
8454 param->paramid > 0 &&
8455 param->paramid <= dpns->numargs)
8457 char *argname = dpns->argnames[param->paramid - 1];
8459 if (argname)
8461 bool should_qualify = false;
8462 ListCell *lc;
8465 * Qualify the parameter name if there are any other deparse
8466 * namespaces with range tables. This avoids qualifying in
8467 * trivial cases like "RETURN a + b", but makes it safe in all
8468 * other cases.
8470 foreach(lc, context->namespaces)
8472 deparse_namespace *depns = lfirst(lc);
8474 if (depns->rtable_names != NIL)
8476 should_qualify = true;
8477 break;
8480 if (should_qualify)
8482 appendStringInfoString(context->buf, quote_identifier(dpns->funcname));
8483 appendStringInfoChar(context->buf, '.');
8486 appendStringInfoString(context->buf, quote_identifier(argname));
8487 return;
8493 * Not PARAM_EXEC, or couldn't find referent: just print $N.
8495 * It's a bug if we get here for anything except PARAM_EXTERN Params, but
8496 * in production builds printing $N seems more useful than failing.
8498 Assert(param->paramkind == PARAM_EXTERN);
8500 appendStringInfo(context->buf, "$%d", param->paramid);
8504 * get_simple_binary_op_name
8506 * helper function for isSimpleNode
8507 * will return single char binary operator name, or NULL if it's not
8509 static const char *
8510 get_simple_binary_op_name(OpExpr *expr)
8512 List *args = expr->args;
8514 if (list_length(args) == 2)
8516 /* binary operator */
8517 Node *arg1 = (Node *) linitial(args);
8518 Node *arg2 = (Node *) lsecond(args);
8519 const char *op;
8521 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
8522 if (strlen(op) == 1)
8523 return op;
8525 return NULL;
8530 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
8532 * true : simple in the context of parent node's type
8533 * false : not simple
8535 static bool
8536 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
8538 if (!node)
8539 return false;
8541 switch (nodeTag(node))
8543 case T_Var:
8544 case T_Const:
8545 case T_Param:
8546 case T_CoerceToDomainValue:
8547 case T_SetToDefault:
8548 case T_CurrentOfExpr:
8549 /* single words: always simple */
8550 return true;
8552 case T_SubscriptingRef:
8553 case T_ArrayExpr:
8554 case T_RowExpr:
8555 case T_CoalesceExpr:
8556 case T_MinMaxExpr:
8557 case T_SQLValueFunction:
8558 case T_XmlExpr:
8559 case T_NextValueExpr:
8560 case T_NullIfExpr:
8561 case T_Aggref:
8562 case T_GroupingFunc:
8563 case T_WindowFunc:
8564 case T_MergeSupportFunc:
8565 case T_FuncExpr:
8566 case T_JsonConstructorExpr:
8567 case T_JsonExpr:
8568 /* function-like: name(..) or name[..] */
8569 return true;
8571 /* CASE keywords act as parentheses */
8572 case T_CaseExpr:
8573 return true;
8575 case T_FieldSelect:
8578 * appears simple since . has top precedence, unless parent is
8579 * T_FieldSelect itself!
8581 return !IsA(parentNode, FieldSelect);
8583 case T_FieldStore:
8586 * treat like FieldSelect (probably doesn't matter)
8588 return !IsA(parentNode, FieldStore);
8590 case T_CoerceToDomain:
8591 /* maybe simple, check args */
8592 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
8593 node, prettyFlags);
8594 case T_RelabelType:
8595 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
8596 node, prettyFlags);
8597 case T_CoerceViaIO:
8598 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
8599 node, prettyFlags);
8600 case T_ArrayCoerceExpr:
8601 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
8602 node, prettyFlags);
8603 case T_ConvertRowtypeExpr:
8604 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
8605 node, prettyFlags);
8607 case T_OpExpr:
8609 /* depends on parent node type; needs further checking */
8610 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
8612 const char *op;
8613 const char *parentOp;
8614 bool is_lopriop;
8615 bool is_hipriop;
8616 bool is_lopriparent;
8617 bool is_hipriparent;
8619 op = get_simple_binary_op_name((OpExpr *) node);
8620 if (!op)
8621 return false;
8623 /* We know only the basic operators + - and * / % */
8624 is_lopriop = (strchr("+-", *op) != NULL);
8625 is_hipriop = (strchr("*/%", *op) != NULL);
8626 if (!(is_lopriop || is_hipriop))
8627 return false;
8629 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
8630 if (!parentOp)
8631 return false;
8633 is_lopriparent = (strchr("+-", *parentOp) != NULL);
8634 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
8635 if (!(is_lopriparent || is_hipriparent))
8636 return false;
8638 if (is_hipriop && is_lopriparent)
8639 return true; /* op binds tighter than parent */
8641 if (is_lopriop && is_hipriparent)
8642 return false;
8645 * Operators are same priority --- can skip parens only if
8646 * we have (a - b) - c, not a - (b - c).
8648 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
8649 return true;
8651 return false;
8653 /* else do the same stuff as for T_SubLink et al. */
8655 /* FALLTHROUGH */
8657 case T_SubLink:
8658 case T_NullTest:
8659 case T_BooleanTest:
8660 case T_DistinctExpr:
8661 case T_JsonIsPredicate:
8662 switch (nodeTag(parentNode))
8664 case T_FuncExpr:
8666 /* special handling for casts and COERCE_SQL_SYNTAX */
8667 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8669 if (type == COERCE_EXPLICIT_CAST ||
8670 type == COERCE_IMPLICIT_CAST ||
8671 type == COERCE_SQL_SYNTAX)
8672 return false;
8673 return true; /* own parentheses */
8675 case T_BoolExpr: /* lower precedence */
8676 case T_SubscriptingRef: /* other separators */
8677 case T_ArrayExpr: /* other separators */
8678 case T_RowExpr: /* other separators */
8679 case T_CoalesceExpr: /* own parentheses */
8680 case T_MinMaxExpr: /* own parentheses */
8681 case T_XmlExpr: /* own parentheses */
8682 case T_NullIfExpr: /* other separators */
8683 case T_Aggref: /* own parentheses */
8684 case T_GroupingFunc: /* own parentheses */
8685 case T_WindowFunc: /* own parentheses */
8686 case T_CaseExpr: /* other separators */
8687 return true;
8688 default:
8689 return false;
8692 case T_BoolExpr:
8693 switch (nodeTag(parentNode))
8695 case T_BoolExpr:
8696 if (prettyFlags & PRETTYFLAG_PAREN)
8698 BoolExprType type;
8699 BoolExprType parentType;
8701 type = ((BoolExpr *) node)->boolop;
8702 parentType = ((BoolExpr *) parentNode)->boolop;
8703 switch (type)
8705 case NOT_EXPR:
8706 case AND_EXPR:
8707 if (parentType == AND_EXPR || parentType == OR_EXPR)
8708 return true;
8709 break;
8710 case OR_EXPR:
8711 if (parentType == OR_EXPR)
8712 return true;
8713 break;
8716 return false;
8717 case T_FuncExpr:
8719 /* special handling for casts and COERCE_SQL_SYNTAX */
8720 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8722 if (type == COERCE_EXPLICIT_CAST ||
8723 type == COERCE_IMPLICIT_CAST ||
8724 type == COERCE_SQL_SYNTAX)
8725 return false;
8726 return true; /* own parentheses */
8728 case T_SubscriptingRef: /* other separators */
8729 case T_ArrayExpr: /* other separators */
8730 case T_RowExpr: /* other separators */
8731 case T_CoalesceExpr: /* own parentheses */
8732 case T_MinMaxExpr: /* own parentheses */
8733 case T_XmlExpr: /* own parentheses */
8734 case T_NullIfExpr: /* other separators */
8735 case T_Aggref: /* own parentheses */
8736 case T_GroupingFunc: /* own parentheses */
8737 case T_WindowFunc: /* own parentheses */
8738 case T_CaseExpr: /* other separators */
8739 case T_JsonExpr: /* own parentheses */
8740 return true;
8741 default:
8742 return false;
8745 case T_JsonValueExpr:
8746 /* maybe simple, check args */
8747 return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
8748 node, prettyFlags);
8750 default:
8751 break;
8753 /* those we don't know: in dubio complexo */
8754 return false;
8759 * appendContextKeyword - append a keyword to buffer
8761 * If prettyPrint is enabled, perform a line break, and adjust indentation.
8762 * Otherwise, just append the keyword.
8764 static void
8765 appendContextKeyword(deparse_context *context, const char *str,
8766 int indentBefore, int indentAfter, int indentPlus)
8768 StringInfo buf = context->buf;
8770 if (PRETTY_INDENT(context))
8772 int indentAmount;
8774 context->indentLevel += indentBefore;
8776 /* remove any trailing spaces currently in the buffer ... */
8777 removeStringInfoSpaces(buf);
8778 /* ... then add a newline and some spaces */
8779 appendStringInfoChar(buf, '\n');
8781 if (context->indentLevel < PRETTYINDENT_LIMIT)
8782 indentAmount = Max(context->indentLevel, 0) + indentPlus;
8783 else
8786 * If we're indented more than PRETTYINDENT_LIMIT characters, try
8787 * to conserve horizontal space by reducing the per-level
8788 * indentation. For best results the scale factor here should
8789 * divide all the indent amounts that get added to indentLevel
8790 * (PRETTYINDENT_STD, etc). It's important that the indentation
8791 * not grow unboundedly, else deeply-nested trees use O(N^2)
8792 * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
8794 indentAmount = PRETTYINDENT_LIMIT +
8795 (context->indentLevel - PRETTYINDENT_LIMIT) /
8796 (PRETTYINDENT_STD / 2);
8797 indentAmount %= PRETTYINDENT_LIMIT;
8798 /* scale/wrap logic affects indentLevel, but not indentPlus */
8799 indentAmount += indentPlus;
8801 appendStringInfoSpaces(buf, indentAmount);
8803 appendStringInfoString(buf, str);
8805 context->indentLevel += indentAfter;
8806 if (context->indentLevel < 0)
8807 context->indentLevel = 0;
8809 else
8810 appendStringInfoString(buf, str);
8814 * removeStringInfoSpaces - delete trailing spaces from a buffer.
8816 * Possibly this should move to stringinfo.c at some point.
8818 static void
8819 removeStringInfoSpaces(StringInfo str)
8821 while (str->len > 0 && str->data[str->len - 1] == ' ')
8822 str->data[--(str->len)] = '\0';
8827 * get_rule_expr_paren - deparse expr using get_rule_expr,
8828 * embracing the string with parentheses if necessary for prettyPrint.
8830 * Never embrace if prettyFlags=0, because it's done in the calling node.
8832 * Any node that does *not* embrace its argument node by sql syntax (with
8833 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
8834 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
8835 * added.
8837 static void
8838 get_rule_expr_paren(Node *node, deparse_context *context,
8839 bool showimplicit, Node *parentNode)
8841 bool need_paren;
8843 need_paren = PRETTY_PAREN(context) &&
8844 !isSimpleNode(node, parentNode, context->prettyFlags);
8846 if (need_paren)
8847 appendStringInfoChar(context->buf, '(');
8849 get_rule_expr(node, context, showimplicit);
8851 if (need_paren)
8852 appendStringInfoChar(context->buf, ')');
8855 static void
8856 get_json_behavior(JsonBehavior *behavior, deparse_context *context,
8857 const char *on)
8860 * The order of array elements must correspond to the order of
8861 * JsonBehaviorType members.
8863 const char *behavior_names[] =
8865 " NULL",
8866 " ERROR",
8867 " EMPTY",
8868 " TRUE",
8869 " FALSE",
8870 " UNKNOWN",
8871 " EMPTY ARRAY",
8872 " EMPTY OBJECT",
8873 " DEFAULT "
8876 if ((int) behavior->btype < 0 || behavior->btype >= lengthof(behavior_names))
8877 elog(ERROR, "invalid json behavior type: %d", behavior->btype);
8879 appendStringInfoString(context->buf, behavior_names[behavior->btype]);
8881 if (behavior->btype == JSON_BEHAVIOR_DEFAULT)
8882 get_rule_expr(behavior->expr, context, false);
8884 appendStringInfo(context->buf, " ON %s", on);
8888 * get_json_expr_options
8890 * Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS and
8891 * JSON_TABLE columns.
8893 static void
8894 get_json_expr_options(JsonExpr *jsexpr, deparse_context *context,
8895 JsonBehaviorType default_behavior)
8897 if (jsexpr->op == JSON_QUERY_OP)
8899 if (jsexpr->wrapper == JSW_CONDITIONAL)
8900 appendStringInfoString(context->buf, " WITH CONDITIONAL WRAPPER");
8901 else if (jsexpr->wrapper == JSW_UNCONDITIONAL)
8902 appendStringInfoString(context->buf, " WITH UNCONDITIONAL WRAPPER");
8903 /* The default */
8904 else if (jsexpr->wrapper == JSW_NONE || jsexpr->wrapper == JSW_UNSPEC)
8905 appendStringInfoString(context->buf, " WITHOUT WRAPPER");
8907 if (jsexpr->omit_quotes)
8908 appendStringInfoString(context->buf, " OMIT QUOTES");
8909 /* The default */
8910 else
8911 appendStringInfoString(context->buf, " KEEP QUOTES");
8914 if (jsexpr->on_empty && jsexpr->on_empty->btype != default_behavior)
8915 get_json_behavior(jsexpr->on_empty, context, "EMPTY");
8917 if (jsexpr->on_error && jsexpr->on_error->btype != default_behavior)
8918 get_json_behavior(jsexpr->on_error, context, "ERROR");
8921 /* ----------
8922 * get_rule_expr - Parse back an expression
8924 * Note: showimplicit determines whether we display any implicit cast that
8925 * is present at the top of the expression tree. It is a passed argument,
8926 * not a field of the context struct, because we change the value as we
8927 * recurse down into the expression. In general we suppress implicit casts
8928 * when the result type is known with certainty (eg, the arguments of an
8929 * OR must be boolean). We display implicit casts for arguments of functions
8930 * and operators, since this is needed to be certain that the same function
8931 * or operator will be chosen when the expression is re-parsed.
8932 * ----------
8934 static void
8935 get_rule_expr(Node *node, deparse_context *context,
8936 bool showimplicit)
8938 StringInfo buf = context->buf;
8940 if (node == NULL)
8941 return;
8943 /* Guard against excessively long or deeply-nested queries */
8944 CHECK_FOR_INTERRUPTS();
8945 check_stack_depth();
8948 * Each level of get_rule_expr must emit an indivisible term
8949 * (parenthesized if necessary) to ensure result is reparsed into the same
8950 * expression tree. The only exception is that when the input is a List,
8951 * we emit the component items comma-separated with no surrounding
8952 * decoration; this is convenient for most callers.
8954 switch (nodeTag(node))
8956 case T_Var:
8957 (void) get_variable((Var *) node, 0, false, context);
8958 break;
8960 case T_Const:
8961 get_const_expr((Const *) node, context, 0);
8962 break;
8964 case T_Param:
8965 get_parameter((Param *) node, context);
8966 break;
8968 case T_Aggref:
8969 get_agg_expr((Aggref *) node, context, (Aggref *) node);
8970 break;
8972 case T_GroupingFunc:
8974 GroupingFunc *gexpr = (GroupingFunc *) node;
8976 appendStringInfoString(buf, "GROUPING(");
8977 get_rule_expr((Node *) gexpr->args, context, true);
8978 appendStringInfoChar(buf, ')');
8980 break;
8982 case T_WindowFunc:
8983 get_windowfunc_expr((WindowFunc *) node, context);
8984 break;
8986 case T_MergeSupportFunc:
8987 appendStringInfoString(buf, "MERGE_ACTION()");
8988 break;
8990 case T_SubscriptingRef:
8992 SubscriptingRef *sbsref = (SubscriptingRef *) node;
8993 bool need_parens;
8996 * If the argument is a CaseTestExpr, we must be inside a
8997 * FieldStore, ie, we are assigning to an element of an array
8998 * within a composite column. Since we already punted on
8999 * displaying the FieldStore's target information, just punt
9000 * here too, and display only the assignment source
9001 * expression.
9003 if (IsA(sbsref->refexpr, CaseTestExpr))
9005 Assert(sbsref->refassgnexpr);
9006 get_rule_expr((Node *) sbsref->refassgnexpr,
9007 context, showimplicit);
9008 break;
9012 * Parenthesize the argument unless it's a simple Var or a
9013 * FieldSelect. (In particular, if it's another
9014 * SubscriptingRef, we *must* parenthesize to avoid
9015 * confusion.)
9017 need_parens = !IsA(sbsref->refexpr, Var) &&
9018 !IsA(sbsref->refexpr, FieldSelect);
9019 if (need_parens)
9020 appendStringInfoChar(buf, '(');
9021 get_rule_expr((Node *) sbsref->refexpr, context, showimplicit);
9022 if (need_parens)
9023 appendStringInfoChar(buf, ')');
9026 * If there's a refassgnexpr, we want to print the node in the
9027 * format "container[subscripts] := refassgnexpr". This is
9028 * not legal SQL, so decompilation of INSERT or UPDATE
9029 * statements should always use processIndirection as part of
9030 * the statement-level syntax. We should only see this when
9031 * EXPLAIN tries to print the targetlist of a plan resulting
9032 * from such a statement.
9034 if (sbsref->refassgnexpr)
9036 Node *refassgnexpr;
9039 * Use processIndirection to print this node's subscripts
9040 * as well as any additional field selections or
9041 * subscripting in immediate descendants. It returns the
9042 * RHS expr that is actually being "assigned".
9044 refassgnexpr = processIndirection(node, context);
9045 appendStringInfoString(buf, " := ");
9046 get_rule_expr(refassgnexpr, context, showimplicit);
9048 else
9050 /* Just an ordinary container fetch, so print subscripts */
9051 printSubscripts(sbsref, context);
9054 break;
9056 case T_FuncExpr:
9057 get_func_expr((FuncExpr *) node, context, showimplicit);
9058 break;
9060 case T_NamedArgExpr:
9062 NamedArgExpr *na = (NamedArgExpr *) node;
9064 appendStringInfo(buf, "%s => ", quote_identifier(na->name));
9065 get_rule_expr((Node *) na->arg, context, showimplicit);
9067 break;
9069 case T_OpExpr:
9070 get_oper_expr((OpExpr *) node, context);
9071 break;
9073 case T_DistinctExpr:
9075 DistinctExpr *expr = (DistinctExpr *) node;
9076 List *args = expr->args;
9077 Node *arg1 = (Node *) linitial(args);
9078 Node *arg2 = (Node *) lsecond(args);
9080 if (!PRETTY_PAREN(context))
9081 appendStringInfoChar(buf, '(');
9082 get_rule_expr_paren(arg1, context, true, node);
9083 appendStringInfoString(buf, " IS DISTINCT FROM ");
9084 get_rule_expr_paren(arg2, context, true, node);
9085 if (!PRETTY_PAREN(context))
9086 appendStringInfoChar(buf, ')');
9088 break;
9090 case T_NullIfExpr:
9092 NullIfExpr *nullifexpr = (NullIfExpr *) node;
9094 appendStringInfoString(buf, "NULLIF(");
9095 get_rule_expr((Node *) nullifexpr->args, context, true);
9096 appendStringInfoChar(buf, ')');
9098 break;
9100 case T_ScalarArrayOpExpr:
9102 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
9103 List *args = expr->args;
9104 Node *arg1 = (Node *) linitial(args);
9105 Node *arg2 = (Node *) lsecond(args);
9107 if (!PRETTY_PAREN(context))
9108 appendStringInfoChar(buf, '(');
9109 get_rule_expr_paren(arg1, context, true, node);
9110 appendStringInfo(buf, " %s %s (",
9111 generate_operator_name(expr->opno,
9112 exprType(arg1),
9113 get_base_element_type(exprType(arg2))),
9114 expr->useOr ? "ANY" : "ALL");
9115 get_rule_expr_paren(arg2, context, true, node);
9118 * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
9119 * a bare sub-SELECT. Since we're here, the sub-SELECT must
9120 * be meant as a scalar sub-SELECT yielding an array value to
9121 * be used in ScalarArrayOpExpr; but the grammar will
9122 * preferentially interpret such a construct as an ANY/ALL
9123 * SubLink. To prevent misparsing the output that way, insert
9124 * a dummy coercion (which will be stripped by parse analysis,
9125 * so no inefficiency is added in dump and reload). This is
9126 * indeed most likely what the user wrote to get the construct
9127 * accepted in the first place.
9129 if (IsA(arg2, SubLink) &&
9130 ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
9131 appendStringInfo(buf, "::%s",
9132 format_type_with_typemod(exprType(arg2),
9133 exprTypmod(arg2)));
9134 appendStringInfoChar(buf, ')');
9135 if (!PRETTY_PAREN(context))
9136 appendStringInfoChar(buf, ')');
9138 break;
9140 case T_BoolExpr:
9142 BoolExpr *expr = (BoolExpr *) node;
9143 Node *first_arg = linitial(expr->args);
9144 ListCell *arg;
9146 switch (expr->boolop)
9148 case AND_EXPR:
9149 if (!PRETTY_PAREN(context))
9150 appendStringInfoChar(buf, '(');
9151 get_rule_expr_paren(first_arg, context,
9152 false, node);
9153 for_each_from(arg, expr->args, 1)
9155 appendStringInfoString(buf, " AND ");
9156 get_rule_expr_paren((Node *) lfirst(arg), context,
9157 false, node);
9159 if (!PRETTY_PAREN(context))
9160 appendStringInfoChar(buf, ')');
9161 break;
9163 case OR_EXPR:
9164 if (!PRETTY_PAREN(context))
9165 appendStringInfoChar(buf, '(');
9166 get_rule_expr_paren(first_arg, context,
9167 false, node);
9168 for_each_from(arg, expr->args, 1)
9170 appendStringInfoString(buf, " OR ");
9171 get_rule_expr_paren((Node *) lfirst(arg), context,
9172 false, node);
9174 if (!PRETTY_PAREN(context))
9175 appendStringInfoChar(buf, ')');
9176 break;
9178 case NOT_EXPR:
9179 if (!PRETTY_PAREN(context))
9180 appendStringInfoChar(buf, '(');
9181 appendStringInfoString(buf, "NOT ");
9182 get_rule_expr_paren(first_arg, context,
9183 false, node);
9184 if (!PRETTY_PAREN(context))
9185 appendStringInfoChar(buf, ')');
9186 break;
9188 default:
9189 elog(ERROR, "unrecognized boolop: %d",
9190 (int) expr->boolop);
9193 break;
9195 case T_SubLink:
9196 get_sublink_expr((SubLink *) node, context);
9197 break;
9199 case T_SubPlan:
9201 SubPlan *subplan = (SubPlan *) node;
9204 * We cannot see an already-planned subplan in rule deparsing,
9205 * only while EXPLAINing a query plan. We don't try to
9206 * reconstruct the original SQL, just reference the subplan
9207 * that appears elsewhere in EXPLAIN's result. It does seem
9208 * useful to show the subLinkType and testexpr (if any), and
9209 * we also note whether the subplan will be hashed.
9211 switch (subplan->subLinkType)
9213 case EXISTS_SUBLINK:
9214 appendStringInfoString(buf, "EXISTS(");
9215 Assert(subplan->testexpr == NULL);
9216 break;
9217 case ALL_SUBLINK:
9218 appendStringInfoString(buf, "(ALL ");
9219 Assert(subplan->testexpr != NULL);
9220 break;
9221 case ANY_SUBLINK:
9222 appendStringInfoString(buf, "(ANY ");
9223 Assert(subplan->testexpr != NULL);
9224 break;
9225 case ROWCOMPARE_SUBLINK:
9226 /* Parenthesizing the testexpr seems sufficient */
9227 appendStringInfoChar(buf, '(');
9228 Assert(subplan->testexpr != NULL);
9229 break;
9230 case EXPR_SUBLINK:
9231 /* No need to decorate these subplan references */
9232 appendStringInfoChar(buf, '(');
9233 Assert(subplan->testexpr == NULL);
9234 break;
9235 case MULTIEXPR_SUBLINK:
9236 /* MULTIEXPR isn't executed in the normal way */
9237 appendStringInfoString(buf, "(rescan ");
9238 Assert(subplan->testexpr == NULL);
9239 break;
9240 case ARRAY_SUBLINK:
9241 appendStringInfoString(buf, "ARRAY(");
9242 Assert(subplan->testexpr == NULL);
9243 break;
9244 case CTE_SUBLINK:
9245 /* This case is unreachable within expressions */
9246 appendStringInfoString(buf, "CTE(");
9247 Assert(subplan->testexpr == NULL);
9248 break;
9251 if (subplan->testexpr != NULL)
9253 deparse_namespace *dpns;
9256 * Push SubPlan into ancestors list while deparsing
9257 * testexpr, so that we can handle PARAM_EXEC references
9258 * to the SubPlan's paramIds. (This makes it look like
9259 * the SubPlan is an "ancestor" of the current plan node,
9260 * which is a little weird, but it does no harm.) In this
9261 * path, we don't need to mention the SubPlan explicitly,
9262 * because the referencing Params will show its existence.
9264 dpns = (deparse_namespace *) linitial(context->namespaces);
9265 dpns->ancestors = lcons(subplan, dpns->ancestors);
9267 get_rule_expr(subplan->testexpr, context, showimplicit);
9268 appendStringInfoChar(buf, ')');
9270 dpns->ancestors = list_delete_first(dpns->ancestors);
9272 else
9274 /* No referencing Params, so show the SubPlan's name */
9275 if (subplan->useHashTable)
9276 appendStringInfo(buf, "hashed %s)", subplan->plan_name);
9277 else
9278 appendStringInfo(buf, "%s)", subplan->plan_name);
9281 break;
9283 case T_AlternativeSubPlan:
9285 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
9286 ListCell *lc;
9289 * This case cannot be reached in normal usage, since no
9290 * AlternativeSubPlan can appear either in parsetrees or
9291 * finished plan trees. We keep it just in case somebody
9292 * wants to use this code to print planner data structures.
9294 appendStringInfoString(buf, "(alternatives: ");
9295 foreach(lc, asplan->subplans)
9297 SubPlan *splan = lfirst_node(SubPlan, lc);
9299 if (splan->useHashTable)
9300 appendStringInfo(buf, "hashed %s", splan->plan_name);
9301 else
9302 appendStringInfoString(buf, splan->plan_name);
9303 if (lnext(asplan->subplans, lc))
9304 appendStringInfoString(buf, " or ");
9306 appendStringInfoChar(buf, ')');
9308 break;
9310 case T_FieldSelect:
9312 FieldSelect *fselect = (FieldSelect *) node;
9313 Node *arg = (Node *) fselect->arg;
9314 int fno = fselect->fieldnum;
9315 const char *fieldname;
9316 bool need_parens;
9319 * Parenthesize the argument unless it's an SubscriptingRef or
9320 * another FieldSelect. Note in particular that it would be
9321 * WRONG to not parenthesize a Var argument; simplicity is not
9322 * the issue here, having the right number of names is.
9324 need_parens = !IsA(arg, SubscriptingRef) &&
9325 !IsA(arg, FieldSelect);
9326 if (need_parens)
9327 appendStringInfoChar(buf, '(');
9328 get_rule_expr(arg, context, true);
9329 if (need_parens)
9330 appendStringInfoChar(buf, ')');
9333 * Get and print the field name.
9335 fieldname = get_name_for_var_field((Var *) arg, fno,
9336 0, context);
9337 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
9339 break;
9341 case T_FieldStore:
9343 FieldStore *fstore = (FieldStore *) node;
9344 bool need_parens;
9347 * There is no good way to represent a FieldStore as real SQL,
9348 * so decompilation of INSERT or UPDATE statements should
9349 * always use processIndirection as part of the
9350 * statement-level syntax. We should only get here when
9351 * EXPLAIN tries to print the targetlist of a plan resulting
9352 * from such a statement. The plan case is even harder than
9353 * ordinary rules would be, because the planner tries to
9354 * collapse multiple assignments to the same field or subfield
9355 * into one FieldStore; so we can see a list of target fields
9356 * not just one, and the arguments could be FieldStores
9357 * themselves. We don't bother to try to print the target
9358 * field names; we just print the source arguments, with a
9359 * ROW() around them if there's more than one. This isn't
9360 * terribly complete, but it's probably good enough for
9361 * EXPLAIN's purposes; especially since anything more would be
9362 * either hopelessly confusing or an even poorer
9363 * representation of what the plan is actually doing.
9365 need_parens = (list_length(fstore->newvals) != 1);
9366 if (need_parens)
9367 appendStringInfoString(buf, "ROW(");
9368 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
9369 if (need_parens)
9370 appendStringInfoChar(buf, ')');
9372 break;
9374 case T_RelabelType:
9376 RelabelType *relabel = (RelabelType *) node;
9377 Node *arg = (Node *) relabel->arg;
9379 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
9380 !showimplicit)
9382 /* don't show the implicit cast */
9383 get_rule_expr_paren(arg, context, false, node);
9385 else
9387 get_coercion_expr(arg, context,
9388 relabel->resulttype,
9389 relabel->resulttypmod,
9390 node);
9393 break;
9395 case T_CoerceViaIO:
9397 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
9398 Node *arg = (Node *) iocoerce->arg;
9400 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
9401 !showimplicit)
9403 /* don't show the implicit cast */
9404 get_rule_expr_paren(arg, context, false, node);
9406 else
9408 get_coercion_expr(arg, context,
9409 iocoerce->resulttype,
9411 node);
9414 break;
9416 case T_ArrayCoerceExpr:
9418 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
9419 Node *arg = (Node *) acoerce->arg;
9421 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
9422 !showimplicit)
9424 /* don't show the implicit cast */
9425 get_rule_expr_paren(arg, context, false, node);
9427 else
9429 get_coercion_expr(arg, context,
9430 acoerce->resulttype,
9431 acoerce->resulttypmod,
9432 node);
9435 break;
9437 case T_ConvertRowtypeExpr:
9439 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
9440 Node *arg = (Node *) convert->arg;
9442 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
9443 !showimplicit)
9445 /* don't show the implicit cast */
9446 get_rule_expr_paren(arg, context, false, node);
9448 else
9450 get_coercion_expr(arg, context,
9451 convert->resulttype, -1,
9452 node);
9455 break;
9457 case T_CollateExpr:
9459 CollateExpr *collate = (CollateExpr *) node;
9460 Node *arg = (Node *) collate->arg;
9462 if (!PRETTY_PAREN(context))
9463 appendStringInfoChar(buf, '(');
9464 get_rule_expr_paren(arg, context, showimplicit, node);
9465 appendStringInfo(buf, " COLLATE %s",
9466 generate_collation_name(collate->collOid));
9467 if (!PRETTY_PAREN(context))
9468 appendStringInfoChar(buf, ')');
9470 break;
9472 case T_CaseExpr:
9474 CaseExpr *caseexpr = (CaseExpr *) node;
9475 ListCell *temp;
9477 appendContextKeyword(context, "CASE",
9478 0, PRETTYINDENT_VAR, 0);
9479 if (caseexpr->arg)
9481 appendStringInfoChar(buf, ' ');
9482 get_rule_expr((Node *) caseexpr->arg, context, true);
9484 foreach(temp, caseexpr->args)
9486 CaseWhen *when = (CaseWhen *) lfirst(temp);
9487 Node *w = (Node *) when->expr;
9489 if (caseexpr->arg)
9492 * The parser should have produced WHEN clauses of the
9493 * form "CaseTestExpr = RHS", possibly with an
9494 * implicit coercion inserted above the CaseTestExpr.
9495 * For accurate decompilation of rules it's essential
9496 * that we show just the RHS. However in an
9497 * expression that's been through the optimizer, the
9498 * WHEN clause could be almost anything (since the
9499 * equality operator could have been expanded into an
9500 * inline function). If we don't recognize the form
9501 * of the WHEN clause, just punt and display it as-is.
9503 if (IsA(w, OpExpr))
9505 List *args = ((OpExpr *) w)->args;
9507 if (list_length(args) == 2 &&
9508 IsA(strip_implicit_coercions(linitial(args)),
9509 CaseTestExpr))
9510 w = (Node *) lsecond(args);
9514 if (!PRETTY_INDENT(context))
9515 appendStringInfoChar(buf, ' ');
9516 appendContextKeyword(context, "WHEN ",
9517 0, 0, 0);
9518 get_rule_expr(w, context, false);
9519 appendStringInfoString(buf, " THEN ");
9520 get_rule_expr((Node *) when->result, context, true);
9522 if (!PRETTY_INDENT(context))
9523 appendStringInfoChar(buf, ' ');
9524 appendContextKeyword(context, "ELSE ",
9525 0, 0, 0);
9526 get_rule_expr((Node *) caseexpr->defresult, context, true);
9527 if (!PRETTY_INDENT(context))
9528 appendStringInfoChar(buf, ' ');
9529 appendContextKeyword(context, "END",
9530 -PRETTYINDENT_VAR, 0, 0);
9532 break;
9534 case T_CaseTestExpr:
9537 * Normally we should never get here, since for expressions
9538 * that can contain this node type we attempt to avoid
9539 * recursing to it. But in an optimized expression we might
9540 * be unable to avoid that (see comments for CaseExpr). If we
9541 * do see one, print it as CASE_TEST_EXPR.
9543 appendStringInfoString(buf, "CASE_TEST_EXPR");
9545 break;
9547 case T_ArrayExpr:
9549 ArrayExpr *arrayexpr = (ArrayExpr *) node;
9551 appendStringInfoString(buf, "ARRAY[");
9552 get_rule_expr((Node *) arrayexpr->elements, context, true);
9553 appendStringInfoChar(buf, ']');
9556 * If the array isn't empty, we assume its elements are
9557 * coerced to the desired type. If it's empty, though, we
9558 * need an explicit coercion to the array type.
9560 if (arrayexpr->elements == NIL)
9561 appendStringInfo(buf, "::%s",
9562 format_type_with_typemod(arrayexpr->array_typeid, -1));
9564 break;
9566 case T_RowExpr:
9568 RowExpr *rowexpr = (RowExpr *) node;
9569 TupleDesc tupdesc = NULL;
9570 ListCell *arg;
9571 int i;
9572 char *sep;
9575 * If it's a named type and not RECORD, we may have to skip
9576 * dropped columns and/or claim there are NULLs for added
9577 * columns.
9579 if (rowexpr->row_typeid != RECORDOID)
9581 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
9582 Assert(list_length(rowexpr->args) <= tupdesc->natts);
9586 * SQL99 allows "ROW" to be omitted when there is more than
9587 * one column, but for simplicity we always print it.
9589 appendStringInfoString(buf, "ROW(");
9590 sep = "";
9591 i = 0;
9592 foreach(arg, rowexpr->args)
9594 Node *e = (Node *) lfirst(arg);
9596 if (tupdesc == NULL ||
9597 !TupleDescAttr(tupdesc, i)->attisdropped)
9599 appendStringInfoString(buf, sep);
9600 /* Whole-row Vars need special treatment here */
9601 get_rule_expr_toplevel(e, context, true);
9602 sep = ", ";
9604 i++;
9606 if (tupdesc != NULL)
9608 while (i < tupdesc->natts)
9610 if (!TupleDescAttr(tupdesc, i)->attisdropped)
9612 appendStringInfoString(buf, sep);
9613 appendStringInfoString(buf, "NULL");
9614 sep = ", ";
9616 i++;
9619 ReleaseTupleDesc(tupdesc);
9621 appendStringInfoChar(buf, ')');
9622 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
9623 appendStringInfo(buf, "::%s",
9624 format_type_with_typemod(rowexpr->row_typeid, -1));
9626 break;
9628 case T_RowCompareExpr:
9630 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
9633 * SQL99 allows "ROW" to be omitted when there is more than
9634 * one column, but for simplicity we always print it. Within
9635 * a ROW expression, whole-row Vars need special treatment, so
9636 * use get_rule_list_toplevel.
9638 appendStringInfoString(buf, "(ROW(");
9639 get_rule_list_toplevel(rcexpr->largs, context, true);
9642 * We assume that the name of the first-column operator will
9643 * do for all the rest too. This is definitely open to
9644 * failure, eg if some but not all operators were renamed
9645 * since the construct was parsed, but there seems no way to
9646 * be perfect.
9648 appendStringInfo(buf, ") %s ROW(",
9649 generate_operator_name(linitial_oid(rcexpr->opnos),
9650 exprType(linitial(rcexpr->largs)),
9651 exprType(linitial(rcexpr->rargs))));
9652 get_rule_list_toplevel(rcexpr->rargs, context, true);
9653 appendStringInfoString(buf, "))");
9655 break;
9657 case T_CoalesceExpr:
9659 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
9661 appendStringInfoString(buf, "COALESCE(");
9662 get_rule_expr((Node *) coalesceexpr->args, context, true);
9663 appendStringInfoChar(buf, ')');
9665 break;
9667 case T_MinMaxExpr:
9669 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
9671 switch (minmaxexpr->op)
9673 case IS_GREATEST:
9674 appendStringInfoString(buf, "GREATEST(");
9675 break;
9676 case IS_LEAST:
9677 appendStringInfoString(buf, "LEAST(");
9678 break;
9680 get_rule_expr((Node *) minmaxexpr->args, context, true);
9681 appendStringInfoChar(buf, ')');
9683 break;
9685 case T_SQLValueFunction:
9687 SQLValueFunction *svf = (SQLValueFunction *) node;
9690 * Note: this code knows that typmod for time, timestamp, and
9691 * timestamptz just prints as integer.
9693 switch (svf->op)
9695 case SVFOP_CURRENT_DATE:
9696 appendStringInfoString(buf, "CURRENT_DATE");
9697 break;
9698 case SVFOP_CURRENT_TIME:
9699 appendStringInfoString(buf, "CURRENT_TIME");
9700 break;
9701 case SVFOP_CURRENT_TIME_N:
9702 appendStringInfo(buf, "CURRENT_TIME(%d)", svf->typmod);
9703 break;
9704 case SVFOP_CURRENT_TIMESTAMP:
9705 appendStringInfoString(buf, "CURRENT_TIMESTAMP");
9706 break;
9707 case SVFOP_CURRENT_TIMESTAMP_N:
9708 appendStringInfo(buf, "CURRENT_TIMESTAMP(%d)",
9709 svf->typmod);
9710 break;
9711 case SVFOP_LOCALTIME:
9712 appendStringInfoString(buf, "LOCALTIME");
9713 break;
9714 case SVFOP_LOCALTIME_N:
9715 appendStringInfo(buf, "LOCALTIME(%d)", svf->typmod);
9716 break;
9717 case SVFOP_LOCALTIMESTAMP:
9718 appendStringInfoString(buf, "LOCALTIMESTAMP");
9719 break;
9720 case SVFOP_LOCALTIMESTAMP_N:
9721 appendStringInfo(buf, "LOCALTIMESTAMP(%d)",
9722 svf->typmod);
9723 break;
9724 case SVFOP_CURRENT_ROLE:
9725 appendStringInfoString(buf, "CURRENT_ROLE");
9726 break;
9727 case SVFOP_CURRENT_USER:
9728 appendStringInfoString(buf, "CURRENT_USER");
9729 break;
9730 case SVFOP_USER:
9731 appendStringInfoString(buf, "USER");
9732 break;
9733 case SVFOP_SESSION_USER:
9734 appendStringInfoString(buf, "SESSION_USER");
9735 break;
9736 case SVFOP_CURRENT_CATALOG:
9737 appendStringInfoString(buf, "CURRENT_CATALOG");
9738 break;
9739 case SVFOP_CURRENT_SCHEMA:
9740 appendStringInfoString(buf, "CURRENT_SCHEMA");
9741 break;
9744 break;
9746 case T_XmlExpr:
9748 XmlExpr *xexpr = (XmlExpr *) node;
9749 bool needcomma = false;
9750 ListCell *arg;
9751 ListCell *narg;
9752 Const *con;
9754 switch (xexpr->op)
9756 case IS_XMLCONCAT:
9757 appendStringInfoString(buf, "XMLCONCAT(");
9758 break;
9759 case IS_XMLELEMENT:
9760 appendStringInfoString(buf, "XMLELEMENT(");
9761 break;
9762 case IS_XMLFOREST:
9763 appendStringInfoString(buf, "XMLFOREST(");
9764 break;
9765 case IS_XMLPARSE:
9766 appendStringInfoString(buf, "XMLPARSE(");
9767 break;
9768 case IS_XMLPI:
9769 appendStringInfoString(buf, "XMLPI(");
9770 break;
9771 case IS_XMLROOT:
9772 appendStringInfoString(buf, "XMLROOT(");
9773 break;
9774 case IS_XMLSERIALIZE:
9775 appendStringInfoString(buf, "XMLSERIALIZE(");
9776 break;
9777 case IS_DOCUMENT:
9778 break;
9780 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
9782 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
9783 appendStringInfoString(buf, "DOCUMENT ");
9784 else
9785 appendStringInfoString(buf, "CONTENT ");
9787 if (xexpr->name)
9789 appendStringInfo(buf, "NAME %s",
9790 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
9791 needcomma = true;
9793 if (xexpr->named_args)
9795 if (xexpr->op != IS_XMLFOREST)
9797 if (needcomma)
9798 appendStringInfoString(buf, ", ");
9799 appendStringInfoString(buf, "XMLATTRIBUTES(");
9800 needcomma = false;
9802 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
9804 Node *e = (Node *) lfirst(arg);
9805 char *argname = strVal(lfirst(narg));
9807 if (needcomma)
9808 appendStringInfoString(buf, ", ");
9809 get_rule_expr((Node *) e, context, true);
9810 appendStringInfo(buf, " AS %s",
9811 quote_identifier(map_xml_name_to_sql_identifier(argname)));
9812 needcomma = true;
9814 if (xexpr->op != IS_XMLFOREST)
9815 appendStringInfoChar(buf, ')');
9817 if (xexpr->args)
9819 if (needcomma)
9820 appendStringInfoString(buf, ", ");
9821 switch (xexpr->op)
9823 case IS_XMLCONCAT:
9824 case IS_XMLELEMENT:
9825 case IS_XMLFOREST:
9826 case IS_XMLPI:
9827 case IS_XMLSERIALIZE:
9828 /* no extra decoration needed */
9829 get_rule_expr((Node *) xexpr->args, context, true);
9830 break;
9831 case IS_XMLPARSE:
9832 Assert(list_length(xexpr->args) == 2);
9834 get_rule_expr((Node *) linitial(xexpr->args),
9835 context, true);
9837 con = lsecond_node(Const, xexpr->args);
9838 Assert(!con->constisnull);
9839 if (DatumGetBool(con->constvalue))
9840 appendStringInfoString(buf,
9841 " PRESERVE WHITESPACE");
9842 else
9843 appendStringInfoString(buf,
9844 " STRIP WHITESPACE");
9845 break;
9846 case IS_XMLROOT:
9847 Assert(list_length(xexpr->args) == 3);
9849 get_rule_expr((Node *) linitial(xexpr->args),
9850 context, true);
9852 appendStringInfoString(buf, ", VERSION ");
9853 con = (Const *) lsecond(xexpr->args);
9854 if (IsA(con, Const) &&
9855 con->constisnull)
9856 appendStringInfoString(buf, "NO VALUE");
9857 else
9858 get_rule_expr((Node *) con, context, false);
9860 con = lthird_node(Const, xexpr->args);
9861 if (con->constisnull)
9862 /* suppress STANDALONE NO VALUE */ ;
9863 else
9865 switch (DatumGetInt32(con->constvalue))
9867 case XML_STANDALONE_YES:
9868 appendStringInfoString(buf,
9869 ", STANDALONE YES");
9870 break;
9871 case XML_STANDALONE_NO:
9872 appendStringInfoString(buf,
9873 ", STANDALONE NO");
9874 break;
9875 case XML_STANDALONE_NO_VALUE:
9876 appendStringInfoString(buf,
9877 ", STANDALONE NO VALUE");
9878 break;
9879 default:
9880 break;
9883 break;
9884 case IS_DOCUMENT:
9885 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
9886 break;
9889 if (xexpr->op == IS_XMLSERIALIZE)
9890 appendStringInfo(buf, " AS %s",
9891 format_type_with_typemod(xexpr->type,
9892 xexpr->typmod));
9893 if (xexpr->op == IS_DOCUMENT)
9894 appendStringInfoString(buf, " IS DOCUMENT");
9895 else
9896 appendStringInfoChar(buf, ')');
9898 break;
9900 case T_NullTest:
9902 NullTest *ntest = (NullTest *) node;
9904 if (!PRETTY_PAREN(context))
9905 appendStringInfoChar(buf, '(');
9906 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
9909 * For scalar inputs, we prefer to print as IS [NOT] NULL,
9910 * which is shorter and traditional. If it's a rowtype input
9911 * but we're applying a scalar test, must print IS [NOT]
9912 * DISTINCT FROM NULL to be semantically correct.
9914 if (ntest->argisrow ||
9915 !type_is_rowtype(exprType((Node *) ntest->arg)))
9917 switch (ntest->nulltesttype)
9919 case IS_NULL:
9920 appendStringInfoString(buf, " IS NULL");
9921 break;
9922 case IS_NOT_NULL:
9923 appendStringInfoString(buf, " IS NOT NULL");
9924 break;
9925 default:
9926 elog(ERROR, "unrecognized nulltesttype: %d",
9927 (int) ntest->nulltesttype);
9930 else
9932 switch (ntest->nulltesttype)
9934 case IS_NULL:
9935 appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL");
9936 break;
9937 case IS_NOT_NULL:
9938 appendStringInfoString(buf, " IS DISTINCT FROM NULL");
9939 break;
9940 default:
9941 elog(ERROR, "unrecognized nulltesttype: %d",
9942 (int) ntest->nulltesttype);
9945 if (!PRETTY_PAREN(context))
9946 appendStringInfoChar(buf, ')');
9948 break;
9950 case T_BooleanTest:
9952 BooleanTest *btest = (BooleanTest *) node;
9954 if (!PRETTY_PAREN(context))
9955 appendStringInfoChar(buf, '(');
9956 get_rule_expr_paren((Node *) btest->arg, context, false, node);
9957 switch (btest->booltesttype)
9959 case IS_TRUE:
9960 appendStringInfoString(buf, " IS TRUE");
9961 break;
9962 case IS_NOT_TRUE:
9963 appendStringInfoString(buf, " IS NOT TRUE");
9964 break;
9965 case IS_FALSE:
9966 appendStringInfoString(buf, " IS FALSE");
9967 break;
9968 case IS_NOT_FALSE:
9969 appendStringInfoString(buf, " IS NOT FALSE");
9970 break;
9971 case IS_UNKNOWN:
9972 appendStringInfoString(buf, " IS UNKNOWN");
9973 break;
9974 case IS_NOT_UNKNOWN:
9975 appendStringInfoString(buf, " IS NOT UNKNOWN");
9976 break;
9977 default:
9978 elog(ERROR, "unrecognized booltesttype: %d",
9979 (int) btest->booltesttype);
9981 if (!PRETTY_PAREN(context))
9982 appendStringInfoChar(buf, ')');
9984 break;
9986 case T_CoerceToDomain:
9988 CoerceToDomain *ctest = (CoerceToDomain *) node;
9989 Node *arg = (Node *) ctest->arg;
9991 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
9992 !showimplicit)
9994 /* don't show the implicit cast */
9995 get_rule_expr(arg, context, false);
9997 else
9999 get_coercion_expr(arg, context,
10000 ctest->resulttype,
10001 ctest->resulttypmod,
10002 node);
10005 break;
10007 case T_CoerceToDomainValue:
10008 appendStringInfoString(buf, "VALUE");
10009 break;
10011 case T_SetToDefault:
10012 appendStringInfoString(buf, "DEFAULT");
10013 break;
10015 case T_CurrentOfExpr:
10017 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
10019 if (cexpr->cursor_name)
10020 appendStringInfo(buf, "CURRENT OF %s",
10021 quote_identifier(cexpr->cursor_name));
10022 else
10023 appendStringInfo(buf, "CURRENT OF $%d",
10024 cexpr->cursor_param);
10026 break;
10028 case T_NextValueExpr:
10030 NextValueExpr *nvexpr = (NextValueExpr *) node;
10033 * This isn't exactly nextval(), but that seems close enough
10034 * for EXPLAIN's purposes.
10036 appendStringInfoString(buf, "nextval(");
10037 simple_quote_literal(buf,
10038 generate_relation_name(nvexpr->seqid,
10039 NIL));
10040 appendStringInfoChar(buf, ')');
10042 break;
10044 case T_InferenceElem:
10046 InferenceElem *iexpr = (InferenceElem *) node;
10047 bool save_varprefix;
10048 bool need_parens;
10051 * InferenceElem can only refer to target relation, so a
10052 * prefix is not useful, and indeed would cause parse errors.
10054 save_varprefix = context->varprefix;
10055 context->varprefix = false;
10058 * Parenthesize the element unless it's a simple Var or a bare
10059 * function call. Follows pg_get_indexdef_worker().
10061 need_parens = !IsA(iexpr->expr, Var);
10062 if (IsA(iexpr->expr, FuncExpr) &&
10063 ((FuncExpr *) iexpr->expr)->funcformat ==
10064 COERCE_EXPLICIT_CALL)
10065 need_parens = false;
10067 if (need_parens)
10068 appendStringInfoChar(buf, '(');
10069 get_rule_expr((Node *) iexpr->expr,
10070 context, false);
10071 if (need_parens)
10072 appendStringInfoChar(buf, ')');
10074 context->varprefix = save_varprefix;
10076 if (iexpr->infercollid)
10077 appendStringInfo(buf, " COLLATE %s",
10078 generate_collation_name(iexpr->infercollid));
10080 /* Add the operator class name, if not default */
10081 if (iexpr->inferopclass)
10083 Oid inferopclass = iexpr->inferopclass;
10084 Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass);
10086 get_opclass_name(inferopclass, inferopcinputtype, buf);
10089 break;
10091 case T_PartitionBoundSpec:
10093 PartitionBoundSpec *spec = (PartitionBoundSpec *) node;
10094 ListCell *cell;
10095 char *sep;
10097 if (spec->is_default)
10099 appendStringInfoString(buf, "DEFAULT");
10100 break;
10103 switch (spec->strategy)
10105 case PARTITION_STRATEGY_HASH:
10106 Assert(spec->modulus > 0 && spec->remainder >= 0);
10107 Assert(spec->modulus > spec->remainder);
10109 appendStringInfoString(buf, "FOR VALUES");
10110 appendStringInfo(buf, " WITH (modulus %d, remainder %d)",
10111 spec->modulus, spec->remainder);
10112 break;
10114 case PARTITION_STRATEGY_LIST:
10115 Assert(spec->listdatums != NIL);
10117 appendStringInfoString(buf, "FOR VALUES IN (");
10118 sep = "";
10119 foreach(cell, spec->listdatums)
10121 Const *val = lfirst_node(Const, cell);
10123 appendStringInfoString(buf, sep);
10124 get_const_expr(val, context, -1);
10125 sep = ", ";
10128 appendStringInfoChar(buf, ')');
10129 break;
10131 case PARTITION_STRATEGY_RANGE:
10132 Assert(spec->lowerdatums != NIL &&
10133 spec->upperdatums != NIL &&
10134 list_length(spec->lowerdatums) ==
10135 list_length(spec->upperdatums));
10137 appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
10138 get_range_partbound_string(spec->lowerdatums),
10139 get_range_partbound_string(spec->upperdatums));
10140 break;
10142 default:
10143 elog(ERROR, "unrecognized partition strategy: %d",
10144 (int) spec->strategy);
10145 break;
10148 break;
10150 case T_JsonValueExpr:
10152 JsonValueExpr *jve = (JsonValueExpr *) node;
10154 get_rule_expr((Node *) jve->raw_expr, context, false);
10155 get_json_format(jve->format, context->buf);
10157 break;
10159 case T_JsonConstructorExpr:
10160 get_json_constructor((JsonConstructorExpr *) node, context, false);
10161 break;
10163 case T_JsonIsPredicate:
10165 JsonIsPredicate *pred = (JsonIsPredicate *) node;
10167 if (!PRETTY_PAREN(context))
10168 appendStringInfoChar(context->buf, '(');
10170 get_rule_expr_paren(pred->expr, context, true, node);
10172 appendStringInfoString(context->buf, " IS JSON");
10174 /* TODO: handle FORMAT clause */
10176 switch (pred->item_type)
10178 case JS_TYPE_SCALAR:
10179 appendStringInfoString(context->buf, " SCALAR");
10180 break;
10181 case JS_TYPE_ARRAY:
10182 appendStringInfoString(context->buf, " ARRAY");
10183 break;
10184 case JS_TYPE_OBJECT:
10185 appendStringInfoString(context->buf, " OBJECT");
10186 break;
10187 default:
10188 break;
10191 if (pred->unique_keys)
10192 appendStringInfoString(context->buf, " WITH UNIQUE KEYS");
10194 if (!PRETTY_PAREN(context))
10195 appendStringInfoChar(context->buf, ')');
10197 break;
10199 case T_JsonExpr:
10201 JsonExpr *jexpr = (JsonExpr *) node;
10203 switch (jexpr->op)
10205 case JSON_EXISTS_OP:
10206 appendStringInfoString(buf, "JSON_EXISTS(");
10207 break;
10208 case JSON_QUERY_OP:
10209 appendStringInfoString(buf, "JSON_QUERY(");
10210 break;
10211 case JSON_VALUE_OP:
10212 appendStringInfoString(buf, "JSON_VALUE(");
10213 break;
10214 default:
10215 elog(ERROR, "unrecognized JsonExpr op: %d",
10216 (int) jexpr->op);
10219 get_rule_expr(jexpr->formatted_expr, context, showimplicit);
10221 appendStringInfoString(buf, ", ");
10223 get_json_path_spec(jexpr->path_spec, context, showimplicit);
10225 if (jexpr->passing_values)
10227 ListCell *lc1,
10228 *lc2;
10229 bool needcomma = false;
10231 appendStringInfoString(buf, " PASSING ");
10233 forboth(lc1, jexpr->passing_names,
10234 lc2, jexpr->passing_values)
10236 if (needcomma)
10237 appendStringInfoString(buf, ", ");
10238 needcomma = true;
10240 get_rule_expr((Node *) lfirst(lc2), context, showimplicit);
10241 appendStringInfo(buf, " AS %s",
10242 ((String *) lfirst_node(String, lc1))->sval);
10246 if (jexpr->op != JSON_EXISTS_OP ||
10247 jexpr->returning->typid != BOOLOID)
10248 get_json_returning(jexpr->returning, context->buf,
10249 jexpr->op == JSON_QUERY_OP);
10251 get_json_expr_options(jexpr, context,
10252 jexpr->op != JSON_EXISTS_OP ?
10253 JSON_BEHAVIOR_NULL :
10254 JSON_BEHAVIOR_FALSE);
10256 appendStringInfoChar(buf, ')');
10258 break;
10260 case T_List:
10262 char *sep;
10263 ListCell *l;
10265 sep = "";
10266 foreach(l, (List *) node)
10268 appendStringInfoString(buf, sep);
10269 get_rule_expr((Node *) lfirst(l), context, showimplicit);
10270 sep = ", ";
10273 break;
10275 case T_TableFunc:
10276 get_tablefunc((TableFunc *) node, context, showimplicit);
10277 break;
10279 default:
10280 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
10281 break;
10286 * get_rule_expr_toplevel - Parse back a toplevel expression
10288 * Same as get_rule_expr(), except that if the expr is just a Var, we pass
10289 * istoplevel = true not false to get_variable(). This causes whole-row Vars
10290 * to get printed with decoration that will prevent expansion of "*".
10291 * We need to use this in contexts such as ROW() and VALUES(), where the
10292 * parser would expand "foo.*" appearing at top level. (In principle we'd
10293 * use this in get_target_list() too, but that has additional worries about
10294 * whether to print AS, so it needs to invoke get_variable() directly anyway.)
10296 static void
10297 get_rule_expr_toplevel(Node *node, deparse_context *context,
10298 bool showimplicit)
10300 if (node && IsA(node, Var))
10301 (void) get_variable((Var *) node, 0, true, context);
10302 else
10303 get_rule_expr(node, context, showimplicit);
10307 * get_rule_list_toplevel - Parse back a list of toplevel expressions
10309 * Apply get_rule_expr_toplevel() to each element of a List.
10311 * This adds commas between the expressions, but caller is responsible
10312 * for printing surrounding decoration.
10314 static void
10315 get_rule_list_toplevel(List *lst, deparse_context *context,
10316 bool showimplicit)
10318 const char *sep;
10319 ListCell *lc;
10321 sep = "";
10322 foreach(lc, lst)
10324 Node *e = (Node *) lfirst(lc);
10326 appendStringInfoString(context->buf, sep);
10327 get_rule_expr_toplevel(e, context, showimplicit);
10328 sep = ", ";
10333 * get_rule_expr_funccall - Parse back a function-call expression
10335 * Same as get_rule_expr(), except that we guarantee that the output will
10336 * look like a function call, or like one of the things the grammar treats as
10337 * equivalent to a function call (see the func_expr_windowless production).
10338 * This is needed in places where the grammar uses func_expr_windowless and
10339 * you can't substitute a parenthesized a_expr. If what we have isn't going
10340 * to look like a function call, wrap it in a dummy CAST() expression, which
10341 * will satisfy the grammar --- and, indeed, is likely what the user wrote to
10342 * produce such a thing.
10344 static void
10345 get_rule_expr_funccall(Node *node, deparse_context *context,
10346 bool showimplicit)
10348 if (looks_like_function(node))
10349 get_rule_expr(node, context, showimplicit);
10350 else
10352 StringInfo buf = context->buf;
10354 appendStringInfoString(buf, "CAST(");
10355 /* no point in showing any top-level implicit cast */
10356 get_rule_expr(node, context, false);
10357 appendStringInfo(buf, " AS %s)",
10358 format_type_with_typemod(exprType(node),
10359 exprTypmod(node)));
10364 * Helper function to identify node types that satisfy func_expr_windowless.
10365 * If in doubt, "false" is always a safe answer.
10367 static bool
10368 looks_like_function(Node *node)
10370 if (node == NULL)
10371 return false; /* probably shouldn't happen */
10372 switch (nodeTag(node))
10374 case T_FuncExpr:
10375 /* OK, unless it's going to deparse as a cast */
10376 return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL ||
10377 ((FuncExpr *) node)->funcformat == COERCE_SQL_SYNTAX);
10378 case T_NullIfExpr:
10379 case T_CoalesceExpr:
10380 case T_MinMaxExpr:
10381 case T_SQLValueFunction:
10382 case T_XmlExpr:
10383 case T_JsonExpr:
10384 /* these are all accepted by func_expr_common_subexpr */
10385 return true;
10386 default:
10387 break;
10389 return false;
10394 * get_oper_expr - Parse back an OpExpr node
10396 static void
10397 get_oper_expr(OpExpr *expr, deparse_context *context)
10399 StringInfo buf = context->buf;
10400 Oid opno = expr->opno;
10401 List *args = expr->args;
10403 if (!PRETTY_PAREN(context))
10404 appendStringInfoChar(buf, '(');
10405 if (list_length(args) == 2)
10407 /* binary operator */
10408 Node *arg1 = (Node *) linitial(args);
10409 Node *arg2 = (Node *) lsecond(args);
10411 get_rule_expr_paren(arg1, context, true, (Node *) expr);
10412 appendStringInfo(buf, " %s ",
10413 generate_operator_name(opno,
10414 exprType(arg1),
10415 exprType(arg2)));
10416 get_rule_expr_paren(arg2, context, true, (Node *) expr);
10418 else
10420 /* prefix operator */
10421 Node *arg = (Node *) linitial(args);
10423 appendStringInfo(buf, "%s ",
10424 generate_operator_name(opno,
10425 InvalidOid,
10426 exprType(arg)));
10427 get_rule_expr_paren(arg, context, true, (Node *) expr);
10429 if (!PRETTY_PAREN(context))
10430 appendStringInfoChar(buf, ')');
10434 * get_func_expr - Parse back a FuncExpr node
10436 static void
10437 get_func_expr(FuncExpr *expr, deparse_context *context,
10438 bool showimplicit)
10440 StringInfo buf = context->buf;
10441 Oid funcoid = expr->funcid;
10442 Oid argtypes[FUNC_MAX_ARGS];
10443 int nargs;
10444 List *argnames;
10445 bool use_variadic;
10446 ListCell *l;
10449 * If the function call came from an implicit coercion, then just show the
10450 * first argument --- unless caller wants to see implicit coercions.
10452 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
10454 get_rule_expr_paren((Node *) linitial(expr->args), context,
10455 false, (Node *) expr);
10456 return;
10460 * If the function call came from a cast, then show the first argument
10461 * plus an explicit cast operation.
10463 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
10464 expr->funcformat == COERCE_IMPLICIT_CAST)
10466 Node *arg = linitial(expr->args);
10467 Oid rettype = expr->funcresulttype;
10468 int32 coercedTypmod;
10470 /* Get the typmod if this is a length-coercion function */
10471 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
10473 get_coercion_expr(arg, context,
10474 rettype, coercedTypmod,
10475 (Node *) expr);
10477 return;
10481 * If the function was called using one of the SQL spec's random special
10482 * syntaxes, try to reproduce that. If we don't recognize the function,
10483 * fall through.
10485 if (expr->funcformat == COERCE_SQL_SYNTAX)
10487 if (get_func_sql_syntax(expr, context))
10488 return;
10492 * Normal function: display as proname(args). First we need to extract
10493 * the argument datatypes.
10495 if (list_length(expr->args) > FUNC_MAX_ARGS)
10496 ereport(ERROR,
10497 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
10498 errmsg("too many arguments")));
10499 nargs = 0;
10500 argnames = NIL;
10501 foreach(l, expr->args)
10503 Node *arg = (Node *) lfirst(l);
10505 if (IsA(arg, NamedArgExpr))
10506 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
10507 argtypes[nargs] = exprType(arg);
10508 nargs++;
10511 appendStringInfo(buf, "%s(",
10512 generate_function_name(funcoid, nargs,
10513 argnames, argtypes,
10514 expr->funcvariadic,
10515 &use_variadic,
10516 context->inGroupBy));
10517 nargs = 0;
10518 foreach(l, expr->args)
10520 if (nargs++ > 0)
10521 appendStringInfoString(buf, ", ");
10522 if (use_variadic && lnext(expr->args, l) == NULL)
10523 appendStringInfoString(buf, "VARIADIC ");
10524 get_rule_expr((Node *) lfirst(l), context, true);
10526 appendStringInfoChar(buf, ')');
10530 * get_agg_expr - Parse back an Aggref node
10532 static void
10533 get_agg_expr(Aggref *aggref, deparse_context *context,
10534 Aggref *original_aggref)
10536 get_agg_expr_helper(aggref, context, original_aggref, NULL, NULL,
10537 false);
10541 * get_agg_expr_helper - subroutine for get_agg_expr and
10542 * get_json_agg_constructor
10544 static void
10545 get_agg_expr_helper(Aggref *aggref, deparse_context *context,
10546 Aggref *original_aggref, const char *funcname,
10547 const char *options, bool is_json_objectagg)
10549 StringInfo buf = context->buf;
10550 Oid argtypes[FUNC_MAX_ARGS];
10551 int nargs;
10552 bool use_variadic = false;
10555 * For a combining aggregate, we look up and deparse the corresponding
10556 * partial aggregate instead. This is necessary because our input
10557 * argument list has been replaced; the new argument list always has just
10558 * one element, which will point to a partial Aggref that supplies us with
10559 * transition states to combine.
10561 if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
10563 TargetEntry *tle;
10565 Assert(list_length(aggref->args) == 1);
10566 tle = linitial_node(TargetEntry, aggref->args);
10567 resolve_special_varno((Node *) tle->expr, context,
10568 get_agg_combine_expr, original_aggref);
10569 return;
10573 * Mark as PARTIAL, if appropriate. We look to the original aggref so as
10574 * to avoid printing this when recursing from the code just above.
10576 if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
10577 appendStringInfoString(buf, "PARTIAL ");
10579 /* Extract the argument types as seen by the parser */
10580 nargs = get_aggregate_argtypes(aggref, argtypes);
10582 if (!funcname)
10583 funcname = generate_function_name(aggref->aggfnoid, nargs, NIL,
10584 argtypes, aggref->aggvariadic,
10585 &use_variadic,
10586 context->inGroupBy);
10588 /* Print the aggregate name, schema-qualified if needed */
10589 appendStringInfo(buf, "%s(%s", funcname,
10590 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
10592 if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
10595 * Ordered-set aggregates do not use "*" syntax. Also, we needn't
10596 * worry about inserting VARIADIC. So we can just dump the direct
10597 * args as-is.
10599 Assert(!aggref->aggvariadic);
10600 get_rule_expr((Node *) aggref->aggdirectargs, context, true);
10601 Assert(aggref->aggorder != NIL);
10602 appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
10603 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
10605 else
10607 /* aggstar can be set only in zero-argument aggregates */
10608 if (aggref->aggstar)
10609 appendStringInfoChar(buf, '*');
10610 else
10612 ListCell *l;
10613 int i;
10615 i = 0;
10616 foreach(l, aggref->args)
10618 TargetEntry *tle = (TargetEntry *) lfirst(l);
10619 Node *arg = (Node *) tle->expr;
10621 Assert(!IsA(arg, NamedArgExpr));
10622 if (tle->resjunk)
10623 continue;
10624 if (i++ > 0)
10626 if (is_json_objectagg)
10629 * the ABSENT ON NULL and WITH UNIQUE args are printed
10630 * separately, so ignore them here
10632 if (i > 2)
10633 break;
10635 appendStringInfoString(buf, " : ");
10637 else
10638 appendStringInfoString(buf, ", ");
10640 if (use_variadic && i == nargs)
10641 appendStringInfoString(buf, "VARIADIC ");
10642 get_rule_expr(arg, context, true);
10646 if (aggref->aggorder != NIL)
10648 appendStringInfoString(buf, " ORDER BY ");
10649 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
10653 if (options)
10654 appendStringInfoString(buf, options);
10656 if (aggref->aggfilter != NULL)
10658 appendStringInfoString(buf, ") FILTER (WHERE ");
10659 get_rule_expr((Node *) aggref->aggfilter, context, false);
10662 appendStringInfoChar(buf, ')');
10666 * This is a helper function for get_agg_expr(). It's used when we deparse
10667 * a combining Aggref; resolve_special_varno locates the corresponding partial
10668 * Aggref and then calls this.
10670 static void
10671 get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
10673 Aggref *aggref;
10674 Aggref *original_aggref = callback_arg;
10676 if (!IsA(node, Aggref))
10677 elog(ERROR, "combining Aggref does not point to an Aggref");
10679 aggref = (Aggref *) node;
10680 get_agg_expr(aggref, context, original_aggref);
10684 * get_windowfunc_expr - Parse back a WindowFunc node
10686 static void
10687 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
10689 get_windowfunc_expr_helper(wfunc, context, NULL, NULL, false);
10694 * get_windowfunc_expr_helper - subroutine for get_windowfunc_expr and
10695 * get_json_agg_constructor
10697 static void
10698 get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
10699 const char *funcname, const char *options,
10700 bool is_json_objectagg)
10702 StringInfo buf = context->buf;
10703 Oid argtypes[FUNC_MAX_ARGS];
10704 int nargs;
10705 List *argnames;
10706 ListCell *l;
10708 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
10709 ereport(ERROR,
10710 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
10711 errmsg("too many arguments")));
10712 nargs = 0;
10713 argnames = NIL;
10714 foreach(l, wfunc->args)
10716 Node *arg = (Node *) lfirst(l);
10718 if (IsA(arg, NamedArgExpr))
10719 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
10720 argtypes[nargs] = exprType(arg);
10721 nargs++;
10724 if (!funcname)
10725 funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
10726 argtypes, false, NULL,
10727 context->inGroupBy);
10729 appendStringInfo(buf, "%s(", funcname);
10731 /* winstar can be set only in zero-argument aggregates */
10732 if (wfunc->winstar)
10733 appendStringInfoChar(buf, '*');
10734 else
10736 if (is_json_objectagg)
10738 get_rule_expr((Node *) linitial(wfunc->args), context, false);
10739 appendStringInfoString(buf, " : ");
10740 get_rule_expr((Node *) lsecond(wfunc->args), context, false);
10742 else
10743 get_rule_expr((Node *) wfunc->args, context, true);
10746 if (options)
10747 appendStringInfoString(buf, options);
10749 if (wfunc->aggfilter != NULL)
10751 appendStringInfoString(buf, ") FILTER (WHERE ");
10752 get_rule_expr((Node *) wfunc->aggfilter, context, false);
10755 appendStringInfoString(buf, ") OVER ");
10757 foreach(l, context->windowClause)
10759 WindowClause *wc = (WindowClause *) lfirst(l);
10761 if (wc->winref == wfunc->winref)
10763 if (wc->name)
10764 appendStringInfoString(buf, quote_identifier(wc->name));
10765 else
10766 get_rule_windowspec(wc, context->targetList, context);
10767 break;
10770 if (l == NULL)
10772 if (context->windowClause)
10773 elog(ERROR, "could not find window clause for winref %u",
10774 wfunc->winref);
10777 * In EXPLAIN, we don't have window context information available, so
10778 * we have to settle for this:
10780 appendStringInfoString(buf, "(?)");
10785 * get_func_sql_syntax - Parse back a SQL-syntax function call
10787 * Returns true if we successfully deparsed, false if we did not
10788 * recognize the function.
10790 static bool
10791 get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
10793 StringInfo buf = context->buf;
10794 Oid funcoid = expr->funcid;
10796 switch (funcoid)
10798 case F_TIMEZONE_INTERVAL_TIMESTAMP:
10799 case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
10800 case F_TIMEZONE_INTERVAL_TIMETZ:
10801 case F_TIMEZONE_TEXT_TIMESTAMP:
10802 case F_TIMEZONE_TEXT_TIMESTAMPTZ:
10803 case F_TIMEZONE_TEXT_TIMETZ:
10804 /* AT TIME ZONE ... note reversed argument order */
10805 appendStringInfoChar(buf, '(');
10806 get_rule_expr_paren((Node *) lsecond(expr->args), context, false,
10807 (Node *) expr);
10808 appendStringInfoString(buf, " AT TIME ZONE ");
10809 get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10810 (Node *) expr);
10811 appendStringInfoChar(buf, ')');
10812 return true;
10814 case F_TIMEZONE_TIMESTAMP:
10815 case F_TIMEZONE_TIMESTAMPTZ:
10816 case F_TIMEZONE_TIMETZ:
10817 /* AT LOCAL */
10818 appendStringInfoChar(buf, '(');
10819 get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10820 (Node *) expr);
10821 appendStringInfoString(buf, " AT LOCAL)");
10822 return true;
10824 case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
10825 case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
10826 case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
10827 case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
10828 case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
10829 case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
10830 case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
10831 case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
10832 case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
10833 case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
10834 case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
10835 case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
10836 case F_OVERLAPS_TIME_TIME_TIME_TIME:
10837 /* (x1, x2) OVERLAPS (y1, y2) */
10838 appendStringInfoString(buf, "((");
10839 get_rule_expr((Node *) linitial(expr->args), context, false);
10840 appendStringInfoString(buf, ", ");
10841 get_rule_expr((Node *) lsecond(expr->args), context, false);
10842 appendStringInfoString(buf, ") OVERLAPS (");
10843 get_rule_expr((Node *) lthird(expr->args), context, false);
10844 appendStringInfoString(buf, ", ");
10845 get_rule_expr((Node *) lfourth(expr->args), context, false);
10846 appendStringInfoString(buf, "))");
10847 return true;
10849 case F_EXTRACT_TEXT_DATE:
10850 case F_EXTRACT_TEXT_TIME:
10851 case F_EXTRACT_TEXT_TIMETZ:
10852 case F_EXTRACT_TEXT_TIMESTAMP:
10853 case F_EXTRACT_TEXT_TIMESTAMPTZ:
10854 case F_EXTRACT_TEXT_INTERVAL:
10855 /* EXTRACT (x FROM y) */
10856 appendStringInfoString(buf, "EXTRACT(");
10858 Const *con = (Const *) linitial(expr->args);
10860 Assert(IsA(con, Const) &&
10861 con->consttype == TEXTOID &&
10862 !con->constisnull);
10863 appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
10865 appendStringInfoString(buf, " FROM ");
10866 get_rule_expr((Node *) lsecond(expr->args), context, false);
10867 appendStringInfoChar(buf, ')');
10868 return true;
10870 case F_IS_NORMALIZED:
10871 /* IS xxx NORMALIZED */
10872 appendStringInfoChar(buf, '(');
10873 get_rule_expr_paren((Node *) linitial(expr->args), context, false,
10874 (Node *) expr);
10875 appendStringInfoString(buf, " IS");
10876 if (list_length(expr->args) == 2)
10878 Const *con = (Const *) lsecond(expr->args);
10880 Assert(IsA(con, Const) &&
10881 con->consttype == TEXTOID &&
10882 !con->constisnull);
10883 appendStringInfo(buf, " %s",
10884 TextDatumGetCString(con->constvalue));
10886 appendStringInfoString(buf, " NORMALIZED)");
10887 return true;
10889 case F_PG_COLLATION_FOR:
10890 /* COLLATION FOR */
10891 appendStringInfoString(buf, "COLLATION FOR (");
10892 get_rule_expr((Node *) linitial(expr->args), context, false);
10893 appendStringInfoChar(buf, ')');
10894 return true;
10896 case F_NORMALIZE:
10897 /* NORMALIZE() */
10898 appendStringInfoString(buf, "NORMALIZE(");
10899 get_rule_expr((Node *) linitial(expr->args), context, false);
10900 if (list_length(expr->args) == 2)
10902 Const *con = (Const *) lsecond(expr->args);
10904 Assert(IsA(con, Const) &&
10905 con->consttype == TEXTOID &&
10906 !con->constisnull);
10907 appendStringInfo(buf, ", %s",
10908 TextDatumGetCString(con->constvalue));
10910 appendStringInfoChar(buf, ')');
10911 return true;
10913 case F_OVERLAY_BIT_BIT_INT4:
10914 case F_OVERLAY_BIT_BIT_INT4_INT4:
10915 case F_OVERLAY_BYTEA_BYTEA_INT4:
10916 case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
10917 case F_OVERLAY_TEXT_TEXT_INT4:
10918 case F_OVERLAY_TEXT_TEXT_INT4_INT4:
10919 /* OVERLAY() */
10920 appendStringInfoString(buf, "OVERLAY(");
10921 get_rule_expr((Node *) linitial(expr->args), context, false);
10922 appendStringInfoString(buf, " PLACING ");
10923 get_rule_expr((Node *) lsecond(expr->args), context, false);
10924 appendStringInfoString(buf, " FROM ");
10925 get_rule_expr((Node *) lthird(expr->args), context, false);
10926 if (list_length(expr->args) == 4)
10928 appendStringInfoString(buf, " FOR ");
10929 get_rule_expr((Node *) lfourth(expr->args), context, false);
10931 appendStringInfoChar(buf, ')');
10932 return true;
10934 case F_POSITION_BIT_BIT:
10935 case F_POSITION_BYTEA_BYTEA:
10936 case F_POSITION_TEXT_TEXT:
10937 /* POSITION() ... extra parens since args are b_expr not a_expr */
10938 appendStringInfoString(buf, "POSITION((");
10939 get_rule_expr((Node *) lsecond(expr->args), context, false);
10940 appendStringInfoString(buf, ") IN (");
10941 get_rule_expr((Node *) linitial(expr->args), context, false);
10942 appendStringInfoString(buf, "))");
10943 return true;
10945 case F_SUBSTRING_BIT_INT4:
10946 case F_SUBSTRING_BIT_INT4_INT4:
10947 case F_SUBSTRING_BYTEA_INT4:
10948 case F_SUBSTRING_BYTEA_INT4_INT4:
10949 case F_SUBSTRING_TEXT_INT4:
10950 case F_SUBSTRING_TEXT_INT4_INT4:
10951 /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
10952 appendStringInfoString(buf, "SUBSTRING(");
10953 get_rule_expr((Node *) linitial(expr->args), context, false);
10954 appendStringInfoString(buf, " FROM ");
10955 get_rule_expr((Node *) lsecond(expr->args), context, false);
10956 if (list_length(expr->args) == 3)
10958 appendStringInfoString(buf, " FOR ");
10959 get_rule_expr((Node *) lthird(expr->args), context, false);
10961 appendStringInfoChar(buf, ')');
10962 return true;
10964 case F_SUBSTRING_TEXT_TEXT_TEXT:
10965 /* SUBSTRING SIMILAR/ESCAPE */
10966 appendStringInfoString(buf, "SUBSTRING(");
10967 get_rule_expr((Node *) linitial(expr->args), context, false);
10968 appendStringInfoString(buf, " SIMILAR ");
10969 get_rule_expr((Node *) lsecond(expr->args), context, false);
10970 appendStringInfoString(buf, " ESCAPE ");
10971 get_rule_expr((Node *) lthird(expr->args), context, false);
10972 appendStringInfoChar(buf, ')');
10973 return true;
10975 case F_BTRIM_BYTEA_BYTEA:
10976 case F_BTRIM_TEXT:
10977 case F_BTRIM_TEXT_TEXT:
10978 /* TRIM() */
10979 appendStringInfoString(buf, "TRIM(BOTH");
10980 if (list_length(expr->args) == 2)
10982 appendStringInfoChar(buf, ' ');
10983 get_rule_expr((Node *) lsecond(expr->args), context, false);
10985 appendStringInfoString(buf, " FROM ");
10986 get_rule_expr((Node *) linitial(expr->args), context, false);
10987 appendStringInfoChar(buf, ')');
10988 return true;
10990 case F_LTRIM_BYTEA_BYTEA:
10991 case F_LTRIM_TEXT:
10992 case F_LTRIM_TEXT_TEXT:
10993 /* TRIM() */
10994 appendStringInfoString(buf, "TRIM(LEADING");
10995 if (list_length(expr->args) == 2)
10997 appendStringInfoChar(buf, ' ');
10998 get_rule_expr((Node *) lsecond(expr->args), context, false);
11000 appendStringInfoString(buf, " FROM ");
11001 get_rule_expr((Node *) linitial(expr->args), context, false);
11002 appendStringInfoChar(buf, ')');
11003 return true;
11005 case F_RTRIM_BYTEA_BYTEA:
11006 case F_RTRIM_TEXT:
11007 case F_RTRIM_TEXT_TEXT:
11008 /* TRIM() */
11009 appendStringInfoString(buf, "TRIM(TRAILING");
11010 if (list_length(expr->args) == 2)
11012 appendStringInfoChar(buf, ' ');
11013 get_rule_expr((Node *) lsecond(expr->args), context, false);
11015 appendStringInfoString(buf, " FROM ");
11016 get_rule_expr((Node *) linitial(expr->args), context, false);
11017 appendStringInfoChar(buf, ')');
11018 return true;
11020 case F_SYSTEM_USER:
11021 appendStringInfoString(buf, "SYSTEM_USER");
11022 return true;
11024 case F_XMLEXISTS:
11025 /* XMLEXISTS ... extra parens because args are c_expr */
11026 appendStringInfoString(buf, "XMLEXISTS((");
11027 get_rule_expr((Node *) linitial(expr->args), context, false);
11028 appendStringInfoString(buf, ") PASSING (");
11029 get_rule_expr((Node *) lsecond(expr->args), context, false);
11030 appendStringInfoString(buf, "))");
11031 return true;
11033 return false;
11036 /* ----------
11037 * get_coercion_expr
11039 * Make a string representation of a value coerced to a specific type
11040 * ----------
11042 static void
11043 get_coercion_expr(Node *arg, deparse_context *context,
11044 Oid resulttype, int32 resulttypmod,
11045 Node *parentNode)
11047 StringInfo buf = context->buf;
11050 * Since parse_coerce.c doesn't immediately collapse application of
11051 * length-coercion functions to constants, what we'll typically see in
11052 * such cases is a Const with typmod -1 and a length-coercion function
11053 * right above it. Avoid generating redundant output. However, beware of
11054 * suppressing casts when the user actually wrote something like
11055 * 'foo'::text::char(3).
11057 * Note: it might seem that we are missing the possibility of needing to
11058 * print a COLLATE clause for such a Const. However, a Const could only
11059 * have nondefault collation in a post-constant-folding tree, in which the
11060 * length coercion would have been folded too. See also the special
11061 * handling of CollateExpr in coerce_to_target_type(): any collation
11062 * marking will be above the coercion node, not below it.
11064 if (arg && IsA(arg, Const) &&
11065 ((Const *) arg)->consttype == resulttype &&
11066 ((Const *) arg)->consttypmod == -1)
11068 /* Show the constant without normal ::typename decoration */
11069 get_const_expr((Const *) arg, context, -1);
11071 else
11073 if (!PRETTY_PAREN(context))
11074 appendStringInfoChar(buf, '(');
11075 get_rule_expr_paren(arg, context, false, parentNode);
11076 if (!PRETTY_PAREN(context))
11077 appendStringInfoChar(buf, ')');
11081 * Never emit resulttype(arg) functional notation. A pg_proc entry could
11082 * take precedence, and a resulttype in pg_temp would require schema
11083 * qualification that format_type_with_typemod() would usually omit. We've
11084 * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
11085 * would work fine.
11087 appendStringInfo(buf, "::%s",
11088 format_type_with_typemod(resulttype, resulttypmod));
11091 /* ----------
11092 * get_const_expr
11094 * Make a string representation of a Const
11096 * showtype can be -1 to never show "::typename" decoration, or +1 to always
11097 * show it, or 0 to show it only if the constant wouldn't be assumed to be
11098 * the right type by default.
11100 * If the Const's collation isn't default for its type, show that too.
11101 * We mustn't do this when showtype is -1 (since that means the caller will
11102 * print "::typename", and we can't put a COLLATE clause in between). It's
11103 * caller's responsibility that collation isn't missed in such cases.
11104 * ----------
11106 static void
11107 get_const_expr(Const *constval, deparse_context *context, int showtype)
11109 StringInfo buf = context->buf;
11110 Oid typoutput;
11111 bool typIsVarlena;
11112 char *extval;
11113 bool needlabel = false;
11115 if (constval->constisnull)
11118 * Always label the type of a NULL constant to prevent misdecisions
11119 * about type when reparsing.
11121 appendStringInfoString(buf, "NULL");
11122 if (showtype >= 0)
11124 appendStringInfo(buf, "::%s",
11125 format_type_with_typemod(constval->consttype,
11126 constval->consttypmod));
11127 get_const_collation(constval, context);
11129 return;
11132 getTypeOutputInfo(constval->consttype,
11133 &typoutput, &typIsVarlena);
11135 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
11137 switch (constval->consttype)
11139 case INT4OID:
11142 * INT4 can be printed without any decoration, unless it is
11143 * negative; in that case print it as '-nnn'::integer to ensure
11144 * that the output will re-parse as a constant, not as a constant
11145 * plus operator. In most cases we could get away with printing
11146 * (-nnn) instead, because of the way that gram.y handles negative
11147 * literals; but that doesn't work for INT_MIN, and it doesn't
11148 * seem that much prettier anyway.
11150 if (extval[0] != '-')
11151 appendStringInfoString(buf, extval);
11152 else
11154 appendStringInfo(buf, "'%s'", extval);
11155 needlabel = true; /* we must attach a cast */
11157 break;
11159 case NUMERICOID:
11162 * NUMERIC can be printed without quotes if it looks like a float
11163 * constant (not an integer, and not Infinity or NaN) and doesn't
11164 * have a leading sign (for the same reason as for INT4).
11166 if (isdigit((unsigned char) extval[0]) &&
11167 strcspn(extval, "eE.") != strlen(extval))
11169 appendStringInfoString(buf, extval);
11171 else
11173 appendStringInfo(buf, "'%s'", extval);
11174 needlabel = true; /* we must attach a cast */
11176 break;
11178 case BOOLOID:
11179 if (strcmp(extval, "t") == 0)
11180 appendStringInfoString(buf, "true");
11181 else
11182 appendStringInfoString(buf, "false");
11183 break;
11185 default:
11186 simple_quote_literal(buf, extval);
11187 break;
11190 pfree(extval);
11192 if (showtype < 0)
11193 return;
11196 * For showtype == 0, append ::typename unless the constant will be
11197 * implicitly typed as the right type when it is read in.
11199 * XXX this code has to be kept in sync with the behavior of the parser,
11200 * especially make_const.
11202 switch (constval->consttype)
11204 case BOOLOID:
11205 case UNKNOWNOID:
11206 /* These types can be left unlabeled */
11207 needlabel = false;
11208 break;
11209 case INT4OID:
11210 /* We determined above whether a label is needed */
11211 break;
11212 case NUMERICOID:
11215 * Float-looking constants will be typed as numeric, which we
11216 * checked above; but if there's a nondefault typmod we need to
11217 * show it.
11219 needlabel |= (constval->consttypmod >= 0);
11220 break;
11221 default:
11222 needlabel = true;
11223 break;
11225 if (needlabel || showtype > 0)
11226 appendStringInfo(buf, "::%s",
11227 format_type_with_typemod(constval->consttype,
11228 constval->consttypmod));
11230 get_const_collation(constval, context);
11234 * helper for get_const_expr: append COLLATE if needed
11236 static void
11237 get_const_collation(Const *constval, deparse_context *context)
11239 StringInfo buf = context->buf;
11241 if (OidIsValid(constval->constcollid))
11243 Oid typcollation = get_typcollation(constval->consttype);
11245 if (constval->constcollid != typcollation)
11247 appendStringInfo(buf, " COLLATE %s",
11248 generate_collation_name(constval->constcollid));
11254 * get_json_path_spec - Parse back a JSON path specification
11256 static void
11257 get_json_path_spec(Node *path_spec, deparse_context *context, bool showimplicit)
11259 if (IsA(path_spec, Const))
11260 get_const_expr((Const *) path_spec, context, -1);
11261 else
11262 get_rule_expr(path_spec, context, showimplicit);
11266 * get_json_format - Parse back a JsonFormat node
11268 static void
11269 get_json_format(JsonFormat *format, StringInfo buf)
11271 if (format->format_type == JS_FORMAT_DEFAULT)
11272 return;
11274 appendStringInfoString(buf,
11275 format->format_type == JS_FORMAT_JSONB ?
11276 " FORMAT JSONB" : " FORMAT JSON");
11278 if (format->encoding != JS_ENC_DEFAULT)
11280 const char *encoding;
11282 encoding =
11283 format->encoding == JS_ENC_UTF16 ? "UTF16" :
11284 format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
11286 appendStringInfo(buf, " ENCODING %s", encoding);
11291 * get_json_returning - Parse back a JsonReturning structure
11293 static void
11294 get_json_returning(JsonReturning *returning, StringInfo buf,
11295 bool json_format_by_default)
11297 if (!OidIsValid(returning->typid))
11298 return;
11300 appendStringInfo(buf, " RETURNING %s",
11301 format_type_with_typemod(returning->typid,
11302 returning->typmod));
11304 if (!json_format_by_default ||
11305 returning->format->format_type !=
11306 (returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
11307 get_json_format(returning->format, buf);
11311 * get_json_constructor - Parse back a JsonConstructorExpr node
11313 static void
11314 get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context,
11315 bool showimplicit)
11317 StringInfo buf = context->buf;
11318 const char *funcname;
11319 bool is_json_object;
11320 int curridx;
11321 ListCell *lc;
11323 if (ctor->type == JSCTOR_JSON_OBJECTAGG)
11325 get_json_agg_constructor(ctor, context, "JSON_OBJECTAGG", true);
11326 return;
11328 else if (ctor->type == JSCTOR_JSON_ARRAYAGG)
11330 get_json_agg_constructor(ctor, context, "JSON_ARRAYAGG", false);
11331 return;
11334 switch (ctor->type)
11336 case JSCTOR_JSON_OBJECT:
11337 funcname = "JSON_OBJECT";
11338 break;
11339 case JSCTOR_JSON_ARRAY:
11340 funcname = "JSON_ARRAY";
11341 break;
11342 case JSCTOR_JSON_PARSE:
11343 funcname = "JSON";
11344 break;
11345 case JSCTOR_JSON_SCALAR:
11346 funcname = "JSON_SCALAR";
11347 break;
11348 case JSCTOR_JSON_SERIALIZE:
11349 funcname = "JSON_SERIALIZE";
11350 break;
11351 default:
11352 elog(ERROR, "invalid JsonConstructorType %d", ctor->type);
11355 appendStringInfo(buf, "%s(", funcname);
11357 is_json_object = ctor->type == JSCTOR_JSON_OBJECT;
11358 foreach(lc, ctor->args)
11360 curridx = foreach_current_index(lc);
11361 if (curridx > 0)
11363 const char *sep;
11365 sep = (is_json_object && (curridx % 2) != 0) ? " : " : ", ";
11366 appendStringInfoString(buf, sep);
11369 get_rule_expr((Node *) lfirst(lc), context, true);
11372 get_json_constructor_options(ctor, buf);
11373 appendStringInfoChar(buf, ')');
11377 * Append options, if any, to the JSON constructor being deparsed
11379 static void
11380 get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
11382 if (ctor->absent_on_null)
11384 if (ctor->type == JSCTOR_JSON_OBJECT ||
11385 ctor->type == JSCTOR_JSON_OBJECTAGG)
11386 appendStringInfoString(buf, " ABSENT ON NULL");
11388 else
11390 if (ctor->type == JSCTOR_JSON_ARRAY ||
11391 ctor->type == JSCTOR_JSON_ARRAYAGG)
11392 appendStringInfoString(buf, " NULL ON NULL");
11395 if (ctor->unique)
11396 appendStringInfoString(buf, " WITH UNIQUE KEYS");
11399 * Append RETURNING clause if needed; JSON() and JSON_SCALAR() don't
11400 * support one.
11402 if (ctor->type != JSCTOR_JSON_PARSE && ctor->type != JSCTOR_JSON_SCALAR)
11403 get_json_returning(ctor->returning, buf, true);
11407 * get_json_agg_constructor - Parse back an aggregate JsonConstructorExpr node
11409 static void
11410 get_json_agg_constructor(JsonConstructorExpr *ctor, deparse_context *context,
11411 const char *funcname, bool is_json_objectagg)
11413 StringInfoData options;
11415 initStringInfo(&options);
11416 get_json_constructor_options(ctor, &options);
11418 if (IsA(ctor->func, Aggref))
11419 get_agg_expr_helper((Aggref *) ctor->func, context,
11420 (Aggref *) ctor->func,
11421 funcname, options.data, is_json_objectagg);
11422 else if (IsA(ctor->func, WindowFunc))
11423 get_windowfunc_expr_helper((WindowFunc *) ctor->func, context,
11424 funcname, options.data,
11425 is_json_objectagg);
11426 else
11427 elog(ERROR, "invalid JsonConstructorExpr underlying node type: %d",
11428 nodeTag(ctor->func));
11432 * simple_quote_literal - Format a string as a SQL literal, append to buf
11434 static void
11435 simple_quote_literal(StringInfo buf, const char *val)
11437 const char *valptr;
11440 * We form the string literal according to the prevailing setting of
11441 * standard_conforming_strings; we never use E''. User is responsible for
11442 * making sure result is used correctly.
11444 appendStringInfoChar(buf, '\'');
11445 for (valptr = val; *valptr; valptr++)
11447 char ch = *valptr;
11449 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
11450 appendStringInfoChar(buf, ch);
11451 appendStringInfoChar(buf, ch);
11453 appendStringInfoChar(buf, '\'');
11457 /* ----------
11458 * get_sublink_expr - Parse back a sublink
11459 * ----------
11461 static void
11462 get_sublink_expr(SubLink *sublink, deparse_context *context)
11464 StringInfo buf = context->buf;
11465 Query *query = (Query *) (sublink->subselect);
11466 char *opname = NULL;
11467 bool need_paren;
11469 if (sublink->subLinkType == ARRAY_SUBLINK)
11470 appendStringInfoString(buf, "ARRAY(");
11471 else
11472 appendStringInfoChar(buf, '(');
11475 * Note that we print the name of only the first operator, when there are
11476 * multiple combining operators. This is an approximation that could go
11477 * wrong in various scenarios (operators in different schemas, renamed
11478 * operators, etc) but there is not a whole lot we can do about it, since
11479 * the syntax allows only one operator to be shown.
11481 if (sublink->testexpr)
11483 if (IsA(sublink->testexpr, OpExpr))
11485 /* single combining operator */
11486 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
11488 get_rule_expr(linitial(opexpr->args), context, true);
11489 opname = generate_operator_name(opexpr->opno,
11490 exprType(linitial(opexpr->args)),
11491 exprType(lsecond(opexpr->args)));
11493 else if (IsA(sublink->testexpr, BoolExpr))
11495 /* multiple combining operators, = or <> cases */
11496 char *sep;
11497 ListCell *l;
11499 appendStringInfoChar(buf, '(');
11500 sep = "";
11501 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
11503 OpExpr *opexpr = lfirst_node(OpExpr, l);
11505 appendStringInfoString(buf, sep);
11506 get_rule_expr(linitial(opexpr->args), context, true);
11507 if (!opname)
11508 opname = generate_operator_name(opexpr->opno,
11509 exprType(linitial(opexpr->args)),
11510 exprType(lsecond(opexpr->args)));
11511 sep = ", ";
11513 appendStringInfoChar(buf, ')');
11515 else if (IsA(sublink->testexpr, RowCompareExpr))
11517 /* multiple combining operators, < <= > >= cases */
11518 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
11520 appendStringInfoChar(buf, '(');
11521 get_rule_expr((Node *) rcexpr->largs, context, true);
11522 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
11523 exprType(linitial(rcexpr->largs)),
11524 exprType(linitial(rcexpr->rargs)));
11525 appendStringInfoChar(buf, ')');
11527 else
11528 elog(ERROR, "unrecognized testexpr type: %d",
11529 (int) nodeTag(sublink->testexpr));
11532 need_paren = true;
11534 switch (sublink->subLinkType)
11536 case EXISTS_SUBLINK:
11537 appendStringInfoString(buf, "EXISTS ");
11538 break;
11540 case ANY_SUBLINK:
11541 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
11542 appendStringInfoString(buf, " IN ");
11543 else
11544 appendStringInfo(buf, " %s ANY ", opname);
11545 break;
11547 case ALL_SUBLINK:
11548 appendStringInfo(buf, " %s ALL ", opname);
11549 break;
11551 case ROWCOMPARE_SUBLINK:
11552 appendStringInfo(buf, " %s ", opname);
11553 break;
11555 case EXPR_SUBLINK:
11556 case MULTIEXPR_SUBLINK:
11557 case ARRAY_SUBLINK:
11558 need_paren = false;
11559 break;
11561 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
11562 default:
11563 elog(ERROR, "unrecognized sublink type: %d",
11564 (int) sublink->subLinkType);
11565 break;
11568 if (need_paren)
11569 appendStringInfoChar(buf, '(');
11571 get_query_def(query, buf, context->namespaces, NULL, false,
11572 context->prettyFlags, context->wrapColumn,
11573 context->indentLevel);
11575 if (need_paren)
11576 appendStringInfoString(buf, "))");
11577 else
11578 appendStringInfoChar(buf, ')');
11582 /* ----------
11583 * get_xmltable - Parse back a XMLTABLE function
11584 * ----------
11586 static void
11587 get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
11589 StringInfo buf = context->buf;
11591 appendStringInfoString(buf, "XMLTABLE(");
11593 if (tf->ns_uris != NIL)
11595 ListCell *lc1,
11596 *lc2;
11597 bool first = true;
11599 appendStringInfoString(buf, "XMLNAMESPACES (");
11600 forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
11602 Node *expr = (Node *) lfirst(lc1);
11603 String *ns_node = lfirst_node(String, lc2);
11605 if (!first)
11606 appendStringInfoString(buf, ", ");
11607 else
11608 first = false;
11610 if (ns_node != NULL)
11612 get_rule_expr(expr, context, showimplicit);
11613 appendStringInfo(buf, " AS %s", strVal(ns_node));
11615 else
11617 appendStringInfoString(buf, "DEFAULT ");
11618 get_rule_expr(expr, context, showimplicit);
11621 appendStringInfoString(buf, "), ");
11624 appendStringInfoChar(buf, '(');
11625 get_rule_expr((Node *) tf->rowexpr, context, showimplicit);
11626 appendStringInfoString(buf, ") PASSING (");
11627 get_rule_expr((Node *) tf->docexpr, context, showimplicit);
11628 appendStringInfoChar(buf, ')');
11630 if (tf->colexprs != NIL)
11632 ListCell *l1;
11633 ListCell *l2;
11634 ListCell *l3;
11635 ListCell *l4;
11636 ListCell *l5;
11637 int colnum = 0;
11639 appendStringInfoString(buf, " COLUMNS ");
11640 forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods,
11641 l4, tf->colexprs, l5, tf->coldefexprs)
11643 char *colname = strVal(lfirst(l1));
11644 Oid typid = lfirst_oid(l2);
11645 int32 typmod = lfirst_int(l3);
11646 Node *colexpr = (Node *) lfirst(l4);
11647 Node *coldefexpr = (Node *) lfirst(l5);
11648 bool ordinality = (tf->ordinalitycol == colnum);
11649 bool notnull = bms_is_member(colnum, tf->notnulls);
11651 if (colnum > 0)
11652 appendStringInfoString(buf, ", ");
11653 colnum++;
11655 appendStringInfo(buf, "%s %s", quote_identifier(colname),
11656 ordinality ? "FOR ORDINALITY" :
11657 format_type_with_typemod(typid, typmod));
11658 if (ordinality)
11659 continue;
11661 if (coldefexpr != NULL)
11663 appendStringInfoString(buf, " DEFAULT (");
11664 get_rule_expr((Node *) coldefexpr, context, showimplicit);
11665 appendStringInfoChar(buf, ')');
11667 if (colexpr != NULL)
11669 appendStringInfoString(buf, " PATH (");
11670 get_rule_expr((Node *) colexpr, context, showimplicit);
11671 appendStringInfoChar(buf, ')');
11673 if (notnull)
11674 appendStringInfoString(buf, " NOT NULL");
11678 appendStringInfoChar(buf, ')');
11682 * get_json_table_nested_columns - Parse back nested JSON_TABLE columns
11684 static void
11685 get_json_table_nested_columns(TableFunc *tf, JsonTablePlan *plan,
11686 deparse_context *context, bool showimplicit,
11687 bool needcomma)
11689 if (IsA(plan, JsonTablePathScan))
11691 JsonTablePathScan *scan = castNode(JsonTablePathScan, plan);
11693 if (needcomma)
11694 appendStringInfoChar(context->buf, ',');
11696 appendStringInfoChar(context->buf, ' ');
11697 appendContextKeyword(context, "NESTED PATH ", 0, 0, 0);
11698 get_const_expr(scan->path->value, context, -1);
11699 appendStringInfo(context->buf, " AS %s", quote_identifier(scan->path->name));
11700 get_json_table_columns(tf, scan, context, showimplicit);
11702 else if (IsA(plan, JsonTableSiblingJoin))
11704 JsonTableSiblingJoin *join = (JsonTableSiblingJoin *) plan;
11706 get_json_table_nested_columns(tf, join->lplan, context, showimplicit,
11707 needcomma);
11708 get_json_table_nested_columns(tf, join->rplan, context, showimplicit,
11709 true);
11714 * get_json_table_columns - Parse back JSON_TABLE columns
11716 static void
11717 get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan,
11718 deparse_context *context,
11719 bool showimplicit)
11721 StringInfo buf = context->buf;
11722 JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr);
11723 ListCell *lc_colname;
11724 ListCell *lc_coltype;
11725 ListCell *lc_coltypmod;
11726 ListCell *lc_colvalexpr;
11727 int colnum = 0;
11729 appendStringInfoChar(buf, ' ');
11730 appendContextKeyword(context, "COLUMNS (", 0, 0, 0);
11732 if (PRETTY_INDENT(context))
11733 context->indentLevel += PRETTYINDENT_VAR;
11735 forfour(lc_colname, tf->colnames,
11736 lc_coltype, tf->coltypes,
11737 lc_coltypmod, tf->coltypmods,
11738 lc_colvalexpr, tf->colvalexprs)
11740 char *colname = strVal(lfirst(lc_colname));
11741 JsonExpr *colexpr;
11742 Oid typid;
11743 int32 typmod;
11744 bool ordinality;
11745 JsonBehaviorType default_behavior;
11747 typid = lfirst_oid(lc_coltype);
11748 typmod = lfirst_int(lc_coltypmod);
11749 colexpr = castNode(JsonExpr, lfirst(lc_colvalexpr));
11751 /* Skip columns that don't belong to this scan. */
11752 if (scan->colMin < 0 || colnum < scan->colMin)
11754 colnum++;
11755 continue;
11757 if (colnum > scan->colMax)
11758 break;
11760 if (colnum > scan->colMin)
11761 appendStringInfoString(buf, ", ");
11763 colnum++;
11765 ordinality = !colexpr;
11767 appendContextKeyword(context, "", 0, 0, 0);
11769 appendStringInfo(buf, "%s %s", quote_identifier(colname),
11770 ordinality ? "FOR ORDINALITY" :
11771 format_type_with_typemod(typid, typmod));
11772 if (ordinality)
11773 continue;
11775 if (colexpr->op == JSON_EXISTS_OP)
11777 appendStringInfoString(buf, " EXISTS");
11778 default_behavior = JSON_BEHAVIOR_FALSE;
11780 else
11782 if (colexpr->op == JSON_QUERY_OP)
11784 char typcategory;
11785 bool typispreferred;
11787 get_type_category_preferred(typid, &typcategory, &typispreferred);
11789 if (typcategory == TYPCATEGORY_STRING)
11790 appendStringInfoString(buf,
11791 colexpr->format->format_type == JS_FORMAT_JSONB ?
11792 " FORMAT JSONB" : " FORMAT JSON");
11795 default_behavior = JSON_BEHAVIOR_NULL;
11798 if (jexpr->on_error->btype == JSON_BEHAVIOR_ERROR)
11799 default_behavior = JSON_BEHAVIOR_ERROR;
11801 appendStringInfoString(buf, " PATH ");
11803 get_json_path_spec(colexpr->path_spec, context, showimplicit);
11805 get_json_expr_options(colexpr, context, default_behavior);
11808 if (scan->child)
11809 get_json_table_nested_columns(tf, scan->child, context, showimplicit,
11810 scan->colMin >= 0);
11812 if (PRETTY_INDENT(context))
11813 context->indentLevel -= PRETTYINDENT_VAR;
11815 appendContextKeyword(context, ")", 0, 0, 0);
11818 /* ----------
11819 * get_json_table - Parse back a JSON_TABLE function
11820 * ----------
11822 static void
11823 get_json_table(TableFunc *tf, deparse_context *context, bool showimplicit)
11825 StringInfo buf = context->buf;
11826 JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr);
11827 JsonTablePathScan *root = castNode(JsonTablePathScan, tf->plan);
11829 appendStringInfoString(buf, "JSON_TABLE(");
11831 if (PRETTY_INDENT(context))
11832 context->indentLevel += PRETTYINDENT_VAR;
11834 appendContextKeyword(context, "", 0, 0, 0);
11836 get_rule_expr(jexpr->formatted_expr, context, showimplicit);
11838 appendStringInfoString(buf, ", ");
11840 get_const_expr(root->path->value, context, -1);
11842 appendStringInfo(buf, " AS %s", quote_identifier(root->path->name));
11844 if (jexpr->passing_values)
11846 ListCell *lc1,
11847 *lc2;
11848 bool needcomma = false;
11850 appendStringInfoChar(buf, ' ');
11851 appendContextKeyword(context, "PASSING ", 0, 0, 0);
11853 if (PRETTY_INDENT(context))
11854 context->indentLevel += PRETTYINDENT_VAR;
11856 forboth(lc1, jexpr->passing_names,
11857 lc2, jexpr->passing_values)
11859 if (needcomma)
11860 appendStringInfoString(buf, ", ");
11861 needcomma = true;
11863 appendContextKeyword(context, "", 0, 0, 0);
11865 get_rule_expr((Node *) lfirst(lc2), context, false);
11866 appendStringInfo(buf, " AS %s",
11867 quote_identifier((lfirst_node(String, lc1))->sval)
11871 if (PRETTY_INDENT(context))
11872 context->indentLevel -= PRETTYINDENT_VAR;
11875 get_json_table_columns(tf, castNode(JsonTablePathScan, tf->plan), context,
11876 showimplicit);
11878 if (jexpr->on_error->btype != JSON_BEHAVIOR_EMPTY)
11879 get_json_behavior(jexpr->on_error, context, "ERROR");
11881 if (PRETTY_INDENT(context))
11882 context->indentLevel -= PRETTYINDENT_VAR;
11884 appendContextKeyword(context, ")", 0, 0, 0);
11887 /* ----------
11888 * get_tablefunc - Parse back a table function
11889 * ----------
11891 static void
11892 get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
11894 /* XMLTABLE and JSON_TABLE are the only existing implementations. */
11896 if (tf->functype == TFT_XMLTABLE)
11897 get_xmltable(tf, context, showimplicit);
11898 else if (tf->functype == TFT_JSON_TABLE)
11899 get_json_table(tf, context, showimplicit);
11902 /* ----------
11903 * get_from_clause - Parse back a FROM clause
11905 * "prefix" is the keyword that denotes the start of the list of FROM
11906 * elements. It is FROM when used to parse back SELECT and UPDATE, but
11907 * is USING when parsing back DELETE.
11908 * ----------
11910 static void
11911 get_from_clause(Query *query, const char *prefix, deparse_context *context)
11913 StringInfo buf = context->buf;
11914 bool first = true;
11915 ListCell *l;
11918 * We use the query's jointree as a guide to what to print. However, we
11919 * must ignore auto-added RTEs that are marked not inFromCl. (These can
11920 * only appear at the top level of the jointree, so it's sufficient to
11921 * check here.) This check also ensures we ignore the rule pseudo-RTEs
11922 * for NEW and OLD.
11924 foreach(l, query->jointree->fromlist)
11926 Node *jtnode = (Node *) lfirst(l);
11928 if (IsA(jtnode, RangeTblRef))
11930 int varno = ((RangeTblRef *) jtnode)->rtindex;
11931 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
11933 if (!rte->inFromCl)
11934 continue;
11937 if (first)
11939 appendContextKeyword(context, prefix,
11940 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
11941 first = false;
11943 get_from_clause_item(jtnode, query, context);
11945 else
11947 StringInfoData itembuf;
11949 appendStringInfoString(buf, ", ");
11952 * Put the new FROM item's text into itembuf so we can decide
11953 * after we've got it whether or not it needs to go on a new line.
11955 initStringInfo(&itembuf);
11956 context->buf = &itembuf;
11958 get_from_clause_item(jtnode, query, context);
11960 /* Restore context's output buffer */
11961 context->buf = buf;
11963 /* Consider line-wrapping if enabled */
11964 if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
11966 /* Does the new item start with a new line? */
11967 if (itembuf.len > 0 && itembuf.data[0] == '\n')
11969 /* If so, we shouldn't add anything */
11970 /* instead, remove any trailing spaces currently in buf */
11971 removeStringInfoSpaces(buf);
11973 else
11975 char *trailing_nl;
11977 /* Locate the start of the current line in the buffer */
11978 trailing_nl = strrchr(buf->data, '\n');
11979 if (trailing_nl == NULL)
11980 trailing_nl = buf->data;
11981 else
11982 trailing_nl++;
11985 * Add a newline, plus some indentation, if the new item
11986 * would cause an overflow.
11988 if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
11989 appendContextKeyword(context, "", -PRETTYINDENT_STD,
11990 PRETTYINDENT_STD,
11991 PRETTYINDENT_VAR);
11995 /* Add the new item */
11996 appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
11998 /* clean up */
11999 pfree(itembuf.data);
12004 static void
12005 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
12007 StringInfo buf = context->buf;
12008 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
12010 if (IsA(jtnode, RangeTblRef))
12012 int varno = ((RangeTblRef *) jtnode)->rtindex;
12013 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
12014 deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
12015 RangeTblFunction *rtfunc1 = NULL;
12017 if (rte->lateral)
12018 appendStringInfoString(buf, "LATERAL ");
12020 /* Print the FROM item proper */
12021 switch (rte->rtekind)
12023 case RTE_RELATION:
12024 /* Normal relation RTE */
12025 appendStringInfo(buf, "%s%s",
12026 only_marker(rte),
12027 generate_relation_name(rte->relid,
12028 context->namespaces));
12029 break;
12030 case RTE_SUBQUERY:
12031 /* Subquery RTE */
12032 appendStringInfoChar(buf, '(');
12033 get_query_def(rte->subquery, buf, context->namespaces, NULL,
12034 true,
12035 context->prettyFlags, context->wrapColumn,
12036 context->indentLevel);
12037 appendStringInfoChar(buf, ')');
12038 break;
12039 case RTE_FUNCTION:
12040 /* Function RTE */
12041 rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
12044 * Omit ROWS FROM() syntax for just one function, unless it
12045 * has both a coldeflist and WITH ORDINALITY. If it has both,
12046 * we must use ROWS FROM() syntax to avoid ambiguity about
12047 * whether the coldeflist includes the ordinality column.
12049 if (list_length(rte->functions) == 1 &&
12050 (rtfunc1->funccolnames == NIL || !rte->funcordinality))
12052 get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
12053 /* we'll print the coldeflist below, if it has one */
12055 else
12057 bool all_unnest;
12058 ListCell *lc;
12061 * If all the function calls in the list are to unnest,
12062 * and none need a coldeflist, then collapse the list back
12063 * down to UNNEST(args). (If we had more than one
12064 * built-in unnest function, this would get more
12065 * difficult.)
12067 * XXX This is pretty ugly, since it makes not-terribly-
12068 * future-proof assumptions about what the parser would do
12069 * with the output; but the alternative is to emit our
12070 * nonstandard ROWS FROM() notation for what might have
12071 * been a perfectly spec-compliant multi-argument
12072 * UNNEST().
12074 all_unnest = true;
12075 foreach(lc, rte->functions)
12077 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
12079 if (!IsA(rtfunc->funcexpr, FuncExpr) ||
12080 ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
12081 rtfunc->funccolnames != NIL)
12083 all_unnest = false;
12084 break;
12088 if (all_unnest)
12090 List *allargs = NIL;
12092 foreach(lc, rte->functions)
12094 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
12095 List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
12097 allargs = list_concat(allargs, args);
12100 appendStringInfoString(buf, "UNNEST(");
12101 get_rule_expr((Node *) allargs, context, true);
12102 appendStringInfoChar(buf, ')');
12104 else
12106 int funcno = 0;
12108 appendStringInfoString(buf, "ROWS FROM(");
12109 foreach(lc, rte->functions)
12111 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
12113 if (funcno > 0)
12114 appendStringInfoString(buf, ", ");
12115 get_rule_expr_funccall(rtfunc->funcexpr, context, true);
12116 if (rtfunc->funccolnames != NIL)
12118 /* Reconstruct the column definition list */
12119 appendStringInfoString(buf, " AS ");
12120 get_from_clause_coldeflist(rtfunc,
12121 NULL,
12122 context);
12124 funcno++;
12126 appendStringInfoChar(buf, ')');
12128 /* prevent printing duplicate coldeflist below */
12129 rtfunc1 = NULL;
12131 if (rte->funcordinality)
12132 appendStringInfoString(buf, " WITH ORDINALITY");
12133 break;
12134 case RTE_TABLEFUNC:
12135 get_tablefunc(rte->tablefunc, context, true);
12136 break;
12137 case RTE_VALUES:
12138 /* Values list RTE */
12139 appendStringInfoChar(buf, '(');
12140 get_values_def(rte->values_lists, context);
12141 appendStringInfoChar(buf, ')');
12142 break;
12143 case RTE_CTE:
12144 appendStringInfoString(buf, quote_identifier(rte->ctename));
12145 break;
12146 default:
12147 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
12148 break;
12151 /* Print the relation alias, if needed */
12152 get_rte_alias(rte, varno, false, context);
12154 /* Print the column definitions or aliases, if needed */
12155 if (rtfunc1 && rtfunc1->funccolnames != NIL)
12157 /* Reconstruct the columndef list, which is also the aliases */
12158 get_from_clause_coldeflist(rtfunc1, colinfo, context);
12160 else
12162 /* Else print column aliases as needed */
12163 get_column_alias_list(colinfo, context);
12166 /* Tablesample clause must go after any alias */
12167 if (rte->rtekind == RTE_RELATION && rte->tablesample)
12168 get_tablesample_def(rte->tablesample, context);
12170 else if (IsA(jtnode, JoinExpr))
12172 JoinExpr *j = (JoinExpr *) jtnode;
12173 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
12174 bool need_paren_on_right;
12176 need_paren_on_right = PRETTY_PAREN(context) &&
12177 !IsA(j->rarg, RangeTblRef) &&
12178 !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
12180 if (!PRETTY_PAREN(context) || j->alias != NULL)
12181 appendStringInfoChar(buf, '(');
12183 get_from_clause_item(j->larg, query, context);
12185 switch (j->jointype)
12187 case JOIN_INNER:
12188 if (j->quals)
12189 appendContextKeyword(context, " JOIN ",
12190 -PRETTYINDENT_STD,
12191 PRETTYINDENT_STD,
12192 PRETTYINDENT_JOIN);
12193 else
12194 appendContextKeyword(context, " CROSS JOIN ",
12195 -PRETTYINDENT_STD,
12196 PRETTYINDENT_STD,
12197 PRETTYINDENT_JOIN);
12198 break;
12199 case JOIN_LEFT:
12200 appendContextKeyword(context, " LEFT JOIN ",
12201 -PRETTYINDENT_STD,
12202 PRETTYINDENT_STD,
12203 PRETTYINDENT_JOIN);
12204 break;
12205 case JOIN_FULL:
12206 appendContextKeyword(context, " FULL JOIN ",
12207 -PRETTYINDENT_STD,
12208 PRETTYINDENT_STD,
12209 PRETTYINDENT_JOIN);
12210 break;
12211 case JOIN_RIGHT:
12212 appendContextKeyword(context, " RIGHT JOIN ",
12213 -PRETTYINDENT_STD,
12214 PRETTYINDENT_STD,
12215 PRETTYINDENT_JOIN);
12216 break;
12217 default:
12218 elog(ERROR, "unrecognized join type: %d",
12219 (int) j->jointype);
12222 if (need_paren_on_right)
12223 appendStringInfoChar(buf, '(');
12224 get_from_clause_item(j->rarg, query, context);
12225 if (need_paren_on_right)
12226 appendStringInfoChar(buf, ')');
12228 if (j->usingClause)
12230 ListCell *lc;
12231 bool first = true;
12233 appendStringInfoString(buf, " USING (");
12234 /* Use the assigned names, not what's in usingClause */
12235 foreach(lc, colinfo->usingNames)
12237 char *colname = (char *) lfirst(lc);
12239 if (first)
12240 first = false;
12241 else
12242 appendStringInfoString(buf, ", ");
12243 appendStringInfoString(buf, quote_identifier(colname));
12245 appendStringInfoChar(buf, ')');
12247 if (j->join_using_alias)
12248 appendStringInfo(buf, " AS %s",
12249 quote_identifier(j->join_using_alias->aliasname));
12251 else if (j->quals)
12253 appendStringInfoString(buf, " ON ");
12254 if (!PRETTY_PAREN(context))
12255 appendStringInfoChar(buf, '(');
12256 get_rule_expr(j->quals, context, false);
12257 if (!PRETTY_PAREN(context))
12258 appendStringInfoChar(buf, ')');
12260 else if (j->jointype != JOIN_INNER)
12262 /* If we didn't say CROSS JOIN above, we must provide an ON */
12263 appendStringInfoString(buf, " ON TRUE");
12266 if (!PRETTY_PAREN(context) || j->alias != NULL)
12267 appendStringInfoChar(buf, ')');
12269 /* Yes, it's correct to put alias after the right paren ... */
12270 if (j->alias != NULL)
12273 * Note that it's correct to emit an alias clause if and only if
12274 * there was one originally. Otherwise we'd be converting a named
12275 * join to unnamed or vice versa, which creates semantic
12276 * subtleties we don't want. However, we might print a different
12277 * alias name than was there originally.
12279 appendStringInfo(buf, " %s",
12280 quote_identifier(get_rtable_name(j->rtindex,
12281 context)));
12282 get_column_alias_list(colinfo, context);
12285 else
12286 elog(ERROR, "unrecognized node type: %d",
12287 (int) nodeTag(jtnode));
12291 * get_rte_alias - print the relation's alias, if needed
12293 * If printed, the alias is preceded by a space, or by " AS " if use_as is true.
12295 static void
12296 get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
12297 deparse_context *context)
12299 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
12300 char *refname = get_rtable_name(varno, context);
12301 deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
12302 bool printalias = false;
12304 if (rte->alias != NULL)
12306 /* Always print alias if user provided one */
12307 printalias = true;
12309 else if (colinfo->printaliases)
12311 /* Always print alias if we need to print column aliases */
12312 printalias = true;
12314 else if (rte->rtekind == RTE_RELATION)
12317 * No need to print alias if it's same as relation name (this would
12318 * normally be the case, but not if set_rtable_names had to resolve a
12319 * conflict).
12321 if (strcmp(refname, get_relation_name(rte->relid)) != 0)
12322 printalias = true;
12324 else if (rte->rtekind == RTE_FUNCTION)
12327 * For a function RTE, always print alias. This covers possible
12328 * renaming of the function and/or instability of the FigureColname
12329 * rules for things that aren't simple functions. Note we'd need to
12330 * force it anyway for the columndef list case.
12332 printalias = true;
12334 else if (rte->rtekind == RTE_SUBQUERY ||
12335 rte->rtekind == RTE_VALUES)
12338 * For a subquery, always print alias. This makes the output
12339 * SQL-spec-compliant, even though we allow such aliases to be omitted
12340 * on input.
12342 printalias = true;
12344 else if (rte->rtekind == RTE_CTE)
12347 * No need to print alias if it's same as CTE name (this would
12348 * normally be the case, but not if set_rtable_names had to resolve a
12349 * conflict).
12351 if (strcmp(refname, rte->ctename) != 0)
12352 printalias = true;
12355 if (printalias)
12356 appendStringInfo(context->buf, "%s%s",
12357 use_as ? " AS " : " ",
12358 quote_identifier(refname));
12362 * get_column_alias_list - print column alias list for an RTE
12364 * Caller must already have printed the relation's alias name.
12366 static void
12367 get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
12369 StringInfo buf = context->buf;
12370 int i;
12371 bool first = true;
12373 /* Don't print aliases if not needed */
12374 if (!colinfo->printaliases)
12375 return;
12377 for (i = 0; i < colinfo->num_new_cols; i++)
12379 char *colname = colinfo->new_colnames[i];
12381 if (first)
12383 appendStringInfoChar(buf, '(');
12384 first = false;
12386 else
12387 appendStringInfoString(buf, ", ");
12388 appendStringInfoString(buf, quote_identifier(colname));
12390 if (!first)
12391 appendStringInfoChar(buf, ')');
12395 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
12397 * When printing a top-level coldeflist (which is syntactically also the
12398 * relation's column alias list), use column names from colinfo. But when
12399 * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
12400 * original coldeflist's names, which are available in rtfunc->funccolnames.
12401 * Pass NULL for colinfo to select the latter behavior.
12403 * The coldeflist is appended immediately (no space) to buf. Caller is
12404 * responsible for ensuring that an alias or AS is present before it.
12406 static void
12407 get_from_clause_coldeflist(RangeTblFunction *rtfunc,
12408 deparse_columns *colinfo,
12409 deparse_context *context)
12411 StringInfo buf = context->buf;
12412 ListCell *l1;
12413 ListCell *l2;
12414 ListCell *l3;
12415 ListCell *l4;
12416 int i;
12418 appendStringInfoChar(buf, '(');
12420 i = 0;
12421 forfour(l1, rtfunc->funccoltypes,
12422 l2, rtfunc->funccoltypmods,
12423 l3, rtfunc->funccolcollations,
12424 l4, rtfunc->funccolnames)
12426 Oid atttypid = lfirst_oid(l1);
12427 int32 atttypmod = lfirst_int(l2);
12428 Oid attcollation = lfirst_oid(l3);
12429 char *attname;
12431 if (colinfo)
12432 attname = colinfo->colnames[i];
12433 else
12434 attname = strVal(lfirst(l4));
12436 Assert(attname); /* shouldn't be any dropped columns here */
12438 if (i > 0)
12439 appendStringInfoString(buf, ", ");
12440 appendStringInfo(buf, "%s %s",
12441 quote_identifier(attname),
12442 format_type_with_typemod(atttypid, atttypmod));
12443 if (OidIsValid(attcollation) &&
12444 attcollation != get_typcollation(atttypid))
12445 appendStringInfo(buf, " COLLATE %s",
12446 generate_collation_name(attcollation));
12448 i++;
12451 appendStringInfoChar(buf, ')');
12455 * get_tablesample_def - print a TableSampleClause
12457 static void
12458 get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
12460 StringInfo buf = context->buf;
12461 Oid argtypes[1];
12462 int nargs;
12463 ListCell *l;
12466 * We should qualify the handler's function name if it wouldn't be
12467 * resolved by lookup in the current search path.
12469 argtypes[0] = INTERNALOID;
12470 appendStringInfo(buf, " TABLESAMPLE %s (",
12471 generate_function_name(tablesample->tsmhandler, 1,
12472 NIL, argtypes,
12473 false, NULL, false));
12475 nargs = 0;
12476 foreach(l, tablesample->args)
12478 if (nargs++ > 0)
12479 appendStringInfoString(buf, ", ");
12480 get_rule_expr((Node *) lfirst(l), context, false);
12482 appendStringInfoChar(buf, ')');
12484 if (tablesample->repeatable != NULL)
12486 appendStringInfoString(buf, " REPEATABLE (");
12487 get_rule_expr((Node *) tablesample->repeatable, context, false);
12488 appendStringInfoChar(buf, ')');
12493 * get_opclass_name - fetch name of an index operator class
12495 * The opclass name is appended (after a space) to buf.
12497 * Output is suppressed if the opclass is the default for the given
12498 * actual_datatype. (If you don't want this behavior, just pass
12499 * InvalidOid for actual_datatype.)
12501 static void
12502 get_opclass_name(Oid opclass, Oid actual_datatype,
12503 StringInfo buf)
12505 HeapTuple ht_opc;
12506 Form_pg_opclass opcrec;
12507 char *opcname;
12508 char *nspname;
12510 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
12511 if (!HeapTupleIsValid(ht_opc))
12512 elog(ERROR, "cache lookup failed for opclass %u", opclass);
12513 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
12515 if (!OidIsValid(actual_datatype) ||
12516 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
12518 /* Okay, we need the opclass name. Do we need to qualify it? */
12519 opcname = NameStr(opcrec->opcname);
12520 if (OpclassIsVisible(opclass))
12521 appendStringInfo(buf, " %s", quote_identifier(opcname));
12522 else
12524 nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
12525 appendStringInfo(buf, " %s.%s",
12526 quote_identifier(nspname),
12527 quote_identifier(opcname));
12530 ReleaseSysCache(ht_opc);
12534 * generate_opclass_name
12535 * Compute the name to display for an opclass specified by OID
12537 * The result includes all necessary quoting and schema-prefixing.
12539 char *
12540 generate_opclass_name(Oid opclass)
12542 StringInfoData buf;
12544 initStringInfo(&buf);
12545 get_opclass_name(opclass, InvalidOid, &buf);
12547 return &buf.data[1]; /* get_opclass_name() prepends space */
12551 * processIndirection - take care of array and subfield assignment
12553 * We strip any top-level FieldStore or assignment SubscriptingRef nodes that
12554 * appear in the input, printing them as decoration for the base column
12555 * name (which we assume the caller just printed). We might also need to
12556 * strip CoerceToDomain nodes, but only ones that appear above assignment
12557 * nodes.
12559 * Returns the subexpression that's to be assigned.
12561 static Node *
12562 processIndirection(Node *node, deparse_context *context)
12564 StringInfo buf = context->buf;
12565 CoerceToDomain *cdomain = NULL;
12567 for (;;)
12569 if (node == NULL)
12570 break;
12571 if (IsA(node, FieldStore))
12573 FieldStore *fstore = (FieldStore *) node;
12574 Oid typrelid;
12575 char *fieldname;
12577 /* lookup tuple type */
12578 typrelid = get_typ_typrelid(fstore->resulttype);
12579 if (!OidIsValid(typrelid))
12580 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
12581 format_type_be(fstore->resulttype));
12584 * Print the field name. There should only be one target field in
12585 * stored rules. There could be more than that in executable
12586 * target lists, but this function cannot be used for that case.
12588 Assert(list_length(fstore->fieldnums) == 1);
12589 fieldname = get_attname(typrelid,
12590 linitial_int(fstore->fieldnums), false);
12591 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
12594 * We ignore arg since it should be an uninteresting reference to
12595 * the target column or subcolumn.
12597 node = (Node *) linitial(fstore->newvals);
12599 else if (IsA(node, SubscriptingRef))
12601 SubscriptingRef *sbsref = (SubscriptingRef *) node;
12603 if (sbsref->refassgnexpr == NULL)
12604 break;
12606 printSubscripts(sbsref, context);
12609 * We ignore refexpr since it should be an uninteresting reference
12610 * to the target column or subcolumn.
12612 node = (Node *) sbsref->refassgnexpr;
12614 else if (IsA(node, CoerceToDomain))
12616 cdomain = (CoerceToDomain *) node;
12617 /* If it's an explicit domain coercion, we're done */
12618 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
12619 break;
12620 /* Tentatively descend past the CoerceToDomain */
12621 node = (Node *) cdomain->arg;
12623 else
12624 break;
12628 * If we descended past a CoerceToDomain whose argument turned out not to
12629 * be a FieldStore or array assignment, back up to the CoerceToDomain.
12630 * (This is not enough to be fully correct if there are nested implicit
12631 * CoerceToDomains, but such cases shouldn't ever occur.)
12633 if (cdomain && node == (Node *) cdomain->arg)
12634 node = (Node *) cdomain;
12636 return node;
12639 static void
12640 printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
12642 StringInfo buf = context->buf;
12643 ListCell *lowlist_item;
12644 ListCell *uplist_item;
12646 lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */
12647 foreach(uplist_item, sbsref->refupperindexpr)
12649 appendStringInfoChar(buf, '[');
12650 if (lowlist_item)
12652 /* If subexpression is NULL, get_rule_expr prints nothing */
12653 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
12654 appendStringInfoChar(buf, ':');
12655 lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
12657 /* If subexpression is NULL, get_rule_expr prints nothing */
12658 get_rule_expr((Node *) lfirst(uplist_item), context, false);
12659 appendStringInfoChar(buf, ']');
12664 * quote_identifier - Quote an identifier only if needed
12666 * When quotes are needed, we palloc the required space; slightly
12667 * space-wasteful but well worth it for notational simplicity.
12669 const char *
12670 quote_identifier(const char *ident)
12673 * Can avoid quoting if ident starts with a lowercase letter or underscore
12674 * and contains only lowercase letters, digits, and underscores, *and* is
12675 * not any SQL keyword. Otherwise, supply quotes.
12677 int nquotes = 0;
12678 bool safe;
12679 const char *ptr;
12680 char *result;
12681 char *optr;
12684 * would like to use <ctype.h> macros here, but they might yield unwanted
12685 * locale-specific results...
12687 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12689 for (ptr = ident; *ptr; ptr++)
12691 char ch = *ptr;
12693 if ((ch >= 'a' && ch <= 'z') ||
12694 (ch >= '0' && ch <= '9') ||
12695 (ch == '_'))
12697 /* okay */
12699 else
12701 safe = false;
12702 if (ch == '"')
12703 nquotes++;
12707 if (quote_all_identifiers)
12708 safe = false;
12710 if (safe)
12713 * Check for keyword. We quote keywords except for unreserved ones.
12714 * (In some cases we could avoid quoting a col_name or type_func_name
12715 * keyword, but it seems much harder than it's worth to tell that.)
12717 * Note: ScanKeywordLookup() does case-insensitive comparison, but
12718 * that's fine, since we already know we have all-lower-case.
12720 int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12722 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12723 safe = false;
12726 if (safe)
12727 return ident; /* no change needed */
12729 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12731 optr = result;
12732 *optr++ = '"';
12733 for (ptr = ident; *ptr; ptr++)
12735 char ch = *ptr;
12737 if (ch == '"')
12738 *optr++ = '"';
12739 *optr++ = ch;
12741 *optr++ = '"';
12742 *optr = '\0';
12744 return result;
12748 * quote_qualified_identifier - Quote a possibly-qualified identifier
12750 * Return a name of the form qualifier.ident, or just ident if qualifier
12751 * is NULL, quoting each component if necessary. The result is palloc'd.
12753 char *
12754 quote_qualified_identifier(const char *qualifier,
12755 const char *ident)
12757 StringInfoData buf;
12759 initStringInfo(&buf);
12760 if (qualifier)
12761 appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
12762 appendStringInfoString(&buf, quote_identifier(ident));
12763 return buf.data;
12767 * get_relation_name
12768 * Get the unqualified name of a relation specified by OID
12770 * This differs from the underlying get_rel_name() function in that it will
12771 * throw error instead of silently returning NULL if the OID is bad.
12773 static char *
12774 get_relation_name(Oid relid)
12776 char *relname = get_rel_name(relid);
12778 if (!relname)
12779 elog(ERROR, "cache lookup failed for relation %u", relid);
12780 return relname;
12784 * generate_relation_name
12785 * Compute the name to display for a relation specified by OID
12787 * The result includes all necessary quoting and schema-prefixing.
12789 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
12790 * We will forcibly qualify the relation name if it equals any CTE name
12791 * visible in the namespace list.
12793 static char *
12794 generate_relation_name(Oid relid, List *namespaces)
12796 HeapTuple tp;
12797 Form_pg_class reltup;
12798 bool need_qual;
12799 ListCell *nslist;
12800 char *relname;
12801 char *nspname;
12802 char *result;
12804 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12805 if (!HeapTupleIsValid(tp))
12806 elog(ERROR, "cache lookup failed for relation %u", relid);
12807 reltup = (Form_pg_class) GETSTRUCT(tp);
12808 relname = NameStr(reltup->relname);
12810 /* Check for conflicting CTE name */
12811 need_qual = false;
12812 foreach(nslist, namespaces)
12814 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
12815 ListCell *ctlist;
12817 foreach(ctlist, dpns->ctes)
12819 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
12821 if (strcmp(cte->ctename, relname) == 0)
12823 need_qual = true;
12824 break;
12827 if (need_qual)
12828 break;
12831 /* Otherwise, qualify the name if not visible in search path */
12832 if (!need_qual)
12833 need_qual = !RelationIsVisible(relid);
12835 if (need_qual)
12836 nspname = get_namespace_name_or_temp(reltup->relnamespace);
12837 else
12838 nspname = NULL;
12840 result = quote_qualified_identifier(nspname, relname);
12842 ReleaseSysCache(tp);
12844 return result;
12848 * generate_qualified_relation_name
12849 * Compute the name to display for a relation specified by OID
12851 * As above, but unconditionally schema-qualify the name.
12853 static char *
12854 generate_qualified_relation_name(Oid relid)
12856 HeapTuple tp;
12857 Form_pg_class reltup;
12858 char *relname;
12859 char *nspname;
12860 char *result;
12862 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12863 if (!HeapTupleIsValid(tp))
12864 elog(ERROR, "cache lookup failed for relation %u", relid);
12865 reltup = (Form_pg_class) GETSTRUCT(tp);
12866 relname = NameStr(reltup->relname);
12868 nspname = get_namespace_name_or_temp(reltup->relnamespace);
12869 if (!nspname)
12870 elog(ERROR, "cache lookup failed for namespace %u",
12871 reltup->relnamespace);
12873 result = quote_qualified_identifier(nspname, relname);
12875 ReleaseSysCache(tp);
12877 return result;
12881 * generate_function_name
12882 * Compute the name to display for a function specified by OID,
12883 * given that it is being called with the specified actual arg names and
12884 * types. (Those matter because of ambiguous-function resolution rules.)
12886 * If we're dealing with a potentially variadic function (in practice, this
12887 * means a FuncExpr or Aggref, not some other way of calling a function), then
12888 * has_variadic must specify whether variadic arguments have been merged,
12889 * and *use_variadic_p will be set to indicate whether to print VARIADIC in
12890 * the output. For non-FuncExpr cases, has_variadic should be false and
12891 * use_variadic_p can be NULL.
12893 * inGroupBy must be true if we're deparsing a GROUP BY clause.
12895 * The result includes all necessary quoting and schema-prefixing.
12897 static char *
12898 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
12899 bool has_variadic, bool *use_variadic_p,
12900 bool inGroupBy)
12902 char *result;
12903 HeapTuple proctup;
12904 Form_pg_proc procform;
12905 char *proname;
12906 bool use_variadic;
12907 char *nspname;
12908 FuncDetailCode p_result;
12909 Oid p_funcid;
12910 Oid p_rettype;
12911 bool p_retset;
12912 int p_nvargs;
12913 Oid p_vatype;
12914 Oid *p_true_typeids;
12915 bool force_qualify = false;
12917 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
12918 if (!HeapTupleIsValid(proctup))
12919 elog(ERROR, "cache lookup failed for function %u", funcid);
12920 procform = (Form_pg_proc) GETSTRUCT(proctup);
12921 proname = NameStr(procform->proname);
12924 * Due to parser hacks to avoid needing to reserve CUBE, we need to force
12925 * qualification of some function names within GROUP BY.
12927 if (inGroupBy)
12929 if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
12930 force_qualify = true;
12934 * Determine whether VARIADIC should be printed. We must do this first
12935 * since it affects the lookup rules in func_get_detail().
12937 * We always print VARIADIC if the function has a merged variadic-array
12938 * argument. Note that this is always the case for functions taking a
12939 * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
12940 * and printed the array elements as separate arguments, the call could
12941 * match a newer non-VARIADIC function.
12943 if (use_variadic_p)
12945 /* Parser should not have set funcvariadic unless fn is variadic */
12946 Assert(!has_variadic || OidIsValid(procform->provariadic));
12947 use_variadic = has_variadic;
12948 *use_variadic_p = use_variadic;
12950 else
12952 Assert(!has_variadic);
12953 use_variadic = false;
12957 * The idea here is to schema-qualify only if the parser would fail to
12958 * resolve the correct function given the unqualified func name with the
12959 * specified argtypes and VARIADIC flag. But if we already decided to
12960 * force qualification, then we can skip the lookup and pretend we didn't
12961 * find it.
12963 if (!force_qualify)
12964 p_result = func_get_detail(list_make1(makeString(proname)),
12965 NIL, argnames, nargs, argtypes,
12966 !use_variadic, true, false,
12967 &p_funcid, &p_rettype,
12968 &p_retset, &p_nvargs, &p_vatype,
12969 &p_true_typeids, NULL);
12970 else
12972 p_result = FUNCDETAIL_NOTFOUND;
12973 p_funcid = InvalidOid;
12976 if ((p_result == FUNCDETAIL_NORMAL ||
12977 p_result == FUNCDETAIL_AGGREGATE ||
12978 p_result == FUNCDETAIL_WINDOWFUNC) &&
12979 p_funcid == funcid)
12980 nspname = NULL;
12981 else
12982 nspname = get_namespace_name_or_temp(procform->pronamespace);
12984 result = quote_qualified_identifier(nspname, proname);
12986 ReleaseSysCache(proctup);
12988 return result;
12992 * generate_operator_name
12993 * Compute the name to display for an operator specified by OID,
12994 * given that it is being called with the specified actual arg types.
12995 * (Arg types matter because of ambiguous-operator resolution rules.
12996 * Pass InvalidOid for unused arg of a unary operator.)
12998 * The result includes all necessary quoting and schema-prefixing,
12999 * plus the OPERATOR() decoration needed to use a qualified operator name
13000 * in an expression.
13002 static char *
13003 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
13005 StringInfoData buf;
13006 HeapTuple opertup;
13007 Form_pg_operator operform;
13008 char *oprname;
13009 char *nspname;
13010 Operator p_result;
13012 initStringInfo(&buf);
13014 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
13015 if (!HeapTupleIsValid(opertup))
13016 elog(ERROR, "cache lookup failed for operator %u", operid);
13017 operform = (Form_pg_operator) GETSTRUCT(opertup);
13018 oprname = NameStr(operform->oprname);
13021 * The idea here is to schema-qualify only if the parser would fail to
13022 * resolve the correct operator given the unqualified op name with the
13023 * specified argtypes.
13025 switch (operform->oprkind)
13027 case 'b':
13028 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
13029 true, -1);
13030 break;
13031 case 'l':
13032 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
13033 true, -1);
13034 break;
13035 default:
13036 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
13037 p_result = NULL; /* keep compiler quiet */
13038 break;
13041 if (p_result != NULL && oprid(p_result) == operid)
13042 nspname = NULL;
13043 else
13045 nspname = get_namespace_name_or_temp(operform->oprnamespace);
13046 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
13049 appendStringInfoString(&buf, oprname);
13051 if (nspname)
13052 appendStringInfoChar(&buf, ')');
13054 if (p_result != NULL)
13055 ReleaseSysCache(p_result);
13057 ReleaseSysCache(opertup);
13059 return buf.data;
13063 * generate_operator_clause --- generate a binary-operator WHERE clause
13065 * This is used for internally-generated-and-executed SQL queries, where
13066 * precision is essential and readability is secondary. The basic
13067 * requirement is to append "leftop op rightop" to buf, where leftop and
13068 * rightop are given as strings and are assumed to yield types leftoptype
13069 * and rightoptype; the operator is identified by OID. The complexity
13070 * comes from needing to be sure that the parser will select the desired
13071 * operator when the query is parsed. We always name the operator using
13072 * OPERATOR(schema.op) syntax, so as to avoid search-path uncertainties.
13073 * We have to emit casts too, if either input isn't already the input type
13074 * of the operator; else we are at the mercy of the parser's heuristics for
13075 * ambiguous-operator resolution. The caller must ensure that leftop and
13076 * rightop are suitable arguments for a cast operation; it's best to insert
13077 * parentheses if they aren't just variables or parameters.
13079 void
13080 generate_operator_clause(StringInfo buf,
13081 const char *leftop, Oid leftoptype,
13082 Oid opoid,
13083 const char *rightop, Oid rightoptype)
13085 HeapTuple opertup;
13086 Form_pg_operator operform;
13087 char *oprname;
13088 char *nspname;
13090 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
13091 if (!HeapTupleIsValid(opertup))
13092 elog(ERROR, "cache lookup failed for operator %u", opoid);
13093 operform = (Form_pg_operator) GETSTRUCT(opertup);
13094 Assert(operform->oprkind == 'b');
13095 oprname = NameStr(operform->oprname);
13097 nspname = get_namespace_name(operform->oprnamespace);
13099 appendStringInfoString(buf, leftop);
13100 if (leftoptype != operform->oprleft)
13101 add_cast_to(buf, operform->oprleft);
13102 appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
13103 appendStringInfoString(buf, oprname);
13104 appendStringInfo(buf, ") %s", rightop);
13105 if (rightoptype != operform->oprright)
13106 add_cast_to(buf, operform->oprright);
13108 ReleaseSysCache(opertup);
13112 * Add a cast specification to buf. We spell out the type name the hard way,
13113 * intentionally not using format_type_be(). This is to avoid corner cases
13114 * for CHARACTER, BIT, and perhaps other types, where specifying the type
13115 * using SQL-standard syntax results in undesirable data truncation. By
13116 * doing it this way we can be certain that the cast will have default (-1)
13117 * target typmod.
13119 static void
13120 add_cast_to(StringInfo buf, Oid typid)
13122 HeapTuple typetup;
13123 Form_pg_type typform;
13124 char *typname;
13125 char *nspname;
13127 typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
13128 if (!HeapTupleIsValid(typetup))
13129 elog(ERROR, "cache lookup failed for type %u", typid);
13130 typform = (Form_pg_type) GETSTRUCT(typetup);
13132 typname = NameStr(typform->typname);
13133 nspname = get_namespace_name_or_temp(typform->typnamespace);
13135 appendStringInfo(buf, "::%s.%s",
13136 quote_identifier(nspname), quote_identifier(typname));
13138 ReleaseSysCache(typetup);
13142 * generate_qualified_type_name
13143 * Compute the name to display for a type specified by OID
13145 * This is different from format_type_be() in that we unconditionally
13146 * schema-qualify the name. That also means no special syntax for
13147 * SQL-standard type names ... although in current usage, this should
13148 * only get used for domains, so such cases wouldn't occur anyway.
13150 static char *
13151 generate_qualified_type_name(Oid typid)
13153 HeapTuple tp;
13154 Form_pg_type typtup;
13155 char *typname;
13156 char *nspname;
13157 char *result;
13159 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
13160 if (!HeapTupleIsValid(tp))
13161 elog(ERROR, "cache lookup failed for type %u", typid);
13162 typtup = (Form_pg_type) GETSTRUCT(tp);
13163 typname = NameStr(typtup->typname);
13165 nspname = get_namespace_name_or_temp(typtup->typnamespace);
13166 if (!nspname)
13167 elog(ERROR, "cache lookup failed for namespace %u",
13168 typtup->typnamespace);
13170 result = quote_qualified_identifier(nspname, typname);
13172 ReleaseSysCache(tp);
13174 return result;
13178 * generate_collation_name
13179 * Compute the name to display for a collation specified by OID
13181 * The result includes all necessary quoting and schema-prefixing.
13183 char *
13184 generate_collation_name(Oid collid)
13186 HeapTuple tp;
13187 Form_pg_collation colltup;
13188 char *collname;
13189 char *nspname;
13190 char *result;
13192 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
13193 if (!HeapTupleIsValid(tp))
13194 elog(ERROR, "cache lookup failed for collation %u", collid);
13195 colltup = (Form_pg_collation) GETSTRUCT(tp);
13196 collname = NameStr(colltup->collname);
13198 if (!CollationIsVisible(collid))
13199 nspname = get_namespace_name_or_temp(colltup->collnamespace);
13200 else
13201 nspname = NULL;
13203 result = quote_qualified_identifier(nspname, collname);
13205 ReleaseSysCache(tp);
13207 return result;
13211 * Given a C string, produce a TEXT datum.
13213 * We assume that the input was palloc'd and may be freed.
13215 static text *
13216 string_to_text(char *str)
13218 text *result;
13220 result = cstring_to_text(str);
13221 pfree(str);
13222 return result;
13226 * Generate a C string representing a relation options from text[] datum.
13228 static void
13229 get_reloptions(StringInfo buf, Datum reloptions)
13231 Datum *options;
13232 int noptions;
13233 int i;
13235 deconstruct_array_builtin(DatumGetArrayTypeP(reloptions), TEXTOID,
13236 &options, NULL, &noptions);
13238 for (i = 0; i < noptions; i++)
13240 char *option = TextDatumGetCString(options[i]);
13241 char *name;
13242 char *separator;
13243 char *value;
13246 * Each array element should have the form name=value. If the "=" is
13247 * missing for some reason, treat it like an empty value.
13249 name = option;
13250 separator = strchr(option, '=');
13251 if (separator)
13253 *separator = '\0';
13254 value = separator + 1;
13256 else
13257 value = "";
13259 if (i > 0)
13260 appendStringInfoString(buf, ", ");
13261 appendStringInfo(buf, "%s=", quote_identifier(name));
13264 * In general we need to quote the value; but to avoid unnecessary
13265 * clutter, do not quote if it is an identifier that would not need
13266 * quoting. (We could also allow numbers, but that is a bit trickier
13267 * than it looks --- for example, are leading zeroes significant? We
13268 * don't want to assume very much here about what custom reloptions
13269 * might mean.)
13271 if (quote_identifier(value) == value)
13272 appendStringInfoString(buf, value);
13273 else
13274 simple_quote_literal(buf, value);
13276 pfree(option);
13281 * Generate a C string representing a relation's reloptions, or NULL if none.
13283 static char *
13284 flatten_reloptions(Oid relid)
13286 char *result = NULL;
13287 HeapTuple tuple;
13288 Datum reloptions;
13289 bool isnull;
13291 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
13292 if (!HeapTupleIsValid(tuple))
13293 elog(ERROR, "cache lookup failed for relation %u", relid);
13295 reloptions = SysCacheGetAttr(RELOID, tuple,
13296 Anum_pg_class_reloptions, &isnull);
13297 if (!isnull)
13299 StringInfoData buf;
13301 initStringInfo(&buf);
13302 get_reloptions(&buf, reloptions);
13304 result = buf.data;
13307 ReleaseSysCache(tuple);
13309 return result;
13313 * get_range_partbound_string
13314 * A C string representation of one range partition bound
13316 char *
13317 get_range_partbound_string(List *bound_datums)
13319 deparse_context context;
13320 StringInfo buf = makeStringInfo();
13321 ListCell *cell;
13322 char *sep;
13324 memset(&context, 0, sizeof(deparse_context));
13325 context.buf = buf;
13327 appendStringInfoChar(buf, '(');
13328 sep = "";
13329 foreach(cell, bound_datums)
13331 PartitionRangeDatum *datum =
13332 lfirst_node(PartitionRangeDatum, cell);
13334 appendStringInfoString(buf, sep);
13335 if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
13336 appendStringInfoString(buf, "MINVALUE");
13337 else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
13338 appendStringInfoString(buf, "MAXVALUE");
13339 else
13341 Const *val = castNode(Const, datum->value);
13343 get_const_expr(val, &context, -1);
13345 sep = ", ";
13347 appendStringInfoChar(buf, ')');
13349 return buf->data;