Update copyright for 2022
[pgsql.git] / src / backend / utils / adt / ruleutils.c
blob039f897331c863336fa3f7f397810c5913522920
1 /*-------------------------------------------------------------------------
3 * ruleutils.c
4 * Functions to convert stored expressions/querytrees back to
5 * source text
7 * Portions Copyright (c) 1996-2022, 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/sysattr.h"
26 #include "access/table.h"
27 #include "catalog/pg_aggregate.h"
28 #include "catalog/pg_am.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_collation.h"
31 #include "catalog/pg_constraint.h"
32 #include "catalog/pg_depend.h"
33 #include "catalog/pg_language.h"
34 #include "catalog/pg_opclass.h"
35 #include "catalog/pg_operator.h"
36 #include "catalog/pg_partitioned_table.h"
37 #include "catalog/pg_proc.h"
38 #include "catalog/pg_statistic_ext.h"
39 #include "catalog/pg_trigger.h"
40 #include "catalog/pg_type.h"
41 #include "commands/defrem.h"
42 #include "commands/tablespace.h"
43 #include "common/keywords.h"
44 #include "executor/spi.h"
45 #include "funcapi.h"
46 #include "mb/pg_wchar.h"
47 #include "miscadmin.h"
48 #include "nodes/makefuncs.h"
49 #include "nodes/nodeFuncs.h"
50 #include "nodes/pathnodes.h"
51 #include "optimizer/optimizer.h"
52 #include "parser/parse_agg.h"
53 #include "parser/parse_func.h"
54 #include "parser/parse_node.h"
55 #include "parser/parse_oper.h"
56 #include "parser/parser.h"
57 #include "parser/parsetree.h"
58 #include "rewrite/rewriteHandler.h"
59 #include "rewrite/rewriteManip.h"
60 #include "rewrite/rewriteSupport.h"
61 #include "utils/array.h"
62 #include "utils/builtins.h"
63 #include "utils/fmgroids.h"
64 #include "utils/guc.h"
65 #include "utils/hsearch.h"
66 #include "utils/lsyscache.h"
67 #include "utils/partcache.h"
68 #include "utils/rel.h"
69 #include "utils/ruleutils.h"
70 #include "utils/snapmgr.h"
71 #include "utils/syscache.h"
72 #include "utils/typcache.h"
73 #include "utils/varlena.h"
74 #include "utils/xml.h"
76 /* ----------
77 * Pretty formatting constants
78 * ----------
81 /* Indent counts */
82 #define PRETTYINDENT_STD 8
83 #define PRETTYINDENT_JOIN 4
84 #define PRETTYINDENT_VAR 4
86 #define PRETTYINDENT_LIMIT 40 /* wrap limit */
88 /* Pretty flags */
89 #define PRETTYFLAG_PAREN 0x0001
90 #define PRETTYFLAG_INDENT 0x0002
91 #define PRETTYFLAG_SCHEMA 0x0004
93 /* Default line length for pretty-print wrapping: 0 means wrap always */
94 #define WRAP_COLUMN_DEFAULT 0
96 /* macros to test if pretty action needed */
97 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
98 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
99 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
102 /* ----------
103 * Local data types
104 * ----------
107 /* Context info needed for invoking a recursive querytree display routine */
108 typedef struct
110 StringInfo buf; /* output buffer to append to */
111 List *namespaces; /* List of deparse_namespace nodes */
112 List *windowClause; /* Current query level's WINDOW clause */
113 List *windowTList; /* targetlist for resolving WINDOW clause */
114 int prettyFlags; /* enabling of pretty-print functions */
115 int wrapColumn; /* max line length, or -1 for no limit */
116 int indentLevel; /* current indent level for pretty-print */
117 bool varprefix; /* true to print prefixes on Vars */
118 ParseExprKind special_exprkind; /* set only for exprkinds needing special
119 * handling */
120 Bitmapset *appendparents; /* if not null, map child Vars of these relids
121 * back to the parent rel */
122 } deparse_context;
125 * Each level of query context around a subtree needs a level of Var namespace.
126 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
127 * the current context's namespaces list.
129 * rtable is the list of actual RTEs from the Query or PlannedStmt.
130 * rtable_names holds the alias name to be used for each RTE (either a C
131 * string, or NULL for nameless RTEs such as unnamed joins).
132 * rtable_columns holds the column alias names to be used for each RTE.
134 * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
135 * in the PlannedStmt case).
136 * ctes is a list of CommonTableExpr nodes (only used in the Query case).
137 * appendrels, if not null (it's only used in the PlannedStmt case), is an
138 * array of AppendRelInfo nodes, indexed by child relid. We use that to map
139 * child-table Vars to their inheritance parents.
141 * In some cases we need to make names of merged JOIN USING columns unique
142 * across the whole query, not only per-RTE. If so, unique_using is true
143 * and using_names is a list of C strings representing names already assigned
144 * to USING columns.
146 * When deparsing plan trees, there is always just a single item in the
147 * deparse_namespace list (since a plan tree never contains Vars with
148 * varlevelsup > 0). We store the Plan node that is the immediate
149 * parent of the expression to be deparsed, as well as a list of that
150 * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
151 * as well as their targetlists, and the index tlist if the current plan node
152 * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
153 * from the current Plan node, but it seems notationally clearer to set them
154 * up as separate fields.)
156 typedef struct
158 List *rtable; /* List of RangeTblEntry nodes */
159 List *rtable_names; /* Parallel list of names for RTEs */
160 List *rtable_columns; /* Parallel list of deparse_columns structs */
161 List *subplans; /* List of Plan trees for SubPlans */
162 List *ctes; /* List of CommonTableExpr nodes */
163 AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
164 /* Workspace for column alias assignment: */
165 bool unique_using; /* Are we making USING names globally unique */
166 List *using_names; /* List of assigned names for USING columns */
167 /* Remaining fields are used only when deparsing a Plan tree: */
168 Plan *plan; /* immediate parent of current expression */
169 List *ancestors; /* ancestors of plan */
170 Plan *outer_plan; /* outer subnode, or NULL if none */
171 Plan *inner_plan; /* inner subnode, or NULL if none */
172 List *outer_tlist; /* referent for OUTER_VAR Vars */
173 List *inner_tlist; /* referent for INNER_VAR Vars */
174 List *index_tlist; /* referent for INDEX_VAR Vars */
175 /* Special namespace representing a function signature: */
176 char *funcname;
177 int numargs;
178 char **argnames;
179 } deparse_namespace;
182 * Per-relation data about column alias names.
184 * Selecting aliases is unreasonably complicated because of the need to dump
185 * rules/views whose underlying tables may have had columns added, deleted, or
186 * renamed since the query was parsed. We must nonetheless print the rule/view
187 * in a form that can be reloaded and will produce the same results as before.
189 * For each RTE used in the query, we must assign column aliases that are
190 * unique within that RTE. SQL does not require this of the original query,
191 * but due to factors such as *-expansion we need to be able to uniquely
192 * reference every column in a decompiled query. As long as we qualify all
193 * column references, per-RTE uniqueness is sufficient for that.
195 * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
196 * since they just inherit column names from their input RTEs, and we can't
197 * rename the columns at the join level. Most of the time this isn't an issue
198 * because we don't need to reference the join's output columns as such; we
199 * can reference the input columns instead. That approach can fail for merged
200 * JOIN USING columns, however, so when we have one of those in an unnamed
201 * join, we have to make that column's alias globally unique across the whole
202 * query to ensure it can be referenced unambiguously.
204 * Another problem is that a JOIN USING clause requires the columns to be
205 * merged to have the same aliases in both input RTEs, and that no other
206 * columns in those RTEs or their children conflict with the USING names.
207 * To handle that, we do USING-column alias assignment in a recursive
208 * traversal of the query's jointree. When descending through a JOIN with
209 * USING, we preassign the USING column names to the child columns, overriding
210 * other rules for column alias assignment. We also mark each RTE with a list
211 * of all USING column names selected for joins containing that RTE, so that
212 * when we assign other columns' aliases later, we can avoid conflicts.
214 * Another problem is that if a JOIN's input tables have had columns added or
215 * deleted since the query was parsed, we must generate a column alias list
216 * for the join that matches the current set of input columns --- otherwise, a
217 * change in the number of columns in the left input would throw off matching
218 * of aliases to columns of the right input. Thus, positions in the printable
219 * column alias list are not necessarily one-for-one with varattnos of the
220 * JOIN, so we need a separate new_colnames[] array for printing purposes.
222 typedef struct
225 * colnames is an array containing column aliases to use for columns that
226 * existed when the query was parsed. Dropped columns have NULL entries.
227 * This array can be directly indexed by varattno to get a Var's name.
229 * Non-NULL entries are guaranteed unique within the RTE, *except* when
230 * this is for an unnamed JOIN RTE. In that case we merely copy up names
231 * from the two input RTEs.
233 * During the recursive descent in set_using_names(), forcible assignment
234 * of a child RTE's column name is represented by pre-setting that element
235 * of the child's colnames array. So at that stage, NULL entries in this
236 * array just mean that no name has been preassigned, not necessarily that
237 * the column is dropped.
239 int num_cols; /* length of colnames[] array */
240 char **colnames; /* array of C strings and NULLs */
243 * new_colnames is an array containing column aliases to use for columns
244 * that would exist if the query was re-parsed against the current
245 * definitions of its base tables. This is what to print as the column
246 * alias list for the RTE. This array does not include dropped columns,
247 * but it will include columns added since original parsing. Indexes in
248 * it therefore have little to do with current varattno values. As above,
249 * entries are unique unless this is for an unnamed JOIN RTE. (In such an
250 * RTE, we never actually print this array, but we must compute it anyway
251 * for possible use in computing column names of upper joins.) The
252 * parallel array is_new_col marks which of these columns are new since
253 * original parsing. Entries with is_new_col false must match the
254 * non-NULL colnames entries one-for-one.
256 int num_new_cols; /* length of new_colnames[] array */
257 char **new_colnames; /* array of C strings */
258 bool *is_new_col; /* array of bool flags */
260 /* This flag tells whether we should actually print a column alias list */
261 bool printaliases;
263 /* This list has all names used as USING names in joins above this RTE */
264 List *parentUsing; /* names assigned to parent merged columns */
267 * If this struct is for a JOIN RTE, we fill these fields during the
268 * set_using_names() pass to describe its relationship to its child RTEs.
270 * leftattnos and rightattnos are arrays with one entry per existing
271 * output column of the join (hence, indexable by join varattno). For a
272 * simple reference to a column of the left child, leftattnos[i] is the
273 * child RTE's attno and rightattnos[i] is zero; and conversely for a
274 * column of the right child. But for merged columns produced by JOIN
275 * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
276 * Note that a simple reference might be to a child RTE column that's been
277 * dropped; but that's OK since the column could not be used in the query.
279 * If it's a JOIN USING, usingNames holds the alias names selected for the
280 * merged columns (these might be different from the original USING list,
281 * if we had to modify names to achieve uniqueness).
283 int leftrti; /* rangetable index of left child */
284 int rightrti; /* rangetable index of right child */
285 int *leftattnos; /* left-child varattnos of join cols, or 0 */
286 int *rightattnos; /* right-child varattnos of join cols, or 0 */
287 List *usingNames; /* names assigned to merged columns */
288 } deparse_columns;
290 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
291 #define deparse_columns_fetch(rangetable_index, dpns) \
292 ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
295 * Entry in set_rtable_names' hash table
297 typedef struct
299 char name[NAMEDATALEN]; /* Hash key --- must be first */
300 int counter; /* Largest addition used so far for name */
301 } NameHashEntry;
303 /* Callback signature for resolve_special_varno() */
304 typedef void (*rsv_callback) (Node *node, deparse_context *context,
305 void *callback_arg);
308 /* ----------
309 * Global data
310 * ----------
312 static SPIPlanPtr plan_getrulebyoid = NULL;
313 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
314 static SPIPlanPtr plan_getviewrule = NULL;
315 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
317 /* GUC parameters */
318 bool quote_all_identifiers = false;
321 /* ----------
322 * Local functions
324 * Most of these functions used to use fixed-size buffers to build their
325 * results. Now, they take an (already initialized) StringInfo object
326 * as a parameter, and append their text output to its contents.
327 * ----------
329 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
330 bool forceprefix, bool showimplicit,
331 int prettyFlags, int startIndent);
332 static char *pg_get_viewdef_worker(Oid viewoid,
333 int prettyFlags, int wrapColumn);
334 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
335 static int decompile_column_index_array(Datum column_index_array, Oid relId,
336 StringInfo buf);
337 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
338 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
339 const Oid *excludeOps,
340 bool attrsOnly, bool keysOnly,
341 bool showTblSpc, bool inherits,
342 int prettyFlags, bool missing_ok);
343 static char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
344 bool missing_ok);
345 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
346 bool attrsOnly, bool missing_ok);
347 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
348 int prettyFlags, bool missing_ok);
349 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
350 int prettyFlags);
351 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
352 bool print_table_args, bool print_defaults);
353 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
354 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
355 static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
356 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
357 Bitmapset *rels_used);
358 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
359 List *parent_namespaces);
360 static void set_simple_column_names(deparse_namespace *dpns);
361 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
362 static void set_using_names(deparse_namespace *dpns, Node *jtnode,
363 List *parentUsing);
364 static void set_relation_column_names(deparse_namespace *dpns,
365 RangeTblEntry *rte,
366 deparse_columns *colinfo);
367 static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
368 deparse_columns *colinfo);
369 static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
370 deparse_columns *colinfo);
371 static char *make_colname_unique(char *colname, deparse_namespace *dpns,
372 deparse_columns *colinfo);
373 static void expand_colnames_array_to(deparse_columns *colinfo, int n);
374 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
375 deparse_columns *colinfo);
376 static char *get_rtable_name(int rtindex, deparse_context *context);
377 static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
378 static Plan *find_recursive_union(deparse_namespace *dpns,
379 WorkTableScan *wtscan);
380 static void push_child_plan(deparse_namespace *dpns, Plan *plan,
381 deparse_namespace *save_dpns);
382 static void pop_child_plan(deparse_namespace *dpns,
383 deparse_namespace *save_dpns);
384 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
385 deparse_namespace *save_dpns);
386 static void pop_ancestor_plan(deparse_namespace *dpns,
387 deparse_namespace *save_dpns);
388 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
389 int prettyFlags);
390 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
391 int prettyFlags, int wrapColumn);
392 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
393 TupleDesc resultDesc,
394 int prettyFlags, int wrapColumn, int startIndent);
395 static void get_values_def(List *values_lists, deparse_context *context);
396 static void get_with_clause(Query *query, deparse_context *context);
397 static void get_select_query_def(Query *query, deparse_context *context,
398 TupleDesc resultDesc);
399 static void get_insert_query_def(Query *query, deparse_context *context);
400 static void get_update_query_def(Query *query, deparse_context *context);
401 static void get_update_query_targetlist_def(Query *query, List *targetList,
402 deparse_context *context,
403 RangeTblEntry *rte);
404 static void get_delete_query_def(Query *query, deparse_context *context);
405 static void get_utility_query_def(Query *query, deparse_context *context);
406 static void get_basic_select_query(Query *query, deparse_context *context,
407 TupleDesc resultDesc);
408 static void get_target_list(List *targetList, deparse_context *context,
409 TupleDesc resultDesc);
410 static void get_setop_query(Node *setOp, Query *query,
411 deparse_context *context,
412 TupleDesc resultDesc);
413 static Node *get_rule_sortgroupclause(Index ref, List *tlist,
414 bool force_colno,
415 deparse_context *context);
416 static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
417 bool omit_parens, deparse_context *context);
418 static void get_rule_orderby(List *orderList, List *targetList,
419 bool force_colno, deparse_context *context);
420 static void get_rule_windowclause(Query *query, deparse_context *context);
421 static void get_rule_windowspec(WindowClause *wc, List *targetList,
422 deparse_context *context);
423 static char *get_variable(Var *var, int levelsup, bool istoplevel,
424 deparse_context *context);
425 static void get_special_variable(Node *node, deparse_context *context,
426 void *callback_arg);
427 static void resolve_special_varno(Node *node, deparse_context *context,
428 rsv_callback callback, void *callback_arg);
429 static Node *find_param_referent(Param *param, deparse_context *context,
430 deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
431 static void get_parameter(Param *param, deparse_context *context);
432 static const char *get_simple_binary_op_name(OpExpr *expr);
433 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
434 static void appendContextKeyword(deparse_context *context, const char *str,
435 int indentBefore, int indentAfter, int indentPlus);
436 static void removeStringInfoSpaces(StringInfo str);
437 static void get_rule_expr(Node *node, deparse_context *context,
438 bool showimplicit);
439 static void get_rule_expr_toplevel(Node *node, deparse_context *context,
440 bool showimplicit);
441 static void get_rule_expr_funccall(Node *node, deparse_context *context,
442 bool showimplicit);
443 static bool looks_like_function(Node *node);
444 static void get_oper_expr(OpExpr *expr, deparse_context *context);
445 static void get_func_expr(FuncExpr *expr, deparse_context *context,
446 bool showimplicit);
447 static void get_agg_expr(Aggref *aggref, deparse_context *context,
448 Aggref *original_aggref);
449 static void get_agg_combine_expr(Node *node, deparse_context *context,
450 void *callback_arg);
451 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
452 static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
453 static void get_coercion_expr(Node *arg, deparse_context *context,
454 Oid resulttype, int32 resulttypmod,
455 Node *parentNode);
456 static void get_const_expr(Const *constval, deparse_context *context,
457 int showtype);
458 static void get_const_collation(Const *constval, deparse_context *context);
459 static void simple_quote_literal(StringInfo buf, const char *val);
460 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
461 static void get_tablefunc(TableFunc *tf, deparse_context *context,
462 bool showimplicit);
463 static void get_from_clause(Query *query, const char *prefix,
464 deparse_context *context);
465 static void get_from_clause_item(Node *jtnode, Query *query,
466 deparse_context *context);
467 static void get_column_alias_list(deparse_columns *colinfo,
468 deparse_context *context);
469 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
470 deparse_columns *colinfo,
471 deparse_context *context);
472 static void get_tablesample_def(TableSampleClause *tablesample,
473 deparse_context *context);
474 static void get_opclass_name(Oid opclass, Oid actual_datatype,
475 StringInfo buf);
476 static Node *processIndirection(Node *node, deparse_context *context);
477 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
478 static char *get_relation_name(Oid relid);
479 static char *generate_relation_name(Oid relid, List *namespaces);
480 static char *generate_qualified_relation_name(Oid relid);
481 static char *generate_function_name(Oid funcid, int nargs,
482 List *argnames, Oid *argtypes,
483 bool has_variadic, bool *use_variadic_p,
484 ParseExprKind special_exprkind);
485 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
486 static void add_cast_to(StringInfo buf, Oid typid);
487 static char *generate_qualified_type_name(Oid typid);
488 static text *string_to_text(char *str);
489 static char *flatten_reloptions(Oid relid);
490 static void get_reloptions(StringInfo buf, Datum reloptions);
492 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
495 /* ----------
496 * pg_get_ruledef - Do it all and return a text
497 * that could be used as a statement
498 * to recreate the rule
499 * ----------
501 Datum
502 pg_get_ruledef(PG_FUNCTION_ARGS)
504 Oid ruleoid = PG_GETARG_OID(0);
505 int prettyFlags;
506 char *res;
508 prettyFlags = PRETTYFLAG_INDENT;
510 res = pg_get_ruledef_worker(ruleoid, prettyFlags);
512 if (res == NULL)
513 PG_RETURN_NULL();
515 PG_RETURN_TEXT_P(string_to_text(res));
519 Datum
520 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
522 Oid ruleoid = PG_GETARG_OID(0);
523 bool pretty = PG_GETARG_BOOL(1);
524 int prettyFlags;
525 char *res;
527 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
529 res = pg_get_ruledef_worker(ruleoid, prettyFlags);
531 if (res == NULL)
532 PG_RETURN_NULL();
534 PG_RETURN_TEXT_P(string_to_text(res));
538 static char *
539 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
541 Datum args[1];
542 char nulls[1];
543 int spirc;
544 HeapTuple ruletup;
545 TupleDesc rulettc;
546 StringInfoData buf;
549 * Do this first so that string is alloc'd in outer context not SPI's.
551 initStringInfo(&buf);
554 * Connect to SPI manager
556 if (SPI_connect() != SPI_OK_CONNECT)
557 elog(ERROR, "SPI_connect failed");
560 * On the first call prepare the plan to lookup pg_rewrite. We read
561 * pg_rewrite over the SPI manager instead of using the syscache to be
562 * checked for read access on pg_rewrite.
564 if (plan_getrulebyoid == NULL)
566 Oid argtypes[1];
567 SPIPlanPtr plan;
569 argtypes[0] = OIDOID;
570 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
571 if (plan == NULL)
572 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
573 SPI_keepplan(plan);
574 plan_getrulebyoid = plan;
578 * Get the pg_rewrite tuple for this rule
580 args[0] = ObjectIdGetDatum(ruleoid);
581 nulls[0] = ' ';
582 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
583 if (spirc != SPI_OK_SELECT)
584 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
585 if (SPI_processed != 1)
588 * There is no tuple data available here, just keep the output buffer
589 * empty.
592 else
595 * Get the rule's definition and put it into executor's memory
597 ruletup = SPI_tuptable->vals[0];
598 rulettc = SPI_tuptable->tupdesc;
599 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
603 * Disconnect from SPI manager
605 if (SPI_finish() != SPI_OK_FINISH)
606 elog(ERROR, "SPI_finish failed");
608 if (buf.len == 0)
609 return NULL;
611 return buf.data;
615 /* ----------
616 * pg_get_viewdef - Mainly the same thing, but we
617 * only return the SELECT part of a view
618 * ----------
620 Datum
621 pg_get_viewdef(PG_FUNCTION_ARGS)
623 /* By OID */
624 Oid viewoid = PG_GETARG_OID(0);
625 int prettyFlags;
626 char *res;
628 prettyFlags = PRETTYFLAG_INDENT;
630 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
632 if (res == NULL)
633 PG_RETURN_NULL();
635 PG_RETURN_TEXT_P(string_to_text(res));
639 Datum
640 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
642 /* By OID */
643 Oid viewoid = PG_GETARG_OID(0);
644 bool pretty = PG_GETARG_BOOL(1);
645 int prettyFlags;
646 char *res;
648 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
650 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
652 if (res == NULL)
653 PG_RETURN_NULL();
655 PG_RETURN_TEXT_P(string_to_text(res));
658 Datum
659 pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
661 /* By OID */
662 Oid viewoid = PG_GETARG_OID(0);
663 int wrap = PG_GETARG_INT32(1);
664 int prettyFlags;
665 char *res;
667 /* calling this implies we want pretty printing */
668 prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA;
670 res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
672 if (res == NULL)
673 PG_RETURN_NULL();
675 PG_RETURN_TEXT_P(string_to_text(res));
678 Datum
679 pg_get_viewdef_name(PG_FUNCTION_ARGS)
681 /* By qualified name */
682 text *viewname = PG_GETARG_TEXT_PP(0);
683 int prettyFlags;
684 RangeVar *viewrel;
685 Oid viewoid;
686 char *res;
688 prettyFlags = PRETTYFLAG_INDENT;
690 /* Look up view name. Can't lock it - we might not have privileges. */
691 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
692 viewoid = RangeVarGetRelid(viewrel, NoLock, false);
694 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
696 if (res == NULL)
697 PG_RETURN_NULL();
699 PG_RETURN_TEXT_P(string_to_text(res));
703 Datum
704 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
706 /* By qualified name */
707 text *viewname = PG_GETARG_TEXT_PP(0);
708 bool pretty = PG_GETARG_BOOL(1);
709 int prettyFlags;
710 RangeVar *viewrel;
711 Oid viewoid;
712 char *res;
714 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
716 /* Look up view name. Can't lock it - we might not have privileges. */
717 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
718 viewoid = RangeVarGetRelid(viewrel, NoLock, false);
720 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
722 if (res == NULL)
723 PG_RETURN_NULL();
725 PG_RETURN_TEXT_P(string_to_text(res));
729 * Common code for by-OID and by-name variants of pg_get_viewdef
731 static char *
732 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
734 Datum args[2];
735 char nulls[2];
736 int spirc;
737 HeapTuple ruletup;
738 TupleDesc rulettc;
739 StringInfoData buf;
742 * Do this first so that string is alloc'd in outer context not SPI's.
744 initStringInfo(&buf);
747 * Connect to SPI manager
749 if (SPI_connect() != SPI_OK_CONNECT)
750 elog(ERROR, "SPI_connect failed");
753 * On the first call prepare the plan to lookup pg_rewrite. We read
754 * pg_rewrite over the SPI manager instead of using the syscache to be
755 * checked for read access on pg_rewrite.
757 if (plan_getviewrule == NULL)
759 Oid argtypes[2];
760 SPIPlanPtr plan;
762 argtypes[0] = OIDOID;
763 argtypes[1] = NAMEOID;
764 plan = SPI_prepare(query_getviewrule, 2, argtypes);
765 if (plan == NULL)
766 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
767 SPI_keepplan(plan);
768 plan_getviewrule = plan;
772 * Get the pg_rewrite tuple for the view's SELECT rule
774 args[0] = ObjectIdGetDatum(viewoid);
775 args[1] = DirectFunctionCall1(namein, CStringGetDatum(ViewSelectRuleName));
776 nulls[0] = ' ';
777 nulls[1] = ' ';
778 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
779 if (spirc != SPI_OK_SELECT)
780 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
781 if (SPI_processed != 1)
784 * There is no tuple data available here, just keep the output buffer
785 * empty.
788 else
791 * Get the rule's definition and put it into executor's memory
793 ruletup = SPI_tuptable->vals[0];
794 rulettc = SPI_tuptable->tupdesc;
795 make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
799 * Disconnect from SPI manager
801 if (SPI_finish() != SPI_OK_FINISH)
802 elog(ERROR, "SPI_finish failed");
804 if (buf.len == 0)
805 return NULL;
807 return buf.data;
810 /* ----------
811 * pg_get_triggerdef - Get the definition of a trigger
812 * ----------
814 Datum
815 pg_get_triggerdef(PG_FUNCTION_ARGS)
817 Oid trigid = PG_GETARG_OID(0);
818 char *res;
820 res = pg_get_triggerdef_worker(trigid, false);
822 if (res == NULL)
823 PG_RETURN_NULL();
825 PG_RETURN_TEXT_P(string_to_text(res));
828 Datum
829 pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
831 Oid trigid = PG_GETARG_OID(0);
832 bool pretty = PG_GETARG_BOOL(1);
833 char *res;
835 res = pg_get_triggerdef_worker(trigid, pretty);
837 if (res == NULL)
838 PG_RETURN_NULL();
840 PG_RETURN_TEXT_P(string_to_text(res));
843 static char *
844 pg_get_triggerdef_worker(Oid trigid, bool pretty)
846 HeapTuple ht_trig;
847 Form_pg_trigger trigrec;
848 StringInfoData buf;
849 Relation tgrel;
850 ScanKeyData skey[1];
851 SysScanDesc tgscan;
852 int findx = 0;
853 char *tgname;
854 char *tgoldtable;
855 char *tgnewtable;
856 Datum value;
857 bool isnull;
860 * Fetch the pg_trigger tuple by the Oid of the trigger
862 tgrel = table_open(TriggerRelationId, AccessShareLock);
864 ScanKeyInit(&skey[0],
865 Anum_pg_trigger_oid,
866 BTEqualStrategyNumber, F_OIDEQ,
867 ObjectIdGetDatum(trigid));
869 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
870 NULL, 1, skey);
872 ht_trig = systable_getnext(tgscan);
874 if (!HeapTupleIsValid(ht_trig))
876 systable_endscan(tgscan);
877 table_close(tgrel, AccessShareLock);
878 return NULL;
881 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
884 * Start the trigger definition. Note that the trigger's name should never
885 * be schema-qualified, but the trigger rel's name may be.
887 initStringInfo(&buf);
889 tgname = NameStr(trigrec->tgname);
890 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
891 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
892 quote_identifier(tgname));
894 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
895 appendStringInfoString(&buf, "BEFORE");
896 else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
897 appendStringInfoString(&buf, "AFTER");
898 else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
899 appendStringInfoString(&buf, "INSTEAD OF");
900 else
901 elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
903 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
905 appendStringInfoString(&buf, " INSERT");
906 findx++;
908 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
910 if (findx > 0)
911 appendStringInfoString(&buf, " OR DELETE");
912 else
913 appendStringInfoString(&buf, " DELETE");
914 findx++;
916 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
918 if (findx > 0)
919 appendStringInfoString(&buf, " OR UPDATE");
920 else
921 appendStringInfoString(&buf, " UPDATE");
922 findx++;
923 /* tgattr is first var-width field, so OK to access directly */
924 if (trigrec->tgattr.dim1 > 0)
926 int i;
928 appendStringInfoString(&buf, " OF ");
929 for (i = 0; i < trigrec->tgattr.dim1; i++)
931 char *attname;
933 if (i > 0)
934 appendStringInfoString(&buf, ", ");
935 attname = get_attname(trigrec->tgrelid,
936 trigrec->tgattr.values[i], false);
937 appendStringInfoString(&buf, quote_identifier(attname));
941 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
943 if (findx > 0)
944 appendStringInfoString(&buf, " OR TRUNCATE");
945 else
946 appendStringInfoString(&buf, " TRUNCATE");
947 findx++;
951 * In non-pretty mode, always schema-qualify the target table name for
952 * safety. In pretty mode, schema-qualify only if not visible.
954 appendStringInfo(&buf, " ON %s ",
955 pretty ?
956 generate_relation_name(trigrec->tgrelid, NIL) :
957 generate_qualified_relation_name(trigrec->tgrelid));
959 if (OidIsValid(trigrec->tgconstraint))
961 if (OidIsValid(trigrec->tgconstrrelid))
962 appendStringInfo(&buf, "FROM %s ",
963 generate_relation_name(trigrec->tgconstrrelid, NIL));
964 if (!trigrec->tgdeferrable)
965 appendStringInfoString(&buf, "NOT ");
966 appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
967 if (trigrec->tginitdeferred)
968 appendStringInfoString(&buf, "DEFERRED ");
969 else
970 appendStringInfoString(&buf, "IMMEDIATE ");
973 value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
974 tgrel->rd_att, &isnull);
975 if (!isnull)
976 tgoldtable = NameStr(*DatumGetName(value));
977 else
978 tgoldtable = NULL;
979 value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
980 tgrel->rd_att, &isnull);
981 if (!isnull)
982 tgnewtable = NameStr(*DatumGetName(value));
983 else
984 tgnewtable = NULL;
985 if (tgoldtable != NULL || tgnewtable != NULL)
987 appendStringInfoString(&buf, "REFERENCING ");
988 if (tgoldtable != NULL)
989 appendStringInfo(&buf, "OLD TABLE AS %s ",
990 quote_identifier(tgoldtable));
991 if (tgnewtable != NULL)
992 appendStringInfo(&buf, "NEW TABLE AS %s ",
993 quote_identifier(tgnewtable));
996 if (TRIGGER_FOR_ROW(trigrec->tgtype))
997 appendStringInfoString(&buf, "FOR EACH ROW ");
998 else
999 appendStringInfoString(&buf, "FOR EACH STATEMENT ");
1001 /* If the trigger has a WHEN qualification, add that */
1002 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
1003 tgrel->rd_att, &isnull);
1004 if (!isnull)
1006 Node *qual;
1007 char relkind;
1008 deparse_context context;
1009 deparse_namespace dpns;
1010 RangeTblEntry *oldrte;
1011 RangeTblEntry *newrte;
1013 appendStringInfoString(&buf, "WHEN (");
1015 qual = stringToNode(TextDatumGetCString(value));
1017 relkind = get_rel_relkind(trigrec->tgrelid);
1019 /* Build minimal OLD and NEW RTEs for the rel */
1020 oldrte = makeNode(RangeTblEntry);
1021 oldrte->rtekind = RTE_RELATION;
1022 oldrte->relid = trigrec->tgrelid;
1023 oldrte->relkind = relkind;
1024 oldrte->rellockmode = AccessShareLock;
1025 oldrte->alias = makeAlias("old", NIL);
1026 oldrte->eref = oldrte->alias;
1027 oldrte->lateral = false;
1028 oldrte->inh = false;
1029 oldrte->inFromCl = true;
1031 newrte = makeNode(RangeTblEntry);
1032 newrte->rtekind = RTE_RELATION;
1033 newrte->relid = trigrec->tgrelid;
1034 newrte->relkind = relkind;
1035 newrte->rellockmode = AccessShareLock;
1036 newrte->alias = makeAlias("new", NIL);
1037 newrte->eref = newrte->alias;
1038 newrte->lateral = false;
1039 newrte->inh = false;
1040 newrte->inFromCl = true;
1042 /* Build two-element rtable */
1043 memset(&dpns, 0, sizeof(dpns));
1044 dpns.rtable = list_make2(oldrte, newrte);
1045 dpns.subplans = NIL;
1046 dpns.ctes = NIL;
1047 dpns.appendrels = NULL;
1048 set_rtable_names(&dpns, NIL, NULL);
1049 set_simple_column_names(&dpns);
1051 /* Set up context with one-deep namespace stack */
1052 context.buf = &buf;
1053 context.namespaces = list_make1(&dpns);
1054 context.windowClause = NIL;
1055 context.windowTList = NIL;
1056 context.varprefix = true;
1057 context.prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
1058 context.wrapColumn = WRAP_COLUMN_DEFAULT;
1059 context.indentLevel = PRETTYINDENT_STD;
1060 context.special_exprkind = EXPR_KIND_NONE;
1061 context.appendparents = NULL;
1063 get_rule_expr(qual, &context, false);
1065 appendStringInfoString(&buf, ") ");
1068 appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
1069 generate_function_name(trigrec->tgfoid, 0,
1070 NIL, NULL,
1071 false, NULL, EXPR_KIND_NONE));
1073 if (trigrec->tgnargs > 0)
1075 char *p;
1076 int i;
1078 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
1079 tgrel->rd_att, &isnull);
1080 if (isnull)
1081 elog(ERROR, "tgargs is null for trigger %u", trigid);
1082 p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
1083 for (i = 0; i < trigrec->tgnargs; i++)
1085 if (i > 0)
1086 appendStringInfoString(&buf, ", ");
1087 simple_quote_literal(&buf, p);
1088 /* advance p to next string embedded in tgargs */
1089 while (*p)
1090 p++;
1091 p++;
1095 /* We deliberately do not put semi-colon at end */
1096 appendStringInfoChar(&buf, ')');
1098 /* Clean up */
1099 systable_endscan(tgscan);
1101 table_close(tgrel, AccessShareLock);
1103 return buf.data;
1106 /* ----------
1107 * pg_get_indexdef - Get the definition of an index
1109 * In the extended version, there is a colno argument as well as pretty bool.
1110 * if colno == 0, we want a complete index definition.
1111 * if colno > 0, we only want the Nth index key's variable or expression.
1113 * Note that the SQL-function versions of this omit any info about the
1114 * index tablespace; this is intentional because pg_dump wants it that way.
1115 * However pg_get_indexdef_string() includes the index tablespace.
1116 * ----------
1118 Datum
1119 pg_get_indexdef(PG_FUNCTION_ARGS)
1121 Oid indexrelid = PG_GETARG_OID(0);
1122 int prettyFlags;
1123 char *res;
1125 prettyFlags = PRETTYFLAG_INDENT;
1127 res = pg_get_indexdef_worker(indexrelid, 0, NULL,
1128 false, false,
1129 false, false,
1130 prettyFlags, true);
1132 if (res == NULL)
1133 PG_RETURN_NULL();
1135 PG_RETURN_TEXT_P(string_to_text(res));
1138 Datum
1139 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
1141 Oid indexrelid = PG_GETARG_OID(0);
1142 int32 colno = PG_GETARG_INT32(1);
1143 bool pretty = PG_GETARG_BOOL(2);
1144 int prettyFlags;
1145 char *res;
1147 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
1149 res = pg_get_indexdef_worker(indexrelid, colno, NULL,
1150 colno != 0, false,
1151 false, false,
1152 prettyFlags, true);
1154 if (res == NULL)
1155 PG_RETURN_NULL();
1157 PG_RETURN_TEXT_P(string_to_text(res));
1161 * Internal version for use by ALTER TABLE.
1162 * Includes a tablespace clause in the result.
1163 * Returns a palloc'd C string; no pretty-printing.
1165 char *
1166 pg_get_indexdef_string(Oid indexrelid)
1168 return pg_get_indexdef_worker(indexrelid, 0, NULL,
1169 false, false,
1170 true, true,
1171 0, false);
1174 /* Internal version that just reports the key-column definitions */
1175 char *
1176 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
1178 int prettyFlags;
1180 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
1182 return pg_get_indexdef_worker(indexrelid, 0, NULL,
1183 true, true,
1184 false, false,
1185 prettyFlags, false);
1189 * Internal workhorse to decompile an index definition.
1191 * This is now used for exclusion constraints as well: if excludeOps is not
1192 * NULL then it points to an array of exclusion operator OIDs.
1194 static char *
1195 pg_get_indexdef_worker(Oid indexrelid, int colno,
1196 const Oid *excludeOps,
1197 bool attrsOnly, bool keysOnly,
1198 bool showTblSpc, bool inherits,
1199 int prettyFlags, bool missing_ok)
1201 /* might want a separate isConstraint parameter later */
1202 bool isConstraint = (excludeOps != NULL);
1203 HeapTuple ht_idx;
1204 HeapTuple ht_idxrel;
1205 HeapTuple ht_am;
1206 Form_pg_index idxrec;
1207 Form_pg_class idxrelrec;
1208 Form_pg_am amrec;
1209 IndexAmRoutine *amroutine;
1210 List *indexprs;
1211 ListCell *indexpr_item;
1212 List *context;
1213 Oid indrelid;
1214 int keyno;
1215 Datum indcollDatum;
1216 Datum indclassDatum;
1217 Datum indoptionDatum;
1218 bool isnull;
1219 oidvector *indcollation;
1220 oidvector *indclass;
1221 int2vector *indoption;
1222 StringInfoData buf;
1223 char *str;
1224 char *sep;
1227 * Fetch the pg_index tuple by the Oid of the index
1229 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
1230 if (!HeapTupleIsValid(ht_idx))
1232 if (missing_ok)
1233 return NULL;
1234 elog(ERROR, "cache lookup failed for index %u", indexrelid);
1236 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1238 indrelid = idxrec->indrelid;
1239 Assert(indexrelid == idxrec->indexrelid);
1241 /* Must get indcollation, indclass, and indoption the hard way */
1242 indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1243 Anum_pg_index_indcollation, &isnull);
1244 Assert(!isnull);
1245 indcollation = (oidvector *) DatumGetPointer(indcollDatum);
1247 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1248 Anum_pg_index_indclass, &isnull);
1249 Assert(!isnull);
1250 indclass = (oidvector *) DatumGetPointer(indclassDatum);
1252 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1253 Anum_pg_index_indoption, &isnull);
1254 Assert(!isnull);
1255 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1258 * Fetch the pg_class tuple of the index relation
1260 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
1261 if (!HeapTupleIsValid(ht_idxrel))
1262 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
1263 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1266 * Fetch the pg_am tuple of the index' access method
1268 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1269 if (!HeapTupleIsValid(ht_am))
1270 elog(ERROR, "cache lookup failed for access method %u",
1271 idxrelrec->relam);
1272 amrec = (Form_pg_am) GETSTRUCT(ht_am);
1274 /* Fetch the index AM's API struct */
1275 amroutine = GetIndexAmRoutine(amrec->amhandler);
1278 * Get the index expressions, if any. (NOTE: we do not use the relcache
1279 * versions of the expressions and predicate, because we want to display
1280 * non-const-folded expressions.)
1282 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
1284 Datum exprsDatum;
1285 bool isnull;
1286 char *exprsString;
1288 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1289 Anum_pg_index_indexprs, &isnull);
1290 Assert(!isnull);
1291 exprsString = TextDatumGetCString(exprsDatum);
1292 indexprs = (List *) stringToNode(exprsString);
1293 pfree(exprsString);
1295 else
1296 indexprs = NIL;
1298 indexpr_item = list_head(indexprs);
1300 context = deparse_context_for(get_relation_name(indrelid), indrelid);
1303 * Start the index definition. Note that the index's name should never be
1304 * schema-qualified, but the indexed rel's name may be.
1306 initStringInfo(&buf);
1308 if (!attrsOnly)
1310 if (!isConstraint)
1311 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
1312 idxrec->indisunique ? "UNIQUE " : "",
1313 quote_identifier(NameStr(idxrelrec->relname)),
1314 idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
1315 && !inherits ? "ONLY " : "",
1316 (prettyFlags & PRETTYFLAG_SCHEMA) ?
1317 generate_relation_name(indrelid, NIL) :
1318 generate_qualified_relation_name(indrelid),
1319 quote_identifier(NameStr(amrec->amname)));
1320 else /* currently, must be EXCLUDE constraint */
1321 appendStringInfo(&buf, "EXCLUDE USING %s (",
1322 quote_identifier(NameStr(amrec->amname)));
1326 * Report the indexed attributes
1328 sep = "";
1329 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1331 AttrNumber attnum = idxrec->indkey.values[keyno];
1332 Oid keycoltype;
1333 Oid keycolcollation;
1336 * Ignore non-key attributes if told to.
1338 if (keysOnly && keyno >= idxrec->indnkeyatts)
1339 break;
1341 /* Otherwise, print INCLUDE to divide key and non-key attrs. */
1342 if (!colno && keyno == idxrec->indnkeyatts)
1344 appendStringInfoString(&buf, ") INCLUDE (");
1345 sep = "";
1348 if (!colno)
1349 appendStringInfoString(&buf, sep);
1350 sep = ", ";
1352 if (attnum != 0)
1354 /* Simple index column */
1355 char *attname;
1356 int32 keycoltypmod;
1358 attname = get_attname(indrelid, attnum, false);
1359 if (!colno || colno == keyno + 1)
1360 appendStringInfoString(&buf, quote_identifier(attname));
1361 get_atttypetypmodcoll(indrelid, attnum,
1362 &keycoltype, &keycoltypmod,
1363 &keycolcollation);
1365 else
1367 /* expressional index */
1368 Node *indexkey;
1370 if (indexpr_item == NULL)
1371 elog(ERROR, "too few entries in indexprs list");
1372 indexkey = (Node *) lfirst(indexpr_item);
1373 indexpr_item = lnext(indexprs, indexpr_item);
1374 /* Deparse */
1375 str = deparse_expression_pretty(indexkey, context, false, false,
1376 prettyFlags, 0);
1377 if (!colno || colno == keyno + 1)
1379 /* Need parens if it's not a bare function call */
1380 if (looks_like_function(indexkey))
1381 appendStringInfoString(&buf, str);
1382 else
1383 appendStringInfo(&buf, "(%s)", str);
1385 keycoltype = exprType(indexkey);
1386 keycolcollation = exprCollation(indexkey);
1389 /* Print additional decoration for (selected) key columns */
1390 if (!attrsOnly && keyno < idxrec->indnkeyatts &&
1391 (!colno || colno == keyno + 1))
1393 int16 opt = indoption->values[keyno];
1394 Oid indcoll = indcollation->values[keyno];
1395 Datum attoptions = get_attoptions(indexrelid, keyno + 1);
1396 bool has_options = attoptions != (Datum) 0;
1398 /* Add collation, if not default for column */
1399 if (OidIsValid(indcoll) && indcoll != keycolcollation)
1400 appendStringInfo(&buf, " COLLATE %s",
1401 generate_collation_name((indcoll)));
1403 /* Add the operator class name, if not default */
1404 get_opclass_name(indclass->values[keyno],
1405 has_options ? InvalidOid : keycoltype, &buf);
1407 if (has_options)
1409 appendStringInfoString(&buf, " (");
1410 get_reloptions(&buf, attoptions);
1411 appendStringInfoChar(&buf, ')');
1414 /* Add options if relevant */
1415 if (amroutine->amcanorder)
1417 /* if it supports sort ordering, report DESC and NULLS opts */
1418 if (opt & INDOPTION_DESC)
1420 appendStringInfoString(&buf, " DESC");
1421 /* NULLS FIRST is the default in this case */
1422 if (!(opt & INDOPTION_NULLS_FIRST))
1423 appendStringInfoString(&buf, " NULLS LAST");
1425 else
1427 if (opt & INDOPTION_NULLS_FIRST)
1428 appendStringInfoString(&buf, " NULLS FIRST");
1432 /* Add the exclusion operator if relevant */
1433 if (excludeOps != NULL)
1434 appendStringInfo(&buf, " WITH %s",
1435 generate_operator_name(excludeOps[keyno],
1436 keycoltype,
1437 keycoltype));
1441 if (!attrsOnly)
1443 appendStringInfoChar(&buf, ')');
1446 * If it has options, append "WITH (options)"
1448 str = flatten_reloptions(indexrelid);
1449 if (str)
1451 appendStringInfo(&buf, " WITH (%s)", str);
1452 pfree(str);
1456 * Print tablespace, but only if requested
1458 if (showTblSpc)
1460 Oid tblspc;
1462 tblspc = get_rel_tablespace(indexrelid);
1463 if (OidIsValid(tblspc))
1465 if (isConstraint)
1466 appendStringInfoString(&buf, " USING INDEX");
1467 appendStringInfo(&buf, " TABLESPACE %s",
1468 quote_identifier(get_tablespace_name(tblspc)));
1473 * If it's a partial index, decompile and append the predicate
1475 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
1477 Node *node;
1478 Datum predDatum;
1479 bool isnull;
1480 char *predString;
1482 /* Convert text string to node tree */
1483 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1484 Anum_pg_index_indpred, &isnull);
1485 Assert(!isnull);
1486 predString = TextDatumGetCString(predDatum);
1487 node = (Node *) stringToNode(predString);
1488 pfree(predString);
1490 /* Deparse */
1491 str = deparse_expression_pretty(node, context, false, false,
1492 prettyFlags, 0);
1493 if (isConstraint)
1494 appendStringInfo(&buf, " WHERE (%s)", str);
1495 else
1496 appendStringInfo(&buf, " WHERE %s", str);
1500 /* Clean up */
1501 ReleaseSysCache(ht_idx);
1502 ReleaseSysCache(ht_idxrel);
1503 ReleaseSysCache(ht_am);
1505 return buf.data;
1509 * pg_get_statisticsobjdef
1510 * Get the definition of an extended statistics object
1512 Datum
1513 pg_get_statisticsobjdef(PG_FUNCTION_ARGS)
1515 Oid statextid = PG_GETARG_OID(0);
1516 char *res;
1518 res = pg_get_statisticsobj_worker(statextid, false, true);
1520 if (res == NULL)
1521 PG_RETURN_NULL();
1523 PG_RETURN_TEXT_P(string_to_text(res));
1527 * Internal version for use by ALTER TABLE.
1528 * Includes a tablespace clause in the result.
1529 * Returns a palloc'd C string; no pretty-printing.
1531 char *
1532 pg_get_statisticsobjdef_string(Oid statextid)
1534 return pg_get_statisticsobj_worker(statextid, false, false);
1538 * pg_get_statisticsobjdef_columns
1539 * Get columns and expressions for an extended statistics object
1541 Datum
1542 pg_get_statisticsobjdef_columns(PG_FUNCTION_ARGS)
1544 Oid statextid = PG_GETARG_OID(0);
1545 char *res;
1547 res = pg_get_statisticsobj_worker(statextid, true, true);
1549 if (res == NULL)
1550 PG_RETURN_NULL();
1552 PG_RETURN_TEXT_P(string_to_text(res));
1556 * Internal workhorse to decompile an extended statistics object.
1558 static char *
1559 pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
1561 Form_pg_statistic_ext statextrec;
1562 HeapTuple statexttup;
1563 StringInfoData buf;
1564 int colno;
1565 char *nsp;
1566 ArrayType *arr;
1567 char *enabled;
1568 Datum datum;
1569 bool isnull;
1570 bool ndistinct_enabled;
1571 bool dependencies_enabled;
1572 bool mcv_enabled;
1573 int i;
1574 List *context;
1575 ListCell *lc;
1576 List *exprs = NIL;
1577 bool has_exprs;
1578 int ncolumns;
1580 statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1582 if (!HeapTupleIsValid(statexttup))
1584 if (missing_ok)
1585 return NULL;
1586 elog(ERROR, "cache lookup failed for statistics object %u", statextid);
1589 /* has the statistics expressions? */
1590 has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1592 statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1595 * Get the statistics expressions, if any. (NOTE: we do not use the
1596 * relcache versions of the expressions, because we want to display
1597 * non-const-folded expressions.)
1599 if (has_exprs)
1601 Datum exprsDatum;
1602 bool isnull;
1603 char *exprsString;
1605 exprsDatum = SysCacheGetAttr(STATEXTOID, statexttup,
1606 Anum_pg_statistic_ext_stxexprs, &isnull);
1607 Assert(!isnull);
1608 exprsString = TextDatumGetCString(exprsDatum);
1609 exprs = (List *) stringToNode(exprsString);
1610 pfree(exprsString);
1612 else
1613 exprs = NIL;
1615 /* count the number of columns (attributes and expressions) */
1616 ncolumns = statextrec->stxkeys.dim1 + list_length(exprs);
1618 initStringInfo(&buf);
1620 if (!columns_only)
1622 nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
1623 appendStringInfo(&buf, "CREATE STATISTICS %s",
1624 quote_qualified_identifier(nsp,
1625 NameStr(statextrec->stxname)));
1628 * Decode the stxkind column so that we know which stats types to
1629 * print.
1631 datum = SysCacheGetAttr(STATEXTOID, statexttup,
1632 Anum_pg_statistic_ext_stxkind, &isnull);
1633 Assert(!isnull);
1634 arr = DatumGetArrayTypeP(datum);
1635 if (ARR_NDIM(arr) != 1 ||
1636 ARR_HASNULL(arr) ||
1637 ARR_ELEMTYPE(arr) != CHAROID)
1638 elog(ERROR, "stxkind is not a 1-D char array");
1639 enabled = (char *) ARR_DATA_PTR(arr);
1641 ndistinct_enabled = false;
1642 dependencies_enabled = false;
1643 mcv_enabled = false;
1645 for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1647 if (enabled[i] == STATS_EXT_NDISTINCT)
1648 ndistinct_enabled = true;
1649 else if (enabled[i] == STATS_EXT_DEPENDENCIES)
1650 dependencies_enabled = true;
1651 else if (enabled[i] == STATS_EXT_MCV)
1652 mcv_enabled = true;
1654 /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */
1658 * If any option is disabled, then we'll need to append the types
1659 * clause to show which options are enabled. We omit the types clause
1660 * on purpose when all options are enabled, so a pg_dump/pg_restore
1661 * will create all statistics types on a newer postgres version, if
1662 * the statistics had all options enabled on the original version.
1664 * But if the statistics is defined on just a single column, it has to
1665 * be an expression statistics. In that case we don't need to specify
1666 * kinds.
1668 if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) &&
1669 (ncolumns > 1))
1671 bool gotone = false;
1673 appendStringInfoString(&buf, " (");
1675 if (ndistinct_enabled)
1677 appendStringInfoString(&buf, "ndistinct");
1678 gotone = true;
1681 if (dependencies_enabled)
1683 appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
1684 gotone = true;
1687 if (mcv_enabled)
1688 appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
1690 appendStringInfoChar(&buf, ')');
1693 appendStringInfoString(&buf, " ON ");
1696 /* decode simple column references */
1697 for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
1699 AttrNumber attnum = statextrec->stxkeys.values[colno];
1700 char *attname;
1702 if (colno > 0)
1703 appendStringInfoString(&buf, ", ");
1705 attname = get_attname(statextrec->stxrelid, attnum, false);
1707 appendStringInfoString(&buf, quote_identifier(attname));
1710 context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1711 statextrec->stxrelid);
1713 foreach(lc, exprs)
1715 Node *expr = (Node *) lfirst(lc);
1716 char *str;
1717 int prettyFlags = PRETTYFLAG_PAREN;
1719 str = deparse_expression_pretty(expr, context, false, false,
1720 prettyFlags, 0);
1722 if (colno > 0)
1723 appendStringInfoString(&buf, ", ");
1725 /* Need parens if it's not a bare function call */
1726 if (looks_like_function(expr))
1727 appendStringInfoString(&buf, str);
1728 else
1729 appendStringInfo(&buf, "(%s)", str);
1731 colno++;
1734 if (!columns_only)
1735 appendStringInfo(&buf, " FROM %s",
1736 generate_relation_name(statextrec->stxrelid, NIL));
1738 ReleaseSysCache(statexttup);
1740 return buf.data;
1744 * Generate text array of expressions for statistics object.
1746 Datum
1747 pg_get_statisticsobjdef_expressions(PG_FUNCTION_ARGS)
1749 Oid statextid = PG_GETARG_OID(0);
1750 Form_pg_statistic_ext statextrec;
1751 HeapTuple statexttup;
1752 Datum datum;
1753 bool isnull;
1754 List *context;
1755 ListCell *lc;
1756 List *exprs = NIL;
1757 bool has_exprs;
1758 char *tmp;
1759 ArrayBuildState *astate = NULL;
1761 statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
1763 if (!HeapTupleIsValid(statexttup))
1764 PG_RETURN_NULL();
1766 /* Does the stats object have expressions? */
1767 has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
1769 /* no expressions? we're done */
1770 if (!has_exprs)
1772 ReleaseSysCache(statexttup);
1773 PG_RETURN_NULL();
1776 statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
1779 * Get the statistics expressions, and deparse them into text values.
1781 datum = SysCacheGetAttr(STATEXTOID, statexttup,
1782 Anum_pg_statistic_ext_stxexprs, &isnull);
1784 Assert(!isnull);
1785 tmp = TextDatumGetCString(datum);
1786 exprs = (List *) stringToNode(tmp);
1787 pfree(tmp);
1789 context = deparse_context_for(get_relation_name(statextrec->stxrelid),
1790 statextrec->stxrelid);
1792 foreach(lc, exprs)
1794 Node *expr = (Node *) lfirst(lc);
1795 char *str;
1796 int prettyFlags = PRETTYFLAG_INDENT;
1798 str = deparse_expression_pretty(expr, context, false, false,
1799 prettyFlags, 0);
1801 astate = accumArrayResult(astate,
1802 PointerGetDatum(cstring_to_text(str)),
1803 false,
1804 TEXTOID,
1805 CurrentMemoryContext);
1808 ReleaseSysCache(statexttup);
1810 PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
1814 * pg_get_partkeydef
1816 * Returns the partition key specification, ie, the following:
1818 * PARTITION BY { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
1820 Datum
1821 pg_get_partkeydef(PG_FUNCTION_ARGS)
1823 Oid relid = PG_GETARG_OID(0);
1824 char *res;
1826 res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
1828 if (res == NULL)
1829 PG_RETURN_NULL();
1831 PG_RETURN_TEXT_P(string_to_text(res));
1834 /* Internal version that just reports the column definitions */
1835 char *
1836 pg_get_partkeydef_columns(Oid relid, bool pretty)
1838 int prettyFlags;
1840 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
1842 return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
1846 * Internal workhorse to decompile a partition key definition.
1848 static char *
1849 pg_get_partkeydef_worker(Oid relid, int prettyFlags,
1850 bool attrsOnly, bool missing_ok)
1852 Form_pg_partitioned_table form;
1853 HeapTuple tuple;
1854 oidvector *partclass;
1855 oidvector *partcollation;
1856 List *partexprs;
1857 ListCell *partexpr_item;
1858 List *context;
1859 Datum datum;
1860 bool isnull;
1861 StringInfoData buf;
1862 int keyno;
1863 char *str;
1864 char *sep;
1866 tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
1867 if (!HeapTupleIsValid(tuple))
1869 if (missing_ok)
1870 return NULL;
1871 elog(ERROR, "cache lookup failed for partition key of %u", relid);
1874 form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
1876 Assert(form->partrelid == relid);
1878 /* Must get partclass and partcollation the hard way */
1879 datum = SysCacheGetAttr(PARTRELID, tuple,
1880 Anum_pg_partitioned_table_partclass, &isnull);
1881 Assert(!isnull);
1882 partclass = (oidvector *) DatumGetPointer(datum);
1884 datum = SysCacheGetAttr(PARTRELID, tuple,
1885 Anum_pg_partitioned_table_partcollation, &isnull);
1886 Assert(!isnull);
1887 partcollation = (oidvector *) DatumGetPointer(datum);
1891 * Get the expressions, if any. (NOTE: we do not use the relcache
1892 * versions of the expressions, because we want to display
1893 * non-const-folded expressions.)
1895 if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
1897 Datum exprsDatum;
1898 bool isnull;
1899 char *exprsString;
1901 exprsDatum = SysCacheGetAttr(PARTRELID, tuple,
1902 Anum_pg_partitioned_table_partexprs, &isnull);
1903 Assert(!isnull);
1904 exprsString = TextDatumGetCString(exprsDatum);
1905 partexprs = (List *) stringToNode(exprsString);
1907 if (!IsA(partexprs, List))
1908 elog(ERROR, "unexpected node type found in partexprs: %d",
1909 (int) nodeTag(partexprs));
1911 pfree(exprsString);
1913 else
1914 partexprs = NIL;
1916 partexpr_item = list_head(partexprs);
1917 context = deparse_context_for(get_relation_name(relid), relid);
1919 initStringInfo(&buf);
1921 switch (form->partstrat)
1923 case PARTITION_STRATEGY_HASH:
1924 if (!attrsOnly)
1925 appendStringInfoString(&buf, "HASH");
1926 break;
1927 case PARTITION_STRATEGY_LIST:
1928 if (!attrsOnly)
1929 appendStringInfoString(&buf, "LIST");
1930 break;
1931 case PARTITION_STRATEGY_RANGE:
1932 if (!attrsOnly)
1933 appendStringInfoString(&buf, "RANGE");
1934 break;
1935 default:
1936 elog(ERROR, "unexpected partition strategy: %d",
1937 (int) form->partstrat);
1940 if (!attrsOnly)
1941 appendStringInfoString(&buf, " (");
1942 sep = "";
1943 for (keyno = 0; keyno < form->partnatts; keyno++)
1945 AttrNumber attnum = form->partattrs.values[keyno];
1946 Oid keycoltype;
1947 Oid keycolcollation;
1948 Oid partcoll;
1950 appendStringInfoString(&buf, sep);
1951 sep = ", ";
1952 if (attnum != 0)
1954 /* Simple attribute reference */
1955 char *attname;
1956 int32 keycoltypmod;
1958 attname = get_attname(relid, attnum, false);
1959 appendStringInfoString(&buf, quote_identifier(attname));
1960 get_atttypetypmodcoll(relid, attnum,
1961 &keycoltype, &keycoltypmod,
1962 &keycolcollation);
1964 else
1966 /* Expression */
1967 Node *partkey;
1969 if (partexpr_item == NULL)
1970 elog(ERROR, "too few entries in partexprs list");
1971 partkey = (Node *) lfirst(partexpr_item);
1972 partexpr_item = lnext(partexprs, partexpr_item);
1974 /* Deparse */
1975 str = deparse_expression_pretty(partkey, context, false, false,
1976 prettyFlags, 0);
1977 /* Need parens if it's not a bare function call */
1978 if (looks_like_function(partkey))
1979 appendStringInfoString(&buf, str);
1980 else
1981 appendStringInfo(&buf, "(%s)", str);
1983 keycoltype = exprType(partkey);
1984 keycolcollation = exprCollation(partkey);
1987 /* Add collation, if not default for column */
1988 partcoll = partcollation->values[keyno];
1989 if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
1990 appendStringInfo(&buf, " COLLATE %s",
1991 generate_collation_name((partcoll)));
1993 /* Add the operator class name, if not default */
1994 if (!attrsOnly)
1995 get_opclass_name(partclass->values[keyno], keycoltype, &buf);
1998 if (!attrsOnly)
1999 appendStringInfoChar(&buf, ')');
2001 /* Clean up */
2002 ReleaseSysCache(tuple);
2004 return buf.data;
2008 * pg_get_partition_constraintdef
2010 * Returns partition constraint expression as a string for the input relation
2012 Datum
2013 pg_get_partition_constraintdef(PG_FUNCTION_ARGS)
2015 Oid relationId = PG_GETARG_OID(0);
2016 Expr *constr_expr;
2017 int prettyFlags;
2018 List *context;
2019 char *consrc;
2021 constr_expr = get_partition_qual_relid(relationId);
2023 /* Quick exit if no partition constraint */
2024 if (constr_expr == NULL)
2025 PG_RETURN_NULL();
2028 * Deparse and return the constraint expression.
2030 prettyFlags = PRETTYFLAG_INDENT;
2031 context = deparse_context_for(get_relation_name(relationId), relationId);
2032 consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
2033 false, prettyFlags, 0);
2035 PG_RETURN_TEXT_P(string_to_text(consrc));
2039 * pg_get_partconstrdef_string
2041 * Returns the partition constraint as a C-string for the input relation, with
2042 * the given alias. No pretty-printing.
2044 char *
2045 pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
2047 Expr *constr_expr;
2048 List *context;
2050 constr_expr = get_partition_qual_relid(partitionId);
2051 context = deparse_context_for(aliasname, partitionId);
2053 return deparse_expression((Node *) constr_expr, context, true, false);
2057 * pg_get_constraintdef
2059 * Returns the definition for the constraint, ie, everything that needs to
2060 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
2062 Datum
2063 pg_get_constraintdef(PG_FUNCTION_ARGS)
2065 Oid constraintId = PG_GETARG_OID(0);
2066 int prettyFlags;
2067 char *res;
2069 prettyFlags = PRETTYFLAG_INDENT;
2071 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2073 if (res == NULL)
2074 PG_RETURN_NULL();
2076 PG_RETURN_TEXT_P(string_to_text(res));
2079 Datum
2080 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
2082 Oid constraintId = PG_GETARG_OID(0);
2083 bool pretty = PG_GETARG_BOOL(1);
2084 int prettyFlags;
2085 char *res;
2087 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
2089 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
2091 if (res == NULL)
2092 PG_RETURN_NULL();
2094 PG_RETURN_TEXT_P(string_to_text(res));
2098 * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
2100 char *
2101 pg_get_constraintdef_command(Oid constraintId)
2103 return pg_get_constraintdef_worker(constraintId, true, 0, false);
2107 * As of 9.4, we now use an MVCC snapshot for this.
2109 static char *
2110 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
2111 int prettyFlags, bool missing_ok)
2113 HeapTuple tup;
2114 Form_pg_constraint conForm;
2115 StringInfoData buf;
2116 SysScanDesc scandesc;
2117 ScanKeyData scankey[1];
2118 Snapshot snapshot = RegisterSnapshot(GetTransactionSnapshot());
2119 Relation relation = table_open(ConstraintRelationId, AccessShareLock);
2121 ScanKeyInit(&scankey[0],
2122 Anum_pg_constraint_oid,
2123 BTEqualStrategyNumber, F_OIDEQ,
2124 ObjectIdGetDatum(constraintId));
2126 scandesc = systable_beginscan(relation,
2127 ConstraintOidIndexId,
2128 true,
2129 snapshot,
2131 scankey);
2134 * We later use the tuple with SysCacheGetAttr() as if we had obtained it
2135 * via SearchSysCache, which works fine.
2137 tup = systable_getnext(scandesc);
2139 UnregisterSnapshot(snapshot);
2141 if (!HeapTupleIsValid(tup))
2143 if (missing_ok)
2145 systable_endscan(scandesc);
2146 table_close(relation, AccessShareLock);
2147 return NULL;
2149 elog(ERROR, "could not find tuple for constraint %u", constraintId);
2152 conForm = (Form_pg_constraint) GETSTRUCT(tup);
2154 initStringInfo(&buf);
2156 if (fullCommand)
2158 if (OidIsValid(conForm->conrelid))
2161 * Currently, callers want ALTER TABLE (without ONLY) for CHECK
2162 * constraints, and other types of constraints don't inherit
2163 * anyway so it doesn't matter whether we say ONLY or not. Someday
2164 * we might need to let callers specify whether to put ONLY in the
2165 * command.
2167 appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
2168 generate_qualified_relation_name(conForm->conrelid),
2169 quote_identifier(NameStr(conForm->conname)));
2171 else
2173 /* Must be a domain constraint */
2174 Assert(OidIsValid(conForm->contypid));
2175 appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
2176 generate_qualified_type_name(conForm->contypid),
2177 quote_identifier(NameStr(conForm->conname)));
2181 switch (conForm->contype)
2183 case CONSTRAINT_FOREIGN:
2185 Datum val;
2186 bool isnull;
2187 const char *string;
2189 /* Start off the constraint definition */
2190 appendStringInfoString(&buf, "FOREIGN KEY (");
2192 /* Fetch and build referencing-column list */
2193 val = SysCacheGetAttr(CONSTROID, tup,
2194 Anum_pg_constraint_conkey, &isnull);
2195 if (isnull)
2196 elog(ERROR, "null conkey for constraint %u",
2197 constraintId);
2199 decompile_column_index_array(val, conForm->conrelid, &buf);
2201 /* add foreign relation name */
2202 appendStringInfo(&buf, ") REFERENCES %s(",
2203 generate_relation_name(conForm->confrelid,
2204 NIL));
2206 /* Fetch and build referenced-column list */
2207 val = SysCacheGetAttr(CONSTROID, tup,
2208 Anum_pg_constraint_confkey, &isnull);
2209 if (isnull)
2210 elog(ERROR, "null confkey for constraint %u",
2211 constraintId);
2213 decompile_column_index_array(val, conForm->confrelid, &buf);
2215 appendStringInfoChar(&buf, ')');
2217 /* Add match type */
2218 switch (conForm->confmatchtype)
2220 case FKCONSTR_MATCH_FULL:
2221 string = " MATCH FULL";
2222 break;
2223 case FKCONSTR_MATCH_PARTIAL:
2224 string = " MATCH PARTIAL";
2225 break;
2226 case FKCONSTR_MATCH_SIMPLE:
2227 string = "";
2228 break;
2229 default:
2230 elog(ERROR, "unrecognized confmatchtype: %d",
2231 conForm->confmatchtype);
2232 string = ""; /* keep compiler quiet */
2233 break;
2235 appendStringInfoString(&buf, string);
2237 /* Add ON UPDATE and ON DELETE clauses, if needed */
2238 switch (conForm->confupdtype)
2240 case FKCONSTR_ACTION_NOACTION:
2241 string = NULL; /* suppress default */
2242 break;
2243 case FKCONSTR_ACTION_RESTRICT:
2244 string = "RESTRICT";
2245 break;
2246 case FKCONSTR_ACTION_CASCADE:
2247 string = "CASCADE";
2248 break;
2249 case FKCONSTR_ACTION_SETNULL:
2250 string = "SET NULL";
2251 break;
2252 case FKCONSTR_ACTION_SETDEFAULT:
2253 string = "SET DEFAULT";
2254 break;
2255 default:
2256 elog(ERROR, "unrecognized confupdtype: %d",
2257 conForm->confupdtype);
2258 string = NULL; /* keep compiler quiet */
2259 break;
2261 if (string)
2262 appendStringInfo(&buf, " ON UPDATE %s", string);
2264 switch (conForm->confdeltype)
2266 case FKCONSTR_ACTION_NOACTION:
2267 string = NULL; /* suppress default */
2268 break;
2269 case FKCONSTR_ACTION_RESTRICT:
2270 string = "RESTRICT";
2271 break;
2272 case FKCONSTR_ACTION_CASCADE:
2273 string = "CASCADE";
2274 break;
2275 case FKCONSTR_ACTION_SETNULL:
2276 string = "SET NULL";
2277 break;
2278 case FKCONSTR_ACTION_SETDEFAULT:
2279 string = "SET DEFAULT";
2280 break;
2281 default:
2282 elog(ERROR, "unrecognized confdeltype: %d",
2283 conForm->confdeltype);
2284 string = NULL; /* keep compiler quiet */
2285 break;
2287 if (string)
2288 appendStringInfo(&buf, " ON DELETE %s", string);
2290 /* Add columns specified to SET NULL or SET DEFAULT if provided. */
2291 val = SysCacheGetAttr(CONSTROID, tup,
2292 Anum_pg_constraint_confdelsetcols, &isnull);
2293 if (!isnull)
2295 appendStringInfo(&buf, " (");
2296 decompile_column_index_array(val, conForm->conrelid, &buf);
2297 appendStringInfo(&buf, ")");
2300 break;
2302 case CONSTRAINT_PRIMARY:
2303 case CONSTRAINT_UNIQUE:
2305 Datum val;
2306 bool isnull;
2307 Oid indexId;
2308 int keyatts;
2309 HeapTuple indtup;
2311 /* Start off the constraint definition */
2312 if (conForm->contype == CONSTRAINT_PRIMARY)
2313 appendStringInfoString(&buf, "PRIMARY KEY (");
2314 else
2315 appendStringInfoString(&buf, "UNIQUE (");
2317 /* Fetch and build target column list */
2318 val = SysCacheGetAttr(CONSTROID, tup,
2319 Anum_pg_constraint_conkey, &isnull);
2320 if (isnull)
2321 elog(ERROR, "null conkey for constraint %u",
2322 constraintId);
2324 keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
2326 appendStringInfoChar(&buf, ')');
2328 indexId = conForm->conindid;
2330 /* Build including column list (from pg_index.indkeys) */
2331 indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
2332 if (!HeapTupleIsValid(indtup))
2333 elog(ERROR, "cache lookup failed for index %u", indexId);
2334 val = SysCacheGetAttr(INDEXRELID, indtup,
2335 Anum_pg_index_indnatts, &isnull);
2336 if (isnull)
2337 elog(ERROR, "null indnatts for index %u", indexId);
2338 if (DatumGetInt32(val) > keyatts)
2340 Datum cols;
2341 Datum *keys;
2342 int nKeys;
2343 int j;
2345 appendStringInfoString(&buf, " INCLUDE (");
2347 cols = SysCacheGetAttr(INDEXRELID, indtup,
2348 Anum_pg_index_indkey, &isnull);
2349 if (isnull)
2350 elog(ERROR, "null indkey for index %u", indexId);
2352 deconstruct_array(DatumGetArrayTypeP(cols),
2353 INT2OID, 2, true, TYPALIGN_SHORT,
2354 &keys, NULL, &nKeys);
2356 for (j = keyatts; j < nKeys; j++)
2358 char *colName;
2360 colName = get_attname(conForm->conrelid,
2361 DatumGetInt16(keys[j]), false);
2362 if (j > keyatts)
2363 appendStringInfoString(&buf, ", ");
2364 appendStringInfoString(&buf, quote_identifier(colName));
2367 appendStringInfoChar(&buf, ')');
2369 ReleaseSysCache(indtup);
2371 /* XXX why do we only print these bits if fullCommand? */
2372 if (fullCommand && OidIsValid(indexId))
2374 char *options = flatten_reloptions(indexId);
2375 Oid tblspc;
2377 if (options)
2379 appendStringInfo(&buf, " WITH (%s)", options);
2380 pfree(options);
2384 * Print the tablespace, unless it's the database default.
2385 * This is to help ALTER TABLE usage of this facility,
2386 * which needs this behavior to recreate exact catalog
2387 * state.
2389 tblspc = get_rel_tablespace(indexId);
2390 if (OidIsValid(tblspc))
2391 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
2392 quote_identifier(get_tablespace_name(tblspc)));
2395 break;
2397 case CONSTRAINT_CHECK:
2399 Datum val;
2400 bool isnull;
2401 char *conbin;
2402 char *consrc;
2403 Node *expr;
2404 List *context;
2406 /* Fetch constraint expression in parsetree form */
2407 val = SysCacheGetAttr(CONSTROID, tup,
2408 Anum_pg_constraint_conbin, &isnull);
2409 if (isnull)
2410 elog(ERROR, "null conbin for constraint %u",
2411 constraintId);
2413 conbin = TextDatumGetCString(val);
2414 expr = stringToNode(conbin);
2416 /* Set up deparsing context for Var nodes in constraint */
2417 if (conForm->conrelid != InvalidOid)
2419 /* relation constraint */
2420 context = deparse_context_for(get_relation_name(conForm->conrelid),
2421 conForm->conrelid);
2423 else
2425 /* domain constraint --- can't have Vars */
2426 context = NIL;
2429 consrc = deparse_expression_pretty(expr, context, false, false,
2430 prettyFlags, 0);
2433 * Now emit the constraint definition, adding NO INHERIT if
2434 * necessary.
2436 * There are cases where the constraint expression will be
2437 * fully parenthesized and we don't need the outer parens ...
2438 * but there are other cases where we do need 'em. Be
2439 * conservative for now.
2441 * Note that simply checking for leading '(' and trailing ')'
2442 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
2444 appendStringInfo(&buf, "CHECK (%s)%s",
2445 consrc,
2446 conForm->connoinherit ? " NO INHERIT" : "");
2447 break;
2449 case CONSTRAINT_TRIGGER:
2452 * There isn't an ALTER TABLE syntax for creating a user-defined
2453 * constraint trigger, but it seems better to print something than
2454 * throw an error; if we throw error then this function couldn't
2455 * safely be applied to all rows of pg_constraint.
2457 appendStringInfoString(&buf, "TRIGGER");
2458 break;
2459 case CONSTRAINT_EXCLUSION:
2461 Oid indexOid = conForm->conindid;
2462 Datum val;
2463 bool isnull;
2464 Datum *elems;
2465 int nElems;
2466 int i;
2467 Oid *operators;
2469 /* Extract operator OIDs from the pg_constraint tuple */
2470 val = SysCacheGetAttr(CONSTROID, tup,
2471 Anum_pg_constraint_conexclop,
2472 &isnull);
2473 if (isnull)
2474 elog(ERROR, "null conexclop for constraint %u",
2475 constraintId);
2477 deconstruct_array(DatumGetArrayTypeP(val),
2478 OIDOID, sizeof(Oid), true, TYPALIGN_INT,
2479 &elems, NULL, &nElems);
2481 operators = (Oid *) palloc(nElems * sizeof(Oid));
2482 for (i = 0; i < nElems; i++)
2483 operators[i] = DatumGetObjectId(elems[i]);
2485 /* pg_get_indexdef_worker does the rest */
2486 /* suppress tablespace because pg_dump wants it that way */
2487 appendStringInfoString(&buf,
2488 pg_get_indexdef_worker(indexOid,
2490 operators,
2491 false,
2492 false,
2493 false,
2494 false,
2495 prettyFlags,
2496 false));
2497 break;
2499 default:
2500 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
2501 break;
2504 if (conForm->condeferrable)
2505 appendStringInfoString(&buf, " DEFERRABLE");
2506 if (conForm->condeferred)
2507 appendStringInfoString(&buf, " INITIALLY DEFERRED");
2508 if (!conForm->convalidated)
2509 appendStringInfoString(&buf, " NOT VALID");
2511 /* Cleanup */
2512 systable_endscan(scandesc);
2513 table_close(relation, AccessShareLock);
2515 return buf.data;
2520 * Convert an int16[] Datum into a comma-separated list of column names
2521 * for the indicated relation; append the list to buf. Returns the number
2522 * of keys.
2524 static int
2525 decompile_column_index_array(Datum column_index_array, Oid relId,
2526 StringInfo buf)
2528 Datum *keys;
2529 int nKeys;
2530 int j;
2532 /* Extract data from array of int16 */
2533 deconstruct_array(DatumGetArrayTypeP(column_index_array),
2534 INT2OID, 2, true, TYPALIGN_SHORT,
2535 &keys, NULL, &nKeys);
2537 for (j = 0; j < nKeys; j++)
2539 char *colName;
2541 colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2543 if (j == 0)
2544 appendStringInfoString(buf, quote_identifier(colName));
2545 else
2546 appendStringInfo(buf, ", %s", quote_identifier(colName));
2549 return nKeys;
2553 /* ----------
2554 * pg_get_expr - Decompile an expression tree
2556 * Input: an expression tree in nodeToString form, and a relation OID
2558 * Output: reverse-listed expression
2560 * Currently, the expression can only refer to a single relation, namely
2561 * the one specified by the second parameter. This is sufficient for
2562 * partial indexes, column default expressions, etc. We also support
2563 * Var-free expressions, for which the OID can be InvalidOid.
2564 * ----------
2566 Datum
2567 pg_get_expr(PG_FUNCTION_ARGS)
2569 text *expr = PG_GETARG_TEXT_PP(0);
2570 Oid relid = PG_GETARG_OID(1);
2571 int prettyFlags;
2572 char *relname;
2574 prettyFlags = PRETTYFLAG_INDENT;
2576 if (OidIsValid(relid))
2578 /* Get the name for the relation */
2579 relname = get_rel_name(relid);
2582 * If the OID isn't actually valid, don't throw an error, just return
2583 * NULL. This is a bit questionable, but it's what we've done
2584 * historically, and it can help avoid unwanted failures when
2585 * examining catalog entries for just-deleted relations.
2587 if (relname == NULL)
2588 PG_RETURN_NULL();
2590 else
2591 relname = NULL;
2593 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2596 Datum
2597 pg_get_expr_ext(PG_FUNCTION_ARGS)
2599 text *expr = PG_GETARG_TEXT_PP(0);
2600 Oid relid = PG_GETARG_OID(1);
2601 bool pretty = PG_GETARG_BOOL(2);
2602 int prettyFlags;
2603 char *relname;
2605 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
2607 if (OidIsValid(relid))
2609 /* Get the name for the relation */
2610 relname = get_rel_name(relid);
2611 /* See notes above */
2612 if (relname == NULL)
2613 PG_RETURN_NULL();
2615 else
2616 relname = NULL;
2618 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
2621 static text *
2622 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
2624 Node *node;
2625 List *context;
2626 char *exprstr;
2627 char *str;
2629 /* Convert input TEXT object to C string */
2630 exprstr = text_to_cstring(expr);
2632 /* Convert expression to node tree */
2633 node = (Node *) stringToNode(exprstr);
2635 pfree(exprstr);
2637 /* Prepare deparse context if needed */
2638 if (OidIsValid(relid))
2639 context = deparse_context_for(relname, relid);
2640 else
2641 context = NIL;
2643 /* Deparse */
2644 str = deparse_expression_pretty(node, context, false, false,
2645 prettyFlags, 0);
2647 return string_to_text(str);
2651 /* ----------
2652 * pg_get_userbyid - Get a user name by roleid and
2653 * fallback to 'unknown (OID=n)'
2654 * ----------
2656 Datum
2657 pg_get_userbyid(PG_FUNCTION_ARGS)
2659 Oid roleid = PG_GETARG_OID(0);
2660 Name result;
2661 HeapTuple roletup;
2662 Form_pg_authid role_rec;
2665 * Allocate space for the result
2667 result = (Name) palloc(NAMEDATALEN);
2668 memset(NameStr(*result), 0, NAMEDATALEN);
2671 * Get the pg_authid entry and print the result
2673 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
2674 if (HeapTupleIsValid(roletup))
2676 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
2677 *result = role_rec->rolname;
2678 ReleaseSysCache(roletup);
2680 else
2681 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
2683 PG_RETURN_NAME(result);
2688 * pg_get_serial_sequence
2689 * Get the name of the sequence used by an identity or serial column,
2690 * formatted suitably for passing to setval, nextval or currval.
2691 * First parameter is not treated as double-quoted, second parameter
2692 * is --- see documentation for reason.
2694 Datum
2695 pg_get_serial_sequence(PG_FUNCTION_ARGS)
2697 text *tablename = PG_GETARG_TEXT_PP(0);
2698 text *columnname = PG_GETARG_TEXT_PP(1);
2699 RangeVar *tablerv;
2700 Oid tableOid;
2701 char *column;
2702 AttrNumber attnum;
2703 Oid sequenceId = InvalidOid;
2704 Relation depRel;
2705 ScanKeyData key[3];
2706 SysScanDesc scan;
2707 HeapTuple tup;
2709 /* Look up table name. Can't lock it - we might not have privileges. */
2710 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
2711 tableOid = RangeVarGetRelid(tablerv, NoLock, false);
2713 /* Get the number of the column */
2714 column = text_to_cstring(columnname);
2716 attnum = get_attnum(tableOid, column);
2717 if (attnum == InvalidAttrNumber)
2718 ereport(ERROR,
2719 (errcode(ERRCODE_UNDEFINED_COLUMN),
2720 errmsg("column \"%s\" of relation \"%s\" does not exist",
2721 column, tablerv->relname)));
2723 /* Search the dependency table for the dependent sequence */
2724 depRel = table_open(DependRelationId, AccessShareLock);
2726 ScanKeyInit(&key[0],
2727 Anum_pg_depend_refclassid,
2728 BTEqualStrategyNumber, F_OIDEQ,
2729 ObjectIdGetDatum(RelationRelationId));
2730 ScanKeyInit(&key[1],
2731 Anum_pg_depend_refobjid,
2732 BTEqualStrategyNumber, F_OIDEQ,
2733 ObjectIdGetDatum(tableOid));
2734 ScanKeyInit(&key[2],
2735 Anum_pg_depend_refobjsubid,
2736 BTEqualStrategyNumber, F_INT4EQ,
2737 Int32GetDatum(attnum));
2739 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
2740 NULL, 3, key);
2742 while (HeapTupleIsValid(tup = systable_getnext(scan)))
2744 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
2747 * Look for an auto dependency (serial column) or internal dependency
2748 * (identity column) of a sequence on a column. (We need the relkind
2749 * test because indexes can also have auto dependencies on columns.)
2751 if (deprec->classid == RelationRelationId &&
2752 deprec->objsubid == 0 &&
2753 (deprec->deptype == DEPENDENCY_AUTO ||
2754 deprec->deptype == DEPENDENCY_INTERNAL) &&
2755 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
2757 sequenceId = deprec->objid;
2758 break;
2762 systable_endscan(scan);
2763 table_close(depRel, AccessShareLock);
2765 if (OidIsValid(sequenceId))
2767 char *result;
2769 result = generate_qualified_relation_name(sequenceId);
2771 PG_RETURN_TEXT_P(string_to_text(result));
2774 PG_RETURN_NULL();
2779 * pg_get_functiondef
2780 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
2781 * the specified function.
2783 * Note: if you change the output format of this function, be careful not
2784 * to break psql's rules (in \ef and \sf) for identifying the start of the
2785 * function body. To wit: the function body starts on a line that begins
2786 * with "AS ", and no preceding line will look like that.
2788 Datum
2789 pg_get_functiondef(PG_FUNCTION_ARGS)
2791 Oid funcid = PG_GETARG_OID(0);
2792 StringInfoData buf;
2793 StringInfoData dq;
2794 HeapTuple proctup;
2795 Form_pg_proc proc;
2796 bool isfunction;
2797 Datum tmp;
2798 bool isnull;
2799 const char *prosrc;
2800 const char *name;
2801 const char *nsp;
2802 float4 procost;
2803 int oldlen;
2805 initStringInfo(&buf);
2807 /* Look up the function */
2808 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2809 if (!HeapTupleIsValid(proctup))
2810 PG_RETURN_NULL();
2812 proc = (Form_pg_proc) GETSTRUCT(proctup);
2813 name = NameStr(proc->proname);
2815 if (proc->prokind == PROKIND_AGGREGATE)
2816 ereport(ERROR,
2817 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2818 errmsg("\"%s\" is an aggregate function", name)));
2820 isfunction = (proc->prokind != PROKIND_PROCEDURE);
2823 * We always qualify the function name, to ensure the right function gets
2824 * replaced.
2826 nsp = get_namespace_name_or_temp(proc->pronamespace);
2827 appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
2828 isfunction ? "FUNCTION" : "PROCEDURE",
2829 quote_qualified_identifier(nsp, name));
2830 (void) print_function_arguments(&buf, proctup, false, true);
2831 appendStringInfoString(&buf, ")\n");
2832 if (isfunction)
2834 appendStringInfoString(&buf, " RETURNS ");
2835 print_function_rettype(&buf, proctup);
2836 appendStringInfoChar(&buf, '\n');
2839 print_function_trftypes(&buf, proctup);
2841 appendStringInfo(&buf, " LANGUAGE %s\n",
2842 quote_identifier(get_language_name(proc->prolang, false)));
2844 /* Emit some miscellaneous options on one line */
2845 oldlen = buf.len;
2847 if (proc->prokind == PROKIND_WINDOW)
2848 appendStringInfoString(&buf, " WINDOW");
2849 switch (proc->provolatile)
2851 case PROVOLATILE_IMMUTABLE:
2852 appendStringInfoString(&buf, " IMMUTABLE");
2853 break;
2854 case PROVOLATILE_STABLE:
2855 appendStringInfoString(&buf, " STABLE");
2856 break;
2857 case PROVOLATILE_VOLATILE:
2858 break;
2861 switch (proc->proparallel)
2863 case PROPARALLEL_SAFE:
2864 appendStringInfoString(&buf, " PARALLEL SAFE");
2865 break;
2866 case PROPARALLEL_RESTRICTED:
2867 appendStringInfoString(&buf, " PARALLEL RESTRICTED");
2868 break;
2869 case PROPARALLEL_UNSAFE:
2870 break;
2873 if (proc->proisstrict)
2874 appendStringInfoString(&buf, " STRICT");
2875 if (proc->prosecdef)
2876 appendStringInfoString(&buf, " SECURITY DEFINER");
2877 if (proc->proleakproof)
2878 appendStringInfoString(&buf, " LEAKPROOF");
2880 /* This code for the default cost and rows should match functioncmds.c */
2881 if (proc->prolang == INTERNALlanguageId ||
2882 proc->prolang == ClanguageId)
2883 procost = 1;
2884 else
2885 procost = 100;
2886 if (proc->procost != procost)
2887 appendStringInfo(&buf, " COST %g", proc->procost);
2889 if (proc->prorows > 0 && proc->prorows != 1000)
2890 appendStringInfo(&buf, " ROWS %g", proc->prorows);
2892 if (proc->prosupport)
2894 Oid argtypes[1];
2897 * We should qualify the support function's name if it wouldn't be
2898 * resolved by lookup in the current search path.
2900 argtypes[0] = INTERNALOID;
2901 appendStringInfo(&buf, " SUPPORT %s",
2902 generate_function_name(proc->prosupport, 1,
2903 NIL, argtypes,
2904 false, NULL, EXPR_KIND_NONE));
2907 if (oldlen != buf.len)
2908 appendStringInfoChar(&buf, '\n');
2910 /* Emit any proconfig options, one per line */
2911 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
2912 if (!isnull)
2914 ArrayType *a = DatumGetArrayTypeP(tmp);
2915 int i;
2917 Assert(ARR_ELEMTYPE(a) == TEXTOID);
2918 Assert(ARR_NDIM(a) == 1);
2919 Assert(ARR_LBOUND(a)[0] == 1);
2921 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
2923 Datum d;
2925 d = array_ref(a, 1, &i,
2926 -1 /* varlenarray */ ,
2927 -1 /* TEXT's typlen */ ,
2928 false /* TEXT's typbyval */ ,
2929 TYPALIGN_INT /* TEXT's typalign */ ,
2930 &isnull);
2931 if (!isnull)
2933 char *configitem = TextDatumGetCString(d);
2934 char *pos;
2936 pos = strchr(configitem, '=');
2937 if (pos == NULL)
2938 continue;
2939 *pos++ = '\0';
2941 appendStringInfo(&buf, " SET %s TO ",
2942 quote_identifier(configitem));
2945 * Variables that are marked GUC_LIST_QUOTE were already fully
2946 * quoted by flatten_set_variable_args() before they were put
2947 * into the proconfig array. However, because the quoting
2948 * rules used there aren't exactly like SQL's, we have to
2949 * break the list value apart and then quote the elements as
2950 * string literals. (The elements may be double-quoted as-is,
2951 * but we can't just feed them to the SQL parser; it would do
2952 * the wrong thing with elements that are zero-length or
2953 * longer than NAMEDATALEN.)
2955 * Variables that are not so marked should just be emitted as
2956 * simple string literals. If the variable is not known to
2957 * guc.c, we'll do that; this makes it unsafe to use
2958 * GUC_LIST_QUOTE for extension variables.
2960 if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
2962 List *namelist;
2963 ListCell *lc;
2965 /* Parse string into list of identifiers */
2966 if (!SplitGUCList(pos, ',', &namelist))
2968 /* this shouldn't fail really */
2969 elog(ERROR, "invalid list syntax in proconfig item");
2971 foreach(lc, namelist)
2973 char *curname = (char *) lfirst(lc);
2975 simple_quote_literal(&buf, curname);
2976 if (lnext(namelist, lc))
2977 appendStringInfoString(&buf, ", ");
2980 else
2981 simple_quote_literal(&buf, pos);
2982 appendStringInfoChar(&buf, '\n');
2987 /* And finally the function definition ... */
2988 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
2989 if (proc->prolang == SQLlanguageId && !isnull)
2991 print_function_sqlbody(&buf, proctup);
2993 else
2995 appendStringInfoString(&buf, "AS ");
2997 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
2998 if (!isnull)
3000 simple_quote_literal(&buf, TextDatumGetCString(tmp));
3001 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
3004 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
3005 if (isnull)
3006 elog(ERROR, "null prosrc");
3007 prosrc = TextDatumGetCString(tmp);
3010 * We always use dollar quoting. Figure out a suitable delimiter.
3012 * Since the user is likely to be editing the function body string, we
3013 * shouldn't use a short delimiter that he might easily create a
3014 * conflict with. Hence prefer "$function$"/"$procedure$", but extend
3015 * if needed.
3017 initStringInfo(&dq);
3018 appendStringInfoChar(&dq, '$');
3019 appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
3020 while (strstr(prosrc, dq.data) != NULL)
3021 appendStringInfoChar(&dq, 'x');
3022 appendStringInfoChar(&dq, '$');
3024 appendBinaryStringInfo(&buf, dq.data, dq.len);
3025 appendStringInfoString(&buf, prosrc);
3026 appendBinaryStringInfo(&buf, dq.data, dq.len);
3029 appendStringInfoChar(&buf, '\n');
3031 ReleaseSysCache(proctup);
3033 PG_RETURN_TEXT_P(string_to_text(buf.data));
3037 * pg_get_function_arguments
3038 * Get a nicely-formatted list of arguments for a function.
3039 * This is everything that would go between the parentheses in
3040 * CREATE FUNCTION.
3042 Datum
3043 pg_get_function_arguments(PG_FUNCTION_ARGS)
3045 Oid funcid = PG_GETARG_OID(0);
3046 StringInfoData buf;
3047 HeapTuple proctup;
3049 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3050 if (!HeapTupleIsValid(proctup))
3051 PG_RETURN_NULL();
3053 initStringInfo(&buf);
3055 (void) print_function_arguments(&buf, proctup, false, true);
3057 ReleaseSysCache(proctup);
3059 PG_RETURN_TEXT_P(string_to_text(buf.data));
3063 * pg_get_function_identity_arguments
3064 * Get a formatted list of arguments for a function.
3065 * This is everything that would go between the parentheses in
3066 * ALTER FUNCTION, etc. In particular, don't print defaults.
3068 Datum
3069 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
3071 Oid funcid = PG_GETARG_OID(0);
3072 StringInfoData buf;
3073 HeapTuple proctup;
3075 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3076 if (!HeapTupleIsValid(proctup))
3077 PG_RETURN_NULL();
3079 initStringInfo(&buf);
3081 (void) print_function_arguments(&buf, proctup, false, false);
3083 ReleaseSysCache(proctup);
3085 PG_RETURN_TEXT_P(string_to_text(buf.data));
3089 * pg_get_function_result
3090 * Get a nicely-formatted version of the result type of a function.
3091 * This is what would appear after RETURNS in CREATE FUNCTION.
3093 Datum
3094 pg_get_function_result(PG_FUNCTION_ARGS)
3096 Oid funcid = PG_GETARG_OID(0);
3097 StringInfoData buf;
3098 HeapTuple proctup;
3100 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3101 if (!HeapTupleIsValid(proctup))
3102 PG_RETURN_NULL();
3104 if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
3106 ReleaseSysCache(proctup);
3107 PG_RETURN_NULL();
3110 initStringInfo(&buf);
3112 print_function_rettype(&buf, proctup);
3114 ReleaseSysCache(proctup);
3116 PG_RETURN_TEXT_P(string_to_text(buf.data));
3120 * Guts of pg_get_function_result: append the function's return type
3121 * to the specified buffer.
3123 static void
3124 print_function_rettype(StringInfo buf, HeapTuple proctup)
3126 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3127 int ntabargs = 0;
3128 StringInfoData rbuf;
3130 initStringInfo(&rbuf);
3132 if (proc->proretset)
3134 /* It might be a table function; try to print the arguments */
3135 appendStringInfoString(&rbuf, "TABLE(");
3136 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
3137 if (ntabargs > 0)
3138 appendStringInfoChar(&rbuf, ')');
3139 else
3140 resetStringInfo(&rbuf);
3143 if (ntabargs == 0)
3145 /* Not a table function, so do the normal thing */
3146 if (proc->proretset)
3147 appendStringInfoString(&rbuf, "SETOF ");
3148 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
3151 appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
3155 * Common code for pg_get_function_arguments and pg_get_function_result:
3156 * append the desired subset of arguments to buf. We print only TABLE
3157 * arguments when print_table_args is true, and all the others when it's false.
3158 * We print argument defaults only if print_defaults is true.
3159 * Function return value is the number of arguments printed.
3161 static int
3162 print_function_arguments(StringInfo buf, HeapTuple proctup,
3163 bool print_table_args, bool print_defaults)
3165 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
3166 int numargs;
3167 Oid *argtypes;
3168 char **argnames;
3169 char *argmodes;
3170 int insertorderbyat = -1;
3171 int argsprinted;
3172 int inputargno;
3173 int nlackdefaults;
3174 List *argdefaults = NIL;
3175 ListCell *nextargdefault = NULL;
3176 int i;
3178 numargs = get_func_arg_info(proctup,
3179 &argtypes, &argnames, &argmodes);
3181 nlackdefaults = numargs;
3182 if (print_defaults && proc->pronargdefaults > 0)
3184 Datum proargdefaults;
3185 bool isnull;
3187 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3188 Anum_pg_proc_proargdefaults,
3189 &isnull);
3190 if (!isnull)
3192 char *str;
3194 str = TextDatumGetCString(proargdefaults);
3195 argdefaults = castNode(List, stringToNode(str));
3196 pfree(str);
3197 nextargdefault = list_head(argdefaults);
3198 /* nlackdefaults counts only *input* arguments lacking defaults */
3199 nlackdefaults = proc->pronargs - list_length(argdefaults);
3203 /* Check for special treatment of ordered-set aggregates */
3204 if (proc->prokind == PROKIND_AGGREGATE)
3206 HeapTuple aggtup;
3207 Form_pg_aggregate agg;
3209 aggtup = SearchSysCache1(AGGFNOID, proc->oid);
3210 if (!HeapTupleIsValid(aggtup))
3211 elog(ERROR, "cache lookup failed for aggregate %u",
3212 proc->oid);
3213 agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
3214 if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
3215 insertorderbyat = agg->aggnumdirectargs;
3216 ReleaseSysCache(aggtup);
3219 argsprinted = 0;
3220 inputargno = 0;
3221 for (i = 0; i < numargs; i++)
3223 Oid argtype = argtypes[i];
3224 char *argname = argnames ? argnames[i] : NULL;
3225 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
3226 const char *modename;
3227 bool isinput;
3229 switch (argmode)
3231 case PROARGMODE_IN:
3234 * For procedures, explicitly mark all argument modes, so as
3235 * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
3237 if (proc->prokind == PROKIND_PROCEDURE)
3238 modename = "IN ";
3239 else
3240 modename = "";
3241 isinput = true;
3242 break;
3243 case PROARGMODE_INOUT:
3244 modename = "INOUT ";
3245 isinput = true;
3246 break;
3247 case PROARGMODE_OUT:
3248 modename = "OUT ";
3249 isinput = false;
3250 break;
3251 case PROARGMODE_VARIADIC:
3252 modename = "VARIADIC ";
3253 isinput = true;
3254 break;
3255 case PROARGMODE_TABLE:
3256 modename = "";
3257 isinput = false;
3258 break;
3259 default:
3260 elog(ERROR, "invalid parameter mode '%c'", argmode);
3261 modename = NULL; /* keep compiler quiet */
3262 isinput = false;
3263 break;
3265 if (isinput)
3266 inputargno++; /* this is a 1-based counter */
3268 if (print_table_args != (argmode == PROARGMODE_TABLE))
3269 continue;
3271 if (argsprinted == insertorderbyat)
3273 if (argsprinted)
3274 appendStringInfoChar(buf, ' ');
3275 appendStringInfoString(buf, "ORDER BY ");
3277 else if (argsprinted)
3278 appendStringInfoString(buf, ", ");
3280 appendStringInfoString(buf, modename);
3281 if (argname && argname[0])
3282 appendStringInfo(buf, "%s ", quote_identifier(argname));
3283 appendStringInfoString(buf, format_type_be(argtype));
3284 if (print_defaults && isinput && inputargno > nlackdefaults)
3286 Node *expr;
3288 Assert(nextargdefault != NULL);
3289 expr = (Node *) lfirst(nextargdefault);
3290 nextargdefault = lnext(argdefaults, nextargdefault);
3292 appendStringInfo(buf, " DEFAULT %s",
3293 deparse_expression(expr, NIL, false, false));
3295 argsprinted++;
3297 /* nasty hack: print the last arg twice for variadic ordered-set agg */
3298 if (argsprinted == insertorderbyat && i == numargs - 1)
3300 i--;
3301 /* aggs shouldn't have defaults anyway, but just to be sure ... */
3302 print_defaults = false;
3306 return argsprinted;
3309 static bool
3310 is_input_argument(int nth, const char *argmodes)
3312 return (!argmodes
3313 || argmodes[nth] == PROARGMODE_IN
3314 || argmodes[nth] == PROARGMODE_INOUT
3315 || argmodes[nth] == PROARGMODE_VARIADIC);
3319 * Append used transformed types to specified buffer
3321 static void
3322 print_function_trftypes(StringInfo buf, HeapTuple proctup)
3324 Oid *trftypes;
3325 int ntypes;
3327 ntypes = get_func_trftypes(proctup, &trftypes);
3328 if (ntypes > 0)
3330 int i;
3332 appendStringInfoString(buf, " TRANSFORM ");
3333 for (i = 0; i < ntypes; i++)
3335 if (i != 0)
3336 appendStringInfoString(buf, ", ");
3337 appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
3339 appendStringInfoChar(buf, '\n');
3344 * Get textual representation of a function argument's default value. The
3345 * second argument of this function is the argument number among all arguments
3346 * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
3347 * how information_schema.sql uses it.
3349 Datum
3350 pg_get_function_arg_default(PG_FUNCTION_ARGS)
3352 Oid funcid = PG_GETARG_OID(0);
3353 int32 nth_arg = PG_GETARG_INT32(1);
3354 HeapTuple proctup;
3355 Form_pg_proc proc;
3356 int numargs;
3357 Oid *argtypes;
3358 char **argnames;
3359 char *argmodes;
3360 int i;
3361 List *argdefaults;
3362 Node *node;
3363 char *str;
3364 int nth_inputarg;
3365 Datum proargdefaults;
3366 bool isnull;
3367 int nth_default;
3369 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3370 if (!HeapTupleIsValid(proctup))
3371 PG_RETURN_NULL();
3373 numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
3374 if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
3376 ReleaseSysCache(proctup);
3377 PG_RETURN_NULL();
3380 nth_inputarg = 0;
3381 for (i = 0; i < nth_arg; i++)
3382 if (is_input_argument(i, argmodes))
3383 nth_inputarg++;
3385 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
3386 Anum_pg_proc_proargdefaults,
3387 &isnull);
3388 if (isnull)
3390 ReleaseSysCache(proctup);
3391 PG_RETURN_NULL();
3394 str = TextDatumGetCString(proargdefaults);
3395 argdefaults = castNode(List, stringToNode(str));
3396 pfree(str);
3398 proc = (Form_pg_proc) GETSTRUCT(proctup);
3401 * Calculate index into proargdefaults: proargdefaults corresponds to the
3402 * last N input arguments, where N = pronargdefaults.
3404 nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
3406 if (nth_default < 0 || nth_default >= list_length(argdefaults))
3408 ReleaseSysCache(proctup);
3409 PG_RETURN_NULL();
3411 node = list_nth(argdefaults, nth_default);
3412 str = deparse_expression(node, NIL, false, false);
3414 ReleaseSysCache(proctup);
3416 PG_RETURN_TEXT_P(string_to_text(str));
3419 static void
3420 print_function_sqlbody(StringInfo buf, HeapTuple proctup)
3422 int numargs;
3423 Oid *argtypes;
3424 char **argnames;
3425 char *argmodes;
3426 deparse_namespace dpns = {0};
3427 Datum tmp;
3428 bool isnull;
3429 Node *n;
3431 dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
3432 numargs = get_func_arg_info(proctup,
3433 &argtypes, &argnames, &argmodes);
3434 dpns.numargs = numargs;
3435 dpns.argnames = argnames;
3437 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3438 Assert(!isnull);
3439 n = stringToNode(TextDatumGetCString(tmp));
3441 if (IsA(n, List))
3443 List *stmts;
3444 ListCell *lc;
3446 stmts = linitial(castNode(List, n));
3448 appendStringInfoString(buf, "BEGIN ATOMIC\n");
3450 foreach(lc, stmts)
3452 Query *query = lfirst_node(Query, lc);
3454 /* It seems advisable to get at least AccessShareLock on rels */
3455 AcquireRewriteLocks(query, false, false);
3456 get_query_def(query, buf, list_make1(&dpns), NULL,
3457 PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1);
3458 appendStringInfoChar(buf, ';');
3459 appendStringInfoChar(buf, '\n');
3462 appendStringInfoString(buf, "END");
3464 else
3466 Query *query = castNode(Query, n);
3468 /* It seems advisable to get at least AccessShareLock on rels */
3469 AcquireRewriteLocks(query, false, false);
3470 get_query_def(query, buf, list_make1(&dpns), NULL,
3471 0, WRAP_COLUMN_DEFAULT, 0);
3475 Datum
3476 pg_get_function_sqlbody(PG_FUNCTION_ARGS)
3478 Oid funcid = PG_GETARG_OID(0);
3479 StringInfoData buf;
3480 HeapTuple proctup;
3481 bool isnull;
3483 initStringInfo(&buf);
3485 /* Look up the function */
3486 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3487 if (!HeapTupleIsValid(proctup))
3488 PG_RETURN_NULL();
3490 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
3491 if (isnull)
3493 ReleaseSysCache(proctup);
3494 PG_RETURN_NULL();
3497 print_function_sqlbody(&buf, proctup);
3499 ReleaseSysCache(proctup);
3501 PG_RETURN_TEXT_P(cstring_to_text(buf.data));
3506 * deparse_expression - General utility for deparsing expressions
3508 * calls deparse_expression_pretty with all prettyPrinting disabled
3510 char *
3511 deparse_expression(Node *expr, List *dpcontext,
3512 bool forceprefix, bool showimplicit)
3514 return deparse_expression_pretty(expr, dpcontext, forceprefix,
3515 showimplicit, 0, 0);
3518 /* ----------
3519 * deparse_expression_pretty - General utility for deparsing expressions
3521 * expr is the node tree to be deparsed. It must be a transformed expression
3522 * tree (ie, not the raw output of gram.y).
3524 * dpcontext is a list of deparse_namespace nodes representing the context
3525 * for interpreting Vars in the node tree. It can be NIL if no Vars are
3526 * expected.
3528 * forceprefix is true to force all Vars to be prefixed with their table names.
3530 * showimplicit is true to force all implicit casts to be shown explicitly.
3532 * Tries to pretty up the output according to prettyFlags and startIndent.
3534 * The result is a palloc'd string.
3535 * ----------
3537 static char *
3538 deparse_expression_pretty(Node *expr, List *dpcontext,
3539 bool forceprefix, bool showimplicit,
3540 int prettyFlags, int startIndent)
3542 StringInfoData buf;
3543 deparse_context context;
3545 initStringInfo(&buf);
3546 context.buf = &buf;
3547 context.namespaces = dpcontext;
3548 context.windowClause = NIL;
3549 context.windowTList = NIL;
3550 context.varprefix = forceprefix;
3551 context.prettyFlags = prettyFlags;
3552 context.wrapColumn = WRAP_COLUMN_DEFAULT;
3553 context.indentLevel = startIndent;
3554 context.special_exprkind = EXPR_KIND_NONE;
3555 context.appendparents = NULL;
3557 get_rule_expr(expr, &context, showimplicit);
3559 return buf.data;
3562 /* ----------
3563 * deparse_context_for - Build deparse context for a single relation
3565 * Given the reference name (alias) and OID of a relation, build deparsing
3566 * context for an expression referencing only that relation (as varno 1,
3567 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
3568 * ----------
3570 List *
3571 deparse_context_for(const char *aliasname, Oid relid)
3573 deparse_namespace *dpns;
3574 RangeTblEntry *rte;
3576 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3578 /* Build a minimal RTE for the rel */
3579 rte = makeNode(RangeTblEntry);
3580 rte->rtekind = RTE_RELATION;
3581 rte->relid = relid;
3582 rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3583 rte->rellockmode = AccessShareLock;
3584 rte->alias = makeAlias(aliasname, NIL);
3585 rte->eref = rte->alias;
3586 rte->lateral = false;
3587 rte->inh = false;
3588 rte->inFromCl = true;
3590 /* Build one-element rtable */
3591 dpns->rtable = list_make1(rte);
3592 dpns->subplans = NIL;
3593 dpns->ctes = NIL;
3594 dpns->appendrels = NULL;
3595 set_rtable_names(dpns, NIL, NULL);
3596 set_simple_column_names(dpns);
3598 /* Return a one-deep namespace stack */
3599 return list_make1(dpns);
3603 * deparse_context_for_plan_tree - Build deparse context for a Plan tree
3605 * When deparsing an expression in a Plan tree, we use the plan's rangetable
3606 * to resolve names of simple Vars. The initialization of column names for
3607 * this is rather expensive if the rangetable is large, and it'll be the same
3608 * for every expression in the Plan tree; so we do it just once and re-use
3609 * the result of this function for each expression. (Note that the result
3610 * is not usable until set_deparse_context_plan() is applied to it.)
3612 * In addition to the PlannedStmt, pass the per-RTE alias names
3613 * assigned by a previous call to select_rtable_names_for_explain.
3615 List *
3616 deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
3618 deparse_namespace *dpns;
3620 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3622 /* Initialize fields that stay the same across the whole plan tree */
3623 dpns->rtable = pstmt->rtable;
3624 dpns->rtable_names = rtable_names;
3625 dpns->subplans = pstmt->subplans;
3626 dpns->ctes = NIL;
3627 if (pstmt->appendRelations)
3629 /* Set up the array, indexed by child relid */
3630 int ntables = list_length(dpns->rtable);
3631 ListCell *lc;
3633 dpns->appendrels = (AppendRelInfo **)
3634 palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3635 foreach(lc, pstmt->appendRelations)
3637 AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3638 Index crelid = appinfo->child_relid;
3640 Assert(crelid > 0 && crelid <= ntables);
3641 Assert(dpns->appendrels[crelid] == NULL);
3642 dpns->appendrels[crelid] = appinfo;
3645 else
3646 dpns->appendrels = NULL; /* don't need it */
3649 * Set up column name aliases. We will get rather bogus results for join
3650 * RTEs, but that doesn't matter because plan trees don't contain any join
3651 * alias Vars.
3653 set_simple_column_names(dpns);
3655 /* Return a one-deep namespace stack */
3656 return list_make1(dpns);
3660 * set_deparse_context_plan - Specify Plan node containing expression
3662 * When deparsing an expression in a Plan tree, we might have to resolve
3663 * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
3664 * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
3665 * can be resolved by drilling down into the left and right child plans.
3666 * Similarly, INDEX_VAR references can be resolved by reference to the
3667 * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
3668 * ForeignScan and CustomScan nodes. (Note that we don't currently support
3669 * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
3670 * for those, we can only deparse the indexqualorig fields, which won't
3671 * contain INDEX_VAR Vars.)
3673 * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
3674 * the most-closely-nested first. This is needed to resolve PARAM_EXEC
3675 * Params. Note we assume that all the Plan nodes share the same rtable.
3677 * Once this function has been called, deparse_expression() can be called on
3678 * subsidiary expression(s) of the specified Plan node. To deparse
3679 * expressions of a different Plan node in the same Plan tree, re-call this
3680 * function to identify the new parent Plan node.
3682 * The result is the same List passed in; this is a notational convenience.
3684 List *
3685 set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
3687 deparse_namespace *dpns;
3689 /* Should always have one-entry namespace list for Plan deparsing */
3690 Assert(list_length(dpcontext) == 1);
3691 dpns = (deparse_namespace *) linitial(dpcontext);
3693 /* Set our attention on the specific plan node passed in */
3694 dpns->ancestors = ancestors;
3695 set_deparse_plan(dpns, plan);
3697 return dpcontext;
3701 * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN
3703 * Determine the relation aliases we'll use during an EXPLAIN operation.
3704 * This is just a frontend to set_rtable_names. We have to expose the aliases
3705 * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
3707 List *
3708 select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
3710 deparse_namespace dpns;
3712 memset(&dpns, 0, sizeof(dpns));
3713 dpns.rtable = rtable;
3714 dpns.subplans = NIL;
3715 dpns.ctes = NIL;
3716 dpns.appendrels = NULL;
3717 set_rtable_names(&dpns, NIL, rels_used);
3718 /* We needn't bother computing column aliases yet */
3720 return dpns.rtable_names;
3724 * set_rtable_names: select RTE aliases to be used in printing a query
3726 * We fill in dpns->rtable_names with a list of names that is one-for-one with
3727 * the already-filled dpns->rtable list. Each RTE name is unique among those
3728 * in the new namespace plus any ancestor namespaces listed in
3729 * parent_namespaces.
3731 * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
3733 * Note that this function is only concerned with relation names, not column
3734 * names.
3736 static void
3737 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
3738 Bitmapset *rels_used)
3740 HASHCTL hash_ctl;
3741 HTAB *names_hash;
3742 NameHashEntry *hentry;
3743 bool found;
3744 int rtindex;
3745 ListCell *lc;
3747 dpns->rtable_names = NIL;
3748 /* nothing more to do if empty rtable */
3749 if (dpns->rtable == NIL)
3750 return;
3753 * We use a hash table to hold known names, so that this process is O(N)
3754 * not O(N^2) for N names.
3756 hash_ctl.keysize = NAMEDATALEN;
3757 hash_ctl.entrysize = sizeof(NameHashEntry);
3758 hash_ctl.hcxt = CurrentMemoryContext;
3759 names_hash = hash_create("set_rtable_names names",
3760 list_length(dpns->rtable),
3761 &hash_ctl,
3762 HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
3764 /* Preload the hash table with names appearing in parent_namespaces */
3765 foreach(lc, parent_namespaces)
3767 deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
3768 ListCell *lc2;
3770 foreach(lc2, olddpns->rtable_names)
3772 char *oldname = (char *) lfirst(lc2);
3774 if (oldname == NULL)
3775 continue;
3776 hentry = (NameHashEntry *) hash_search(names_hash,
3777 oldname,
3778 HASH_ENTER,
3779 &found);
3780 /* we do not complain about duplicate names in parent namespaces */
3781 hentry->counter = 0;
3785 /* Now we can scan the rtable */
3786 rtindex = 1;
3787 foreach(lc, dpns->rtable)
3789 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3790 char *refname;
3792 /* Just in case this takes an unreasonable amount of time ... */
3793 CHECK_FOR_INTERRUPTS();
3795 if (rels_used && !bms_is_member(rtindex, rels_used))
3797 /* Ignore unreferenced RTE */
3798 refname = NULL;
3800 else if (rte->alias)
3802 /* If RTE has a user-defined alias, prefer that */
3803 refname = rte->alias->aliasname;
3805 else if (rte->rtekind == RTE_RELATION)
3807 /* Use the current actual name of the relation */
3808 refname = get_rel_name(rte->relid);
3810 else if (rte->rtekind == RTE_JOIN)
3812 /* Unnamed join has no refname */
3813 refname = NULL;
3815 else
3817 /* Otherwise use whatever the parser assigned */
3818 refname = rte->eref->aliasname;
3822 * If the selected name isn't unique, append digits to make it so, and
3823 * make a new hash entry for it once we've got a unique name. For a
3824 * very long input name, we might have to truncate to stay within
3825 * NAMEDATALEN.
3827 if (refname)
3829 hentry = (NameHashEntry *) hash_search(names_hash,
3830 refname,
3831 HASH_ENTER,
3832 &found);
3833 if (found)
3835 /* Name already in use, must choose a new one */
3836 int refnamelen = strlen(refname);
3837 char *modname = (char *) palloc(refnamelen + 16);
3838 NameHashEntry *hentry2;
3842 hentry->counter++;
3843 for (;;)
3845 memcpy(modname, refname, refnamelen);
3846 sprintf(modname + refnamelen, "_%d", hentry->counter);
3847 if (strlen(modname) < NAMEDATALEN)
3848 break;
3849 /* drop chars from refname to keep all the digits */
3850 refnamelen = pg_mbcliplen(refname, refnamelen,
3851 refnamelen - 1);
3853 hentry2 = (NameHashEntry *) hash_search(names_hash,
3854 modname,
3855 HASH_ENTER,
3856 &found);
3857 } while (found);
3858 hentry2->counter = 0; /* init new hash entry */
3859 refname = modname;
3861 else
3863 /* Name not previously used, need only initialize hentry */
3864 hentry->counter = 0;
3868 dpns->rtable_names = lappend(dpns->rtable_names, refname);
3869 rtindex++;
3872 hash_destroy(names_hash);
3876 * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
3878 * For convenience, this is defined to initialize the deparse_namespace struct
3879 * from scratch.
3881 static void
3882 set_deparse_for_query(deparse_namespace *dpns, Query *query,
3883 List *parent_namespaces)
3885 ListCell *lc;
3886 ListCell *lc2;
3888 /* Initialize *dpns and fill rtable/ctes links */
3889 memset(dpns, 0, sizeof(deparse_namespace));
3890 dpns->rtable = query->rtable;
3891 dpns->subplans = NIL;
3892 dpns->ctes = query->cteList;
3893 dpns->appendrels = NULL;
3895 /* Assign a unique relation alias to each RTE */
3896 set_rtable_names(dpns, parent_namespaces, NULL);
3898 /* Initialize dpns->rtable_columns to contain zeroed structs */
3899 dpns->rtable_columns = NIL;
3900 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3901 dpns->rtable_columns = lappend(dpns->rtable_columns,
3902 palloc0(sizeof(deparse_columns)));
3904 /* If it's a utility query, it won't have a jointree */
3905 if (query->jointree)
3907 /* Detect whether global uniqueness of USING names is needed */
3908 dpns->unique_using =
3909 has_dangerous_join_using(dpns, (Node *) query->jointree);
3912 * Select names for columns merged by USING, via a recursive pass over
3913 * the query jointree.
3915 set_using_names(dpns, (Node *) query->jointree, NIL);
3919 * Now assign remaining column aliases for each RTE. We do this in a
3920 * linear scan of the rtable, so as to process RTEs whether or not they
3921 * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
3922 * etc). JOIN RTEs must be processed after their children, but this is
3923 * okay because they appear later in the rtable list than their children
3924 * (cf Asserts in identify_join_columns()).
3926 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
3928 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3929 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
3931 if (rte->rtekind == RTE_JOIN)
3932 set_join_column_names(dpns, rte, colinfo);
3933 else
3934 set_relation_column_names(dpns, rte, colinfo);
3939 * set_simple_column_names: fill in column aliases for non-query situations
3941 * This handles EXPLAIN and cases where we only have relation RTEs. Without
3942 * a join tree, we can't do anything smart about join RTEs, but we don't
3943 * need to (note that EXPLAIN should never see join alias Vars anyway).
3944 * If we do hit a join RTE we'll just process it like a non-table base RTE.
3946 static void
3947 set_simple_column_names(deparse_namespace *dpns)
3949 ListCell *lc;
3950 ListCell *lc2;
3952 /* Initialize dpns->rtable_columns to contain zeroed structs */
3953 dpns->rtable_columns = NIL;
3954 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
3955 dpns->rtable_columns = lappend(dpns->rtable_columns,
3956 palloc0(sizeof(deparse_columns)));
3958 /* Assign unique column aliases within each RTE */
3959 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
3961 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3962 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
3964 set_relation_column_names(dpns, rte, colinfo);
3969 * has_dangerous_join_using: search jointree for unnamed JOIN USING
3971 * Merged columns of a JOIN USING may act differently from either of the input
3972 * columns, either because they are merged with COALESCE (in a FULL JOIN) or
3973 * because an implicit coercion of the underlying input column is required.
3974 * In such a case the column must be referenced as a column of the JOIN not as
3975 * a column of either input. And this is problematic if the join is unnamed
3976 * (alias-less): we cannot qualify the column's name with an RTE name, since
3977 * there is none. (Forcibly assigning an alias to the join is not a solution,
3978 * since that will prevent legal references to tables below the join.)
3979 * To ensure that every column in the query is unambiguously referenceable,
3980 * we must assign such merged columns names that are globally unique across
3981 * the whole query, aliasing other columns out of the way as necessary.
3983 * Because the ensuing re-aliasing is fairly damaging to the readability of
3984 * the query, we don't do this unless we have to. So, we must pre-scan
3985 * the join tree to see if we have to, before starting set_using_names().
3987 static bool
3988 has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
3990 if (IsA(jtnode, RangeTblRef))
3992 /* nothing to do here */
3994 else if (IsA(jtnode, FromExpr))
3996 FromExpr *f = (FromExpr *) jtnode;
3997 ListCell *lc;
3999 foreach(lc, f->fromlist)
4001 if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
4002 return true;
4005 else if (IsA(jtnode, JoinExpr))
4007 JoinExpr *j = (JoinExpr *) jtnode;
4009 /* Is it an unnamed JOIN with USING? */
4010 if (j->alias == NULL && j->usingClause)
4013 * Yes, so check each join alias var to see if any of them are not
4014 * simple references to underlying columns. If so, we have a
4015 * dangerous situation and must pick unique aliases.
4017 RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
4019 /* We need only examine the merged columns */
4020 for (int i = 0; i < jrte->joinmergedcols; i++)
4022 Node *aliasvar = list_nth(jrte->joinaliasvars, i);
4024 if (!IsA(aliasvar, Var))
4025 return true;
4029 /* Nope, but inspect children */
4030 if (has_dangerous_join_using(dpns, j->larg))
4031 return true;
4032 if (has_dangerous_join_using(dpns, j->rarg))
4033 return true;
4035 else
4036 elog(ERROR, "unrecognized node type: %d",
4037 (int) nodeTag(jtnode));
4038 return false;
4042 * set_using_names: select column aliases to be used for merged USING columns
4044 * We do this during a recursive descent of the query jointree.
4045 * dpns->unique_using must already be set to determine the global strategy.
4047 * Column alias info is saved in the dpns->rtable_columns list, which is
4048 * assumed to be filled with pre-zeroed deparse_columns structs.
4050 * parentUsing is a list of all USING aliases assigned in parent joins of
4051 * the current jointree node. (The passed-in list must not be modified.)
4053 static void
4054 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
4056 if (IsA(jtnode, RangeTblRef))
4058 /* nothing to do now */
4060 else if (IsA(jtnode, FromExpr))
4062 FromExpr *f = (FromExpr *) jtnode;
4063 ListCell *lc;
4065 foreach(lc, f->fromlist)
4066 set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
4068 else if (IsA(jtnode, JoinExpr))
4070 JoinExpr *j = (JoinExpr *) jtnode;
4071 RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
4072 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
4073 int *leftattnos;
4074 int *rightattnos;
4075 deparse_columns *leftcolinfo;
4076 deparse_columns *rightcolinfo;
4077 int i;
4078 ListCell *lc;
4080 /* Get info about the shape of the join */
4081 identify_join_columns(j, rte, colinfo);
4082 leftattnos = colinfo->leftattnos;
4083 rightattnos = colinfo->rightattnos;
4085 /* Look up the not-yet-filled-in child deparse_columns structs */
4086 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4087 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4090 * If this join is unnamed, then we cannot substitute new aliases at
4091 * this level, so any name requirements pushed down to here must be
4092 * pushed down again to the children.
4094 if (rte->alias == NULL)
4096 for (i = 0; i < colinfo->num_cols; i++)
4098 char *colname = colinfo->colnames[i];
4100 if (colname == NULL)
4101 continue;
4103 /* Push down to left column, unless it's a system column */
4104 if (leftattnos[i] > 0)
4106 expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4107 leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4110 /* Same on the righthand side */
4111 if (rightattnos[i] > 0)
4113 expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4114 rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4120 * If there's a USING clause, select the USING column names and push
4121 * those names down to the children. We have two strategies:
4123 * If dpns->unique_using is true, we force all USING names to be
4124 * unique across the whole query level. In principle we'd only need
4125 * the names of dangerous USING columns to be globally unique, but to
4126 * safely assign all USING names in a single pass, we have to enforce
4127 * the same uniqueness rule for all of them. However, if a USING
4128 * column's name has been pushed down from the parent, we should use
4129 * it as-is rather than making a uniqueness adjustment. This is
4130 * necessary when we're at an unnamed join, and it creates no risk of
4131 * ambiguity. Also, if there's a user-written output alias for a
4132 * merged column, we prefer to use that rather than the input name;
4133 * this simplifies the logic and seems likely to lead to less aliasing
4134 * overall.
4136 * If dpns->unique_using is false, we only need USING names to be
4137 * unique within their own join RTE. We still need to honor
4138 * pushed-down names, though.
4140 * Though significantly different in results, these two strategies are
4141 * implemented by the same code, with only the difference of whether
4142 * to put assigned names into dpns->using_names.
4144 if (j->usingClause)
4146 /* Copy the input parentUsing list so we don't modify it */
4147 parentUsing = list_copy(parentUsing);
4149 /* USING names must correspond to the first join output columns */
4150 expand_colnames_array_to(colinfo, list_length(j->usingClause));
4151 i = 0;
4152 foreach(lc, j->usingClause)
4154 char *colname = strVal(lfirst(lc));
4156 /* Assert it's a merged column */
4157 Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
4159 /* Adopt passed-down name if any, else select unique name */
4160 if (colinfo->colnames[i] != NULL)
4161 colname = colinfo->colnames[i];
4162 else
4164 /* Prefer user-written output alias if any */
4165 if (rte->alias && i < list_length(rte->alias->colnames))
4166 colname = strVal(list_nth(rte->alias->colnames, i));
4167 /* Make it appropriately unique */
4168 colname = make_colname_unique(colname, dpns, colinfo);
4169 if (dpns->unique_using)
4170 dpns->using_names = lappend(dpns->using_names,
4171 colname);
4172 /* Save it as output column name, too */
4173 colinfo->colnames[i] = colname;
4176 /* Remember selected names for use later */
4177 colinfo->usingNames = lappend(colinfo->usingNames, colname);
4178 parentUsing = lappend(parentUsing, colname);
4180 /* Push down to left column, unless it's a system column */
4181 if (leftattnos[i] > 0)
4183 expand_colnames_array_to(leftcolinfo, leftattnos[i]);
4184 leftcolinfo->colnames[leftattnos[i] - 1] = colname;
4187 /* Same on the righthand side */
4188 if (rightattnos[i] > 0)
4190 expand_colnames_array_to(rightcolinfo, rightattnos[i]);
4191 rightcolinfo->colnames[rightattnos[i] - 1] = colname;
4194 i++;
4198 /* Mark child deparse_columns structs with correct parentUsing info */
4199 leftcolinfo->parentUsing = parentUsing;
4200 rightcolinfo->parentUsing = parentUsing;
4202 /* Now recursively assign USING column names in children */
4203 set_using_names(dpns, j->larg, parentUsing);
4204 set_using_names(dpns, j->rarg, parentUsing);
4206 else
4207 elog(ERROR, "unrecognized node type: %d",
4208 (int) nodeTag(jtnode));
4212 * set_relation_column_names: select column aliases for a non-join RTE
4214 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4215 * If any colnames entries are already filled in, those override local
4216 * choices.
4218 static void
4219 set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
4220 deparse_columns *colinfo)
4222 int ncolumns;
4223 char **real_colnames;
4224 bool changed_any;
4225 int noldcolumns;
4226 int i;
4227 int j;
4230 * Extract the RTE's "real" column names. This is comparable to
4231 * get_rte_attribute_name, except that it's important to disregard dropped
4232 * columns. We put NULL into the array for a dropped column.
4234 if (rte->rtekind == RTE_RELATION)
4236 /* Relation --- look to the system catalogs for up-to-date info */
4237 Relation rel;
4238 TupleDesc tupdesc;
4240 rel = relation_open(rte->relid, AccessShareLock);
4241 tupdesc = RelationGetDescr(rel);
4243 ncolumns = tupdesc->natts;
4244 real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4246 for (i = 0; i < ncolumns; i++)
4248 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
4250 if (attr->attisdropped)
4251 real_colnames[i] = NULL;
4252 else
4253 real_colnames[i] = pstrdup(NameStr(attr->attname));
4255 relation_close(rel, AccessShareLock);
4257 else
4259 /* Otherwise use the column names from eref */
4260 ListCell *lc;
4262 ncolumns = list_length(rte->eref->colnames);
4263 real_colnames = (char **) palloc(ncolumns * sizeof(char *));
4265 i = 0;
4266 foreach(lc, rte->eref->colnames)
4269 * If the column name shown in eref is an empty string, then it's
4270 * a column that was dropped at the time of parsing the query, so
4271 * treat it as dropped.
4273 char *cname = strVal(lfirst(lc));
4275 if (cname[0] == '\0')
4276 cname = NULL;
4277 real_colnames[i] = cname;
4278 i++;
4283 * Ensure colinfo->colnames has a slot for each column. (It could be long
4284 * enough already, if we pushed down a name for the last column.) Note:
4285 * it's possible that there are now more columns than there were when the
4286 * query was parsed, ie colnames could be longer than rte->eref->colnames.
4287 * We must assign unique aliases to the new columns too, else there could
4288 * be unresolved conflicts when the view/rule is reloaded.
4290 expand_colnames_array_to(colinfo, ncolumns);
4291 Assert(colinfo->num_cols == ncolumns);
4294 * Make sufficiently large new_colnames and is_new_col arrays, too.
4296 * Note: because we leave colinfo->num_new_cols zero until after the loop,
4297 * colname_is_unique will not consult that array, which is fine because it
4298 * would only be duplicate effort.
4300 colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
4301 colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
4304 * Scan the columns, select a unique alias for each one, and store it in
4305 * colinfo->colnames and colinfo->new_colnames. The former array has NULL
4306 * entries for dropped columns, the latter omits them. Also mark
4307 * new_colnames entries as to whether they are new since parse time; this
4308 * is the case for entries beyond the length of rte->eref->colnames.
4310 noldcolumns = list_length(rte->eref->colnames);
4311 changed_any = false;
4312 j = 0;
4313 for (i = 0; i < ncolumns; i++)
4315 char *real_colname = real_colnames[i];
4316 char *colname = colinfo->colnames[i];
4318 /* Skip dropped columns */
4319 if (real_colname == NULL)
4321 Assert(colname == NULL); /* colnames[i] is already NULL */
4322 continue;
4325 /* If alias already assigned, that's what to use */
4326 if (colname == NULL)
4328 /* If user wrote an alias, prefer that over real column name */
4329 if (rte->alias && i < list_length(rte->alias->colnames))
4330 colname = strVal(list_nth(rte->alias->colnames, i));
4331 else
4332 colname = real_colname;
4334 /* Unique-ify and insert into colinfo */
4335 colname = make_colname_unique(colname, dpns, colinfo);
4337 colinfo->colnames[i] = colname;
4340 /* Put names of non-dropped columns in new_colnames[] too */
4341 colinfo->new_colnames[j] = colname;
4342 /* And mark them as new or not */
4343 colinfo->is_new_col[j] = (i >= noldcolumns);
4344 j++;
4346 /* Remember if any assigned aliases differ from "real" name */
4347 if (!changed_any && strcmp(colname, real_colname) != 0)
4348 changed_any = true;
4352 * Set correct length for new_colnames[] array. (Note: if columns have
4353 * been added, colinfo->num_cols includes them, which is not really quite
4354 * right but is harmless, since any new columns must be at the end where
4355 * they won't affect varattnos of pre-existing columns.)
4357 colinfo->num_new_cols = j;
4360 * For a relation RTE, we need only print the alias column names if any
4361 * are different from the underlying "real" names. For a function RTE,
4362 * always emit a complete column alias list; this is to protect against
4363 * possible instability of the default column names (eg, from altering
4364 * parameter names). For tablefunc RTEs, we never print aliases, because
4365 * the column names are part of the clause itself. For other RTE types,
4366 * print if we changed anything OR if there were user-written column
4367 * aliases (since the latter would be part of the underlying "reality").
4369 if (rte->rtekind == RTE_RELATION)
4370 colinfo->printaliases = changed_any;
4371 else if (rte->rtekind == RTE_FUNCTION)
4372 colinfo->printaliases = true;
4373 else if (rte->rtekind == RTE_TABLEFUNC)
4374 colinfo->printaliases = false;
4375 else if (rte->alias && rte->alias->colnames != NIL)
4376 colinfo->printaliases = true;
4377 else
4378 colinfo->printaliases = changed_any;
4382 * set_join_column_names: select column aliases for a join RTE
4384 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
4385 * If any colnames entries are already filled in, those override local
4386 * choices. Also, names for USING columns were already chosen by
4387 * set_using_names(). We further expect that column alias selection has been
4388 * completed for both input RTEs.
4390 static void
4391 set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
4392 deparse_columns *colinfo)
4394 deparse_columns *leftcolinfo;
4395 deparse_columns *rightcolinfo;
4396 bool changed_any;
4397 int noldcolumns;
4398 int nnewcolumns;
4399 Bitmapset *leftmerged = NULL;
4400 Bitmapset *rightmerged = NULL;
4401 int i;
4402 int j;
4403 int ic;
4404 int jc;
4406 /* Look up the previously-filled-in child deparse_columns structs */
4407 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
4408 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
4411 * Ensure colinfo->colnames has a slot for each column. (It could be long
4412 * enough already, if we pushed down a name for the last column.) Note:
4413 * it's possible that one or both inputs now have more columns than there
4414 * were when the query was parsed, but we'll deal with that below. We
4415 * only need entries in colnames for pre-existing columns.
4417 noldcolumns = list_length(rte->eref->colnames);
4418 expand_colnames_array_to(colinfo, noldcolumns);
4419 Assert(colinfo->num_cols == noldcolumns);
4422 * Scan the join output columns, select an alias for each one, and store
4423 * it in colinfo->colnames. If there are USING columns, set_using_names()
4424 * already selected their names, so we can start the loop at the first
4425 * non-merged column.
4427 changed_any = false;
4428 for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
4430 char *colname = colinfo->colnames[i];
4431 char *real_colname;
4433 /* Join column must refer to at least one input column */
4434 Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
4436 /* Get the child column name */
4437 if (colinfo->leftattnos[i] > 0)
4438 real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
4439 else if (colinfo->rightattnos[i] > 0)
4440 real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
4441 else
4443 /* We're joining system columns --- use eref name */
4444 real_colname = strVal(list_nth(rte->eref->colnames, i));
4447 /* If child col has been dropped, no need to assign a join colname */
4448 if (real_colname == NULL)
4450 colinfo->colnames[i] = NULL;
4451 continue;
4454 /* In an unnamed join, just report child column names as-is */
4455 if (rte->alias == NULL)
4457 colinfo->colnames[i] = real_colname;
4458 continue;
4461 /* If alias already assigned, that's what to use */
4462 if (colname == NULL)
4464 /* If user wrote an alias, prefer that over real column name */
4465 if (rte->alias && i < list_length(rte->alias->colnames))
4466 colname = strVal(list_nth(rte->alias->colnames, i));
4467 else
4468 colname = real_colname;
4470 /* Unique-ify and insert into colinfo */
4471 colname = make_colname_unique(colname, dpns, colinfo);
4473 colinfo->colnames[i] = colname;
4476 /* Remember if any assigned aliases differ from "real" name */
4477 if (!changed_any && strcmp(colname, real_colname) != 0)
4478 changed_any = true;
4482 * Calculate number of columns the join would have if it were re-parsed
4483 * now, and create storage for the new_colnames and is_new_col arrays.
4485 * Note: colname_is_unique will be consulting new_colnames[] during the
4486 * loops below, so its not-yet-filled entries must be zeroes.
4488 nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
4489 list_length(colinfo->usingNames);
4490 colinfo->num_new_cols = nnewcolumns;
4491 colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
4492 colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
4495 * Generating the new_colnames array is a bit tricky since any new columns
4496 * added since parse time must be inserted in the right places. This code
4497 * must match the parser, which will order a join's columns as merged
4498 * columns first (in USING-clause order), then non-merged columns from the
4499 * left input (in attnum order), then non-merged columns from the right
4500 * input (ditto). If one of the inputs is itself a join, its columns will
4501 * be ordered according to the same rule, which means newly-added columns
4502 * might not be at the end. We can figure out what's what by consulting
4503 * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
4505 * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
4506 * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
4507 * meanings for the current child RTE.
4510 /* Handle merged columns; they are first and can't be new */
4511 i = j = 0;
4512 while (i < noldcolumns &&
4513 colinfo->leftattnos[i] != 0 &&
4514 colinfo->rightattnos[i] != 0)
4516 /* column name is already determined and known unique */
4517 colinfo->new_colnames[j] = colinfo->colnames[i];
4518 colinfo->is_new_col[j] = false;
4520 /* build bitmapsets of child attnums of merged columns */
4521 if (colinfo->leftattnos[i] > 0)
4522 leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
4523 if (colinfo->rightattnos[i] > 0)
4524 rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
4526 i++, j++;
4529 /* Handle non-merged left-child columns */
4530 ic = 0;
4531 for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
4533 char *child_colname = leftcolinfo->new_colnames[jc];
4535 if (!leftcolinfo->is_new_col[jc])
4537 /* Advance ic to next non-dropped old column of left child */
4538 while (ic < leftcolinfo->num_cols &&
4539 leftcolinfo->colnames[ic] == NULL)
4540 ic++;
4541 Assert(ic < leftcolinfo->num_cols);
4542 ic++;
4543 /* If it is a merged column, we already processed it */
4544 if (bms_is_member(ic, leftmerged))
4545 continue;
4546 /* Else, advance i to the corresponding existing join column */
4547 while (i < colinfo->num_cols &&
4548 colinfo->colnames[i] == NULL)
4549 i++;
4550 Assert(i < colinfo->num_cols);
4551 Assert(ic == colinfo->leftattnos[i]);
4552 /* Use the already-assigned name of this column */
4553 colinfo->new_colnames[j] = colinfo->colnames[i];
4554 i++;
4556 else
4559 * Unique-ify the new child column name and assign, unless we're
4560 * in an unnamed join, in which case just copy
4562 if (rte->alias != NULL)
4564 colinfo->new_colnames[j] =
4565 make_colname_unique(child_colname, dpns, colinfo);
4566 if (!changed_any &&
4567 strcmp(colinfo->new_colnames[j], child_colname) != 0)
4568 changed_any = true;
4570 else
4571 colinfo->new_colnames[j] = child_colname;
4574 colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
4575 j++;
4578 /* Handle non-merged right-child columns in exactly the same way */
4579 ic = 0;
4580 for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
4582 char *child_colname = rightcolinfo->new_colnames[jc];
4584 if (!rightcolinfo->is_new_col[jc])
4586 /* Advance ic to next non-dropped old column of right child */
4587 while (ic < rightcolinfo->num_cols &&
4588 rightcolinfo->colnames[ic] == NULL)
4589 ic++;
4590 Assert(ic < rightcolinfo->num_cols);
4591 ic++;
4592 /* If it is a merged column, we already processed it */
4593 if (bms_is_member(ic, rightmerged))
4594 continue;
4595 /* Else, advance i to the corresponding existing join column */
4596 while (i < colinfo->num_cols &&
4597 colinfo->colnames[i] == NULL)
4598 i++;
4599 Assert(i < colinfo->num_cols);
4600 Assert(ic == colinfo->rightattnos[i]);
4601 /* Use the already-assigned name of this column */
4602 colinfo->new_colnames[j] = colinfo->colnames[i];
4603 i++;
4605 else
4608 * Unique-ify the new child column name and assign, unless we're
4609 * in an unnamed join, in which case just copy
4611 if (rte->alias != NULL)
4613 colinfo->new_colnames[j] =
4614 make_colname_unique(child_colname, dpns, colinfo);
4615 if (!changed_any &&
4616 strcmp(colinfo->new_colnames[j], child_colname) != 0)
4617 changed_any = true;
4619 else
4620 colinfo->new_colnames[j] = child_colname;
4623 colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
4624 j++;
4627 /* Assert we processed the right number of columns */
4628 #ifdef USE_ASSERT_CHECKING
4629 while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
4630 i++;
4631 Assert(i == colinfo->num_cols);
4632 Assert(j == nnewcolumns);
4633 #endif
4636 * For a named join, print column aliases if we changed any from the child
4637 * names. Unnamed joins cannot print aliases.
4639 if (rte->alias != NULL)
4640 colinfo->printaliases = changed_any;
4641 else
4642 colinfo->printaliases = false;
4646 * colname_is_unique: is colname distinct from already-chosen column names?
4648 * dpns is query-wide info, colinfo is for the column's RTE
4650 static bool
4651 colname_is_unique(const char *colname, deparse_namespace *dpns,
4652 deparse_columns *colinfo)
4654 int i;
4655 ListCell *lc;
4657 /* Check against already-assigned column aliases within RTE */
4658 for (i = 0; i < colinfo->num_cols; i++)
4660 char *oldname = colinfo->colnames[i];
4662 if (oldname && strcmp(oldname, colname) == 0)
4663 return false;
4667 * If we're building a new_colnames array, check that too (this will be
4668 * partially but not completely redundant with the previous checks)
4670 for (i = 0; i < colinfo->num_new_cols; i++)
4672 char *oldname = colinfo->new_colnames[i];
4674 if (oldname && strcmp(oldname, colname) == 0)
4675 return false;
4678 /* Also check against USING-column names that must be globally unique */
4679 foreach(lc, dpns->using_names)
4681 char *oldname = (char *) lfirst(lc);
4683 if (strcmp(oldname, colname) == 0)
4684 return false;
4687 /* Also check against names already assigned for parent-join USING cols */
4688 foreach(lc, colinfo->parentUsing)
4690 char *oldname = (char *) lfirst(lc);
4692 if (strcmp(oldname, colname) == 0)
4693 return false;
4696 return true;
4700 * make_colname_unique: modify colname if necessary to make it unique
4702 * dpns is query-wide info, colinfo is for the column's RTE
4704 static char *
4705 make_colname_unique(char *colname, deparse_namespace *dpns,
4706 deparse_columns *colinfo)
4709 * If the selected name isn't unique, append digits to make it so. For a
4710 * very long input name, we might have to truncate to stay within
4711 * NAMEDATALEN.
4713 if (!colname_is_unique(colname, dpns, colinfo))
4715 int colnamelen = strlen(colname);
4716 char *modname = (char *) palloc(colnamelen + 16);
4717 int i = 0;
4721 i++;
4722 for (;;)
4724 memcpy(modname, colname, colnamelen);
4725 sprintf(modname + colnamelen, "_%d", i);
4726 if (strlen(modname) < NAMEDATALEN)
4727 break;
4728 /* drop chars from colname to keep all the digits */
4729 colnamelen = pg_mbcliplen(colname, colnamelen,
4730 colnamelen - 1);
4732 } while (!colname_is_unique(modname, dpns, colinfo));
4733 colname = modname;
4735 return colname;
4739 * expand_colnames_array_to: make colinfo->colnames at least n items long
4741 * Any added array entries are initialized to zero.
4743 static void
4744 expand_colnames_array_to(deparse_columns *colinfo, int n)
4746 if (n > colinfo->num_cols)
4748 if (colinfo->colnames == NULL)
4749 colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4750 else
4752 colinfo->colnames = (char **) repalloc(colinfo->colnames,
4753 n * sizeof(char *));
4754 memset(colinfo->colnames + colinfo->num_cols, 0,
4755 (n - colinfo->num_cols) * sizeof(char *));
4757 colinfo->num_cols = n;
4762 * identify_join_columns: figure out where columns of a join come from
4764 * Fills the join-specific fields of the colinfo struct, except for
4765 * usingNames which is filled later.
4767 static void
4768 identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
4769 deparse_columns *colinfo)
4771 int numjoincols;
4772 int jcolno;
4773 int rcolno;
4774 ListCell *lc;
4776 /* Extract left/right child RT indexes */
4777 if (IsA(j->larg, RangeTblRef))
4778 colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
4779 else if (IsA(j->larg, JoinExpr))
4780 colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
4781 else
4782 elog(ERROR, "unrecognized node type in jointree: %d",
4783 (int) nodeTag(j->larg));
4784 if (IsA(j->rarg, RangeTblRef))
4785 colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
4786 else if (IsA(j->rarg, JoinExpr))
4787 colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
4788 else
4789 elog(ERROR, "unrecognized node type in jointree: %d",
4790 (int) nodeTag(j->rarg));
4792 /* Assert children will be processed earlier than join in second pass */
4793 Assert(colinfo->leftrti < j->rtindex);
4794 Assert(colinfo->rightrti < j->rtindex);
4796 /* Initialize result arrays with zeroes */
4797 numjoincols = list_length(jrte->joinaliasvars);
4798 Assert(numjoincols == list_length(jrte->eref->colnames));
4799 colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
4800 colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
4803 * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
4804 * Recall that the column(s) merged due to USING are the first column(s)
4805 * of the join output. We need not do anything special while scanning
4806 * joinleftcols, but while scanning joinrightcols we must distinguish
4807 * merged from unmerged columns.
4809 jcolno = 0;
4810 foreach(lc, jrte->joinleftcols)
4812 int leftattno = lfirst_int(lc);
4814 colinfo->leftattnos[jcolno++] = leftattno;
4816 rcolno = 0;
4817 foreach(lc, jrte->joinrightcols)
4819 int rightattno = lfirst_int(lc);
4821 if (rcolno < jrte->joinmergedcols) /* merged column? */
4822 colinfo->rightattnos[rcolno] = rightattno;
4823 else
4824 colinfo->rightattnos[jcolno++] = rightattno;
4825 rcolno++;
4827 Assert(jcolno == numjoincols);
4831 * get_rtable_name: convenience function to get a previously assigned RTE alias
4833 * The RTE must belong to the topmost namespace level in "context".
4835 static char *
4836 get_rtable_name(int rtindex, deparse_context *context)
4838 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
4840 Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4841 return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4845 * set_deparse_plan: set up deparse_namespace to parse subexpressions
4846 * of a given Plan node
4848 * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
4849 * and index_tlist fields. Caller must already have adjusted the ancestors
4850 * list if necessary. Note that the rtable, subplans, and ctes fields do
4851 * not need to change when shifting attention to different plan nodes in a
4852 * single plan tree.
4854 static void
4855 set_deparse_plan(deparse_namespace *dpns, Plan *plan)
4857 dpns->plan = plan;
4860 * We special-case Append and MergeAppend to pretend that the first child
4861 * plan is the OUTER referent; we have to interpret OUTER Vars in their
4862 * tlists according to one of the children, and the first one is the most
4863 * natural choice.
4865 if (IsA(plan, Append))
4866 dpns->outer_plan = linitial(((Append *) plan)->appendplans);
4867 else if (IsA(plan, MergeAppend))
4868 dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
4869 else
4870 dpns->outer_plan = outerPlan(plan);
4872 if (dpns->outer_plan)
4873 dpns->outer_tlist = dpns->outer_plan->targetlist;
4874 else
4875 dpns->outer_tlist = NIL;
4878 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
4879 * use OUTER because that could someday conflict with the normal meaning.)
4880 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
4881 * For a WorkTableScan, locate the parent RecursiveUnion plan node and use
4882 * that as INNER referent.
4884 * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
4885 * excluded expression's tlist. (Similar to the SubqueryScan we don't want
4886 * to reuse OUTER, it's used for RETURNING in some modify table cases,
4887 * although not INSERT .. CONFLICT).
4889 if (IsA(plan, SubqueryScan))
4890 dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
4891 else if (IsA(plan, CteScan))
4892 dpns->inner_plan = list_nth(dpns->subplans,
4893 ((CteScan *) plan)->ctePlanId - 1);
4894 else if (IsA(plan, WorkTableScan))
4895 dpns->inner_plan = find_recursive_union(dpns,
4896 (WorkTableScan *) plan);
4897 else if (IsA(plan, ModifyTable))
4898 dpns->inner_plan = plan;
4899 else
4900 dpns->inner_plan = innerPlan(plan);
4902 if (IsA(plan, ModifyTable))
4903 dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
4904 else if (dpns->inner_plan)
4905 dpns->inner_tlist = dpns->inner_plan->targetlist;
4906 else
4907 dpns->inner_tlist = NIL;
4909 /* Set up referent for INDEX_VAR Vars, if needed */
4910 if (IsA(plan, IndexOnlyScan))
4911 dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
4912 else if (IsA(plan, ForeignScan))
4913 dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
4914 else if (IsA(plan, CustomScan))
4915 dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
4916 else
4917 dpns->index_tlist = NIL;
4921 * Locate the ancestor plan node that is the RecursiveUnion generating
4922 * the WorkTableScan's work table. We can match on wtParam, since that
4923 * should be unique within the plan tree.
4925 static Plan *
4926 find_recursive_union(deparse_namespace *dpns, WorkTableScan *wtscan)
4928 ListCell *lc;
4930 foreach(lc, dpns->ancestors)
4932 Plan *ancestor = (Plan *) lfirst(lc);
4934 if (IsA(ancestor, RecursiveUnion) &&
4935 ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
4936 return ancestor;
4938 elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
4939 wtscan->wtParam);
4940 return NULL;
4944 * push_child_plan: temporarily transfer deparsing attention to a child plan
4946 * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
4947 * deparse context in case the referenced expression itself uses
4948 * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid
4949 * affecting levelsup issues (although in a Plan tree there really shouldn't
4950 * be any).
4952 * Caller must provide a local deparse_namespace variable to save the
4953 * previous state for pop_child_plan.
4955 static void
4956 push_child_plan(deparse_namespace *dpns, Plan *plan,
4957 deparse_namespace *save_dpns)
4959 /* Save state for restoration later */
4960 *save_dpns = *dpns;
4962 /* Link current plan node into ancestors list */
4963 dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
4965 /* Set attention on selected child */
4966 set_deparse_plan(dpns, plan);
4970 * pop_child_plan: undo the effects of push_child_plan
4972 static void
4973 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
4975 List *ancestors;
4977 /* Get rid of ancestors list cell added by push_child_plan */
4978 ancestors = list_delete_first(dpns->ancestors);
4980 /* Restore fields changed by push_child_plan */
4981 *dpns = *save_dpns;
4983 /* Make sure dpns->ancestors is right (may be unnecessary) */
4984 dpns->ancestors = ancestors;
4988 * push_ancestor_plan: temporarily transfer deparsing attention to an
4989 * ancestor plan
4991 * When expanding a Param reference, we must adjust the deparse context
4992 * to match the plan node that contains the expression being printed;
4993 * otherwise we'd fail if that expression itself contains a Param or
4994 * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
4996 * The target ancestor is conveniently identified by the ListCell holding it
4997 * in dpns->ancestors.
4999 * Caller must provide a local deparse_namespace variable to save the
5000 * previous state for pop_ancestor_plan.
5002 static void
5003 push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
5004 deparse_namespace *save_dpns)
5006 Plan *plan = (Plan *) lfirst(ancestor_cell);
5008 /* Save state for restoration later */
5009 *save_dpns = *dpns;
5011 /* Build a new ancestor list with just this node's ancestors */
5012 dpns->ancestors =
5013 list_copy_tail(dpns->ancestors,
5014 list_cell_number(dpns->ancestors, ancestor_cell) + 1);
5016 /* Set attention on selected ancestor */
5017 set_deparse_plan(dpns, plan);
5021 * pop_ancestor_plan: undo the effects of push_ancestor_plan
5023 static void
5024 pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
5026 /* Free the ancestor list made in push_ancestor_plan */
5027 list_free(dpns->ancestors);
5029 /* Restore fields changed by push_ancestor_plan */
5030 *dpns = *save_dpns;
5034 /* ----------
5035 * make_ruledef - reconstruct the CREATE RULE command
5036 * for a given pg_rewrite tuple
5037 * ----------
5039 static void
5040 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
5041 int prettyFlags)
5043 char *rulename;
5044 char ev_type;
5045 Oid ev_class;
5046 bool is_instead;
5047 char *ev_qual;
5048 char *ev_action;
5049 List *actions;
5050 Relation ev_relation;
5051 TupleDesc viewResultDesc = NULL;
5052 int fno;
5053 Datum dat;
5054 bool isnull;
5057 * Get the attribute values from the rules tuple
5059 fno = SPI_fnumber(rulettc, "rulename");
5060 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5061 Assert(!isnull);
5062 rulename = NameStr(*(DatumGetName(dat)));
5064 fno = SPI_fnumber(rulettc, "ev_type");
5065 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5066 Assert(!isnull);
5067 ev_type = DatumGetChar(dat);
5069 fno = SPI_fnumber(rulettc, "ev_class");
5070 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5071 Assert(!isnull);
5072 ev_class = DatumGetObjectId(dat);
5074 fno = SPI_fnumber(rulettc, "is_instead");
5075 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5076 Assert(!isnull);
5077 is_instead = DatumGetBool(dat);
5079 fno = SPI_fnumber(rulettc, "ev_qual");
5080 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5081 Assert(ev_qual != NULL);
5083 fno = SPI_fnumber(rulettc, "ev_action");
5084 ev_action = SPI_getvalue(ruletup, rulettc, fno);
5085 Assert(ev_action != NULL);
5086 actions = (List *) stringToNode(ev_action);
5087 if (actions == NIL)
5088 elog(ERROR, "invalid empty ev_action list");
5090 ev_relation = table_open(ev_class, AccessShareLock);
5093 * Build the rules definition text
5095 appendStringInfo(buf, "CREATE RULE %s AS",
5096 quote_identifier(rulename));
5098 if (prettyFlags & PRETTYFLAG_INDENT)
5099 appendStringInfoString(buf, "\n ON ");
5100 else
5101 appendStringInfoString(buf, " ON ");
5103 /* The event the rule is fired for */
5104 switch (ev_type)
5106 case '1':
5107 appendStringInfoString(buf, "SELECT");
5108 viewResultDesc = RelationGetDescr(ev_relation);
5109 break;
5111 case '2':
5112 appendStringInfoString(buf, "UPDATE");
5113 break;
5115 case '3':
5116 appendStringInfoString(buf, "INSERT");
5117 break;
5119 case '4':
5120 appendStringInfoString(buf, "DELETE");
5121 break;
5123 default:
5124 ereport(ERROR,
5125 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5126 errmsg("rule \"%s\" has unsupported event type %d",
5127 rulename, ev_type)));
5128 break;
5131 /* The relation the rule is fired on */
5132 appendStringInfo(buf, " TO %s",
5133 (prettyFlags & PRETTYFLAG_SCHEMA) ?
5134 generate_relation_name(ev_class, NIL) :
5135 generate_qualified_relation_name(ev_class));
5137 /* If the rule has an event qualification, add it */
5138 if (strcmp(ev_qual, "<>") != 0)
5140 Node *qual;
5141 Query *query;
5142 deparse_context context;
5143 deparse_namespace dpns;
5145 if (prettyFlags & PRETTYFLAG_INDENT)
5146 appendStringInfoString(buf, "\n ");
5147 appendStringInfoString(buf, " WHERE ");
5149 qual = stringToNode(ev_qual);
5152 * We need to make a context for recognizing any Vars in the qual
5153 * (which can only be references to OLD and NEW). Use the rtable of
5154 * the first query in the action list for this purpose.
5156 query = (Query *) linitial(actions);
5159 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
5160 * into the SELECT, and that's what we need to look at. (Ugly kluge
5161 * ... try to fix this when we redesign querytrees.)
5163 query = getInsertSelectQuery(query, NULL);
5165 /* Must acquire locks right away; see notes in get_query_def() */
5166 AcquireRewriteLocks(query, false, false);
5168 context.buf = buf;
5169 context.namespaces = list_make1(&dpns);
5170 context.windowClause = NIL;
5171 context.windowTList = NIL;
5172 context.varprefix = (list_length(query->rtable) != 1);
5173 context.prettyFlags = prettyFlags;
5174 context.wrapColumn = WRAP_COLUMN_DEFAULT;
5175 context.indentLevel = PRETTYINDENT_STD;
5176 context.special_exprkind = EXPR_KIND_NONE;
5177 context.appendparents = NULL;
5179 set_deparse_for_query(&dpns, query, NIL);
5181 get_rule_expr(qual, &context, false);
5184 appendStringInfoString(buf, " DO ");
5186 /* The INSTEAD keyword (if so) */
5187 if (is_instead)
5188 appendStringInfoString(buf, "INSTEAD ");
5190 /* Finally the rules actions */
5191 if (list_length(actions) > 1)
5193 ListCell *action;
5194 Query *query;
5196 appendStringInfoChar(buf, '(');
5197 foreach(action, actions)
5199 query = (Query *) lfirst(action);
5200 get_query_def(query, buf, NIL, viewResultDesc,
5201 prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5202 if (prettyFlags)
5203 appendStringInfoString(buf, ";\n");
5204 else
5205 appendStringInfoString(buf, "; ");
5207 appendStringInfoString(buf, ");");
5209 else
5211 Query *query;
5213 query = (Query *) linitial(actions);
5214 get_query_def(query, buf, NIL, viewResultDesc,
5215 prettyFlags, WRAP_COLUMN_DEFAULT, 0);
5216 appendStringInfoChar(buf, ';');
5219 table_close(ev_relation, AccessShareLock);
5223 /* ----------
5224 * make_viewdef - reconstruct the SELECT part of a
5225 * view rewrite rule
5226 * ----------
5228 static void
5229 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
5230 int prettyFlags, int wrapColumn)
5232 Query *query;
5233 char ev_type;
5234 Oid ev_class;
5235 bool is_instead;
5236 char *ev_qual;
5237 char *ev_action;
5238 List *actions;
5239 Relation ev_relation;
5240 int fno;
5241 Datum dat;
5242 bool isnull;
5245 * Get the attribute values from the rules tuple
5247 fno = SPI_fnumber(rulettc, "ev_type");
5248 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5249 Assert(!isnull);
5250 ev_type = DatumGetChar(dat);
5252 fno = SPI_fnumber(rulettc, "ev_class");
5253 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5254 Assert(!isnull);
5255 ev_class = DatumGetObjectId(dat);
5257 fno = SPI_fnumber(rulettc, "is_instead");
5258 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
5259 Assert(!isnull);
5260 is_instead = DatumGetBool(dat);
5262 fno = SPI_fnumber(rulettc, "ev_qual");
5263 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
5264 Assert(ev_qual != NULL);
5266 fno = SPI_fnumber(rulettc, "ev_action");
5267 ev_action = SPI_getvalue(ruletup, rulettc, fno);
5268 Assert(ev_action != NULL);
5269 actions = (List *) stringToNode(ev_action);
5271 if (list_length(actions) != 1)
5273 /* keep output buffer empty and leave */
5274 return;
5277 query = (Query *) linitial(actions);
5279 if (ev_type != '1' || !is_instead ||
5280 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
5282 /* keep output buffer empty and leave */
5283 return;
5286 ev_relation = table_open(ev_class, AccessShareLock);
5288 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
5289 prettyFlags, wrapColumn, 0);
5290 appendStringInfoChar(buf, ';');
5292 table_close(ev_relation, AccessShareLock);
5296 /* ----------
5297 * get_query_def - Parse back one query parsetree
5299 * If resultDesc is not NULL, then it is the output tuple descriptor for
5300 * the view represented by a SELECT query.
5301 * ----------
5303 static void
5304 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
5305 TupleDesc resultDesc,
5306 int prettyFlags, int wrapColumn, int startIndent)
5308 deparse_context context;
5309 deparse_namespace dpns;
5311 /* Guard against excessively long or deeply-nested queries */
5312 CHECK_FOR_INTERRUPTS();
5313 check_stack_depth();
5316 * Before we begin to examine the query, acquire locks on referenced
5317 * relations, and fix up deleted columns in JOIN RTEs. This ensures
5318 * consistent results. Note we assume it's OK to scribble on the passed
5319 * querytree!
5321 * We are only deparsing the query (we are not about to execute it), so we
5322 * only need AccessShareLock on the relations it mentions.
5324 AcquireRewriteLocks(query, false, false);
5326 context.buf = buf;
5327 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5328 context.windowClause = NIL;
5329 context.windowTList = NIL;
5330 context.varprefix = (parentnamespace != NIL ||
5331 list_length(query->rtable) != 1);
5332 context.prettyFlags = prettyFlags;
5333 context.wrapColumn = wrapColumn;
5334 context.indentLevel = startIndent;
5335 context.special_exprkind = EXPR_KIND_NONE;
5336 context.appendparents = NULL;
5338 set_deparse_for_query(&dpns, query, parentnamespace);
5340 switch (query->commandType)
5342 case CMD_SELECT:
5343 get_select_query_def(query, &context, resultDesc);
5344 break;
5346 case CMD_UPDATE:
5347 get_update_query_def(query, &context);
5348 break;
5350 case CMD_INSERT:
5351 get_insert_query_def(query, &context);
5352 break;
5354 case CMD_DELETE:
5355 get_delete_query_def(query, &context);
5356 break;
5358 case CMD_NOTHING:
5359 appendStringInfoString(buf, "NOTHING");
5360 break;
5362 case CMD_UTILITY:
5363 get_utility_query_def(query, &context);
5364 break;
5366 default:
5367 elog(ERROR, "unrecognized query command type: %d",
5368 query->commandType);
5369 break;
5373 /* ----------
5374 * get_values_def - Parse back a VALUES list
5375 * ----------
5377 static void
5378 get_values_def(List *values_lists, deparse_context *context)
5380 StringInfo buf = context->buf;
5381 bool first_list = true;
5382 ListCell *vtl;
5384 appendStringInfoString(buf, "VALUES ");
5386 foreach(vtl, values_lists)
5388 List *sublist = (List *) lfirst(vtl);
5389 bool first_col = true;
5390 ListCell *lc;
5392 if (first_list)
5393 first_list = false;
5394 else
5395 appendStringInfoString(buf, ", ");
5397 appendStringInfoChar(buf, '(');
5398 foreach(lc, sublist)
5400 Node *col = (Node *) lfirst(lc);
5402 if (first_col)
5403 first_col = false;
5404 else
5405 appendStringInfoChar(buf, ',');
5408 * Print the value. Whole-row Vars need special treatment.
5410 get_rule_expr_toplevel(col, context, false);
5412 appendStringInfoChar(buf, ')');
5416 /* ----------
5417 * get_with_clause - Parse back a WITH clause
5418 * ----------
5420 static void
5421 get_with_clause(Query *query, deparse_context *context)
5423 StringInfo buf = context->buf;
5424 const char *sep;
5425 ListCell *l;
5427 if (query->cteList == NIL)
5428 return;
5430 if (PRETTY_INDENT(context))
5432 context->indentLevel += PRETTYINDENT_STD;
5433 appendStringInfoChar(buf, ' ');
5436 if (query->hasRecursive)
5437 sep = "WITH RECURSIVE ";
5438 else
5439 sep = "WITH ";
5440 foreach(l, query->cteList)
5442 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
5444 appendStringInfoString(buf, sep);
5445 appendStringInfoString(buf, quote_identifier(cte->ctename));
5446 if (cte->aliascolnames)
5448 bool first = true;
5449 ListCell *col;
5451 appendStringInfoChar(buf, '(');
5452 foreach(col, cte->aliascolnames)
5454 if (first)
5455 first = false;
5456 else
5457 appendStringInfoString(buf, ", ");
5458 appendStringInfoString(buf,
5459 quote_identifier(strVal(lfirst(col))));
5461 appendStringInfoChar(buf, ')');
5463 appendStringInfoString(buf, " AS ");
5464 switch (cte->ctematerialized)
5466 case CTEMaterializeDefault:
5467 break;
5468 case CTEMaterializeAlways:
5469 appendStringInfoString(buf, "MATERIALIZED ");
5470 break;
5471 case CTEMaterializeNever:
5472 appendStringInfoString(buf, "NOT MATERIALIZED ");
5473 break;
5475 appendStringInfoChar(buf, '(');
5476 if (PRETTY_INDENT(context))
5477 appendContextKeyword(context, "", 0, 0, 0);
5478 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
5479 context->prettyFlags, context->wrapColumn,
5480 context->indentLevel);
5481 if (PRETTY_INDENT(context))
5482 appendContextKeyword(context, "", 0, 0, 0);
5483 appendStringInfoChar(buf, ')');
5485 if (cte->search_clause)
5487 bool first = true;
5488 ListCell *lc;
5490 appendStringInfo(buf, " SEARCH %s FIRST BY ",
5491 cte->search_clause->search_breadth_first ? "BREADTH" : "DEPTH");
5493 foreach(lc, cte->search_clause->search_col_list)
5495 if (first)
5496 first = false;
5497 else
5498 appendStringInfoString(buf, ", ");
5499 appendStringInfoString(buf,
5500 quote_identifier(strVal(lfirst(lc))));
5503 appendStringInfo(buf, " SET %s", quote_identifier(cte->search_clause->search_seq_column));
5506 if (cte->cycle_clause)
5508 bool first = true;
5509 ListCell *lc;
5511 appendStringInfoString(buf, " CYCLE ");
5513 foreach(lc, cte->cycle_clause->cycle_col_list)
5515 if (first)
5516 first = false;
5517 else
5518 appendStringInfoString(buf, ", ");
5519 appendStringInfoString(buf,
5520 quote_identifier(strVal(lfirst(lc))));
5523 appendStringInfo(buf, " SET %s", quote_identifier(cte->cycle_clause->cycle_mark_column));
5526 Const *cmv = castNode(Const, cte->cycle_clause->cycle_mark_value);
5527 Const *cmd = castNode(Const, cte->cycle_clause->cycle_mark_default);
5529 if (!(cmv->consttype == BOOLOID && !cmv->constisnull && DatumGetBool(cmv->constvalue) == true &&
5530 cmd->consttype == BOOLOID && !cmd->constisnull && DatumGetBool(cmd->constvalue) == false))
5532 appendStringInfoString(buf, " TO ");
5533 get_rule_expr(cte->cycle_clause->cycle_mark_value, context, false);
5534 appendStringInfoString(buf, " DEFAULT ");
5535 get_rule_expr(cte->cycle_clause->cycle_mark_default, context, false);
5539 appendStringInfo(buf, " USING %s", quote_identifier(cte->cycle_clause->cycle_path_column));
5542 sep = ", ";
5545 if (PRETTY_INDENT(context))
5547 context->indentLevel -= PRETTYINDENT_STD;
5548 appendContextKeyword(context, "", 0, 0, 0);
5550 else
5551 appendStringInfoChar(buf, ' ');
5554 /* ----------
5555 * get_select_query_def - Parse back a SELECT parsetree
5556 * ----------
5558 static void
5559 get_select_query_def(Query *query, deparse_context *context,
5560 TupleDesc resultDesc)
5562 StringInfo buf = context->buf;
5563 List *save_windowclause;
5564 List *save_windowtlist;
5565 bool force_colno;
5566 ListCell *l;
5568 /* Insert the WITH clause if given */
5569 get_with_clause(query, context);
5571 /* Set up context for possible window functions */
5572 save_windowclause = context->windowClause;
5573 context->windowClause = query->windowClause;
5574 save_windowtlist = context->windowTList;
5575 context->windowTList = query->targetList;
5578 * If the Query node has a setOperations tree, then it's the top level of
5579 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
5580 * fields are interesting in the top query itself.
5582 if (query->setOperations)
5584 get_setop_query(query->setOperations, query, context, resultDesc);
5585 /* ORDER BY clauses must be simple in this case */
5586 force_colno = true;
5588 else
5590 get_basic_select_query(query, context, resultDesc);
5591 force_colno = false;
5594 /* Add the ORDER BY clause if given */
5595 if (query->sortClause != NIL)
5597 appendContextKeyword(context, " ORDER BY ",
5598 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5599 get_rule_orderby(query->sortClause, query->targetList,
5600 force_colno, context);
5604 * Add the LIMIT/OFFSET clauses if given. If non-default options, use the
5605 * standard spelling of LIMIT.
5607 if (query->limitOffset != NULL)
5609 appendContextKeyword(context, " OFFSET ",
5610 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5611 get_rule_expr(query->limitOffset, context, false);
5613 if (query->limitCount != NULL)
5615 if (query->limitOption == LIMIT_OPTION_WITH_TIES)
5617 appendContextKeyword(context, " FETCH FIRST ",
5618 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5619 get_rule_expr(query->limitCount, context, false);
5620 appendStringInfoString(buf, " ROWS WITH TIES");
5622 else
5624 appendContextKeyword(context, " LIMIT ",
5625 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5626 if (IsA(query->limitCount, Const) &&
5627 ((Const *) query->limitCount)->constisnull)
5628 appendStringInfoString(buf, "ALL");
5629 else
5630 get_rule_expr(query->limitCount, context, false);
5634 /* Add FOR [KEY] UPDATE/SHARE clauses if present */
5635 if (query->hasForUpdate)
5637 foreach(l, query->rowMarks)
5639 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
5641 /* don't print implicit clauses */
5642 if (rc->pushedDown)
5643 continue;
5645 switch (rc->strength)
5647 case LCS_NONE:
5648 /* we intentionally throw an error for LCS_NONE */
5649 elog(ERROR, "unrecognized LockClauseStrength %d",
5650 (int) rc->strength);
5651 break;
5652 case LCS_FORKEYSHARE:
5653 appendContextKeyword(context, " FOR KEY SHARE",
5654 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5655 break;
5656 case LCS_FORSHARE:
5657 appendContextKeyword(context, " FOR SHARE",
5658 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5659 break;
5660 case LCS_FORNOKEYUPDATE:
5661 appendContextKeyword(context, " FOR NO KEY UPDATE",
5662 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5663 break;
5664 case LCS_FORUPDATE:
5665 appendContextKeyword(context, " FOR UPDATE",
5666 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5667 break;
5670 appendStringInfo(buf, " OF %s",
5671 quote_identifier(get_rtable_name(rc->rti,
5672 context)));
5673 if (rc->waitPolicy == LockWaitError)
5674 appendStringInfoString(buf, " NOWAIT");
5675 else if (rc->waitPolicy == LockWaitSkip)
5676 appendStringInfoString(buf, " SKIP LOCKED");
5680 context->windowClause = save_windowclause;
5681 context->windowTList = save_windowtlist;
5685 * Detect whether query looks like SELECT ... FROM VALUES(),
5686 * with no need to rename the output columns of the VALUES RTE.
5687 * If so, return the VALUES RTE. Otherwise return NULL.
5689 static RangeTblEntry *
5690 get_simple_values_rte(Query *query, TupleDesc resultDesc)
5692 RangeTblEntry *result = NULL;
5693 ListCell *lc;
5696 * We want to detect a match even if the Query also contains OLD or NEW
5697 * rule RTEs. So the idea is to scan the rtable and see if there is only
5698 * one inFromCl RTE that is a VALUES RTE.
5700 foreach(lc, query->rtable)
5702 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
5704 if (rte->rtekind == RTE_VALUES && rte->inFromCl)
5706 if (result)
5707 return NULL; /* multiple VALUES (probably not possible) */
5708 result = rte;
5710 else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
5711 continue; /* ignore rule entries */
5712 else
5713 return NULL; /* something else -> not simple VALUES */
5717 * We don't need to check the targetlist in any great detail, because
5718 * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
5719 * appear inside auto-generated sub-queries with very restricted
5720 * structure. However, DefineView might have modified the tlist by
5721 * injecting new column aliases, or we might have some other column
5722 * aliases forced by a resultDesc. We can only simplify if the RTE's
5723 * column names match the names that get_target_list() would select.
5725 if (result)
5727 ListCell *lcn;
5728 int colno;
5730 if (list_length(query->targetList) != list_length(result->eref->colnames))
5731 return NULL; /* this probably cannot happen */
5732 colno = 0;
5733 forboth(lc, query->targetList, lcn, result->eref->colnames)
5735 TargetEntry *tle = (TargetEntry *) lfirst(lc);
5736 char *cname = strVal(lfirst(lcn));
5737 char *colname;
5739 if (tle->resjunk)
5740 return NULL; /* this probably cannot happen */
5742 /* compute name that get_target_list would use for column */
5743 colno++;
5744 if (resultDesc && colno <= resultDesc->natts)
5745 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5746 else
5747 colname = tle->resname;
5749 /* does it match the VALUES RTE? */
5750 if (colname == NULL || strcmp(colname, cname) != 0)
5751 return NULL; /* column name has been changed */
5755 return result;
5758 static void
5759 get_basic_select_query(Query *query, deparse_context *context,
5760 TupleDesc resultDesc)
5762 StringInfo buf = context->buf;
5763 RangeTblEntry *values_rte;
5764 char *sep;
5765 ListCell *l;
5767 if (PRETTY_INDENT(context))
5769 context->indentLevel += PRETTYINDENT_STD;
5770 appendStringInfoChar(buf, ' ');
5774 * If the query looks like SELECT * FROM (VALUES ...), then print just the
5775 * VALUES part. This reverses what transformValuesClause() did at parse
5776 * time.
5778 values_rte = get_simple_values_rte(query, resultDesc);
5779 if (values_rte)
5781 get_values_def(values_rte->values_lists, context);
5782 return;
5786 * Build up the query string - first we say SELECT
5788 if (query->isReturn)
5789 appendStringInfoString(buf, "RETURN");
5790 else
5791 appendStringInfoString(buf, "SELECT");
5793 /* Add the DISTINCT clause if given */
5794 if (query->distinctClause != NIL)
5796 if (query->hasDistinctOn)
5798 appendStringInfoString(buf, " DISTINCT ON (");
5799 sep = "";
5800 foreach(l, query->distinctClause)
5802 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5804 appendStringInfoString(buf, sep);
5805 get_rule_sortgroupclause(srt->tleSortGroupRef, query->targetList,
5806 false, context);
5807 sep = ", ";
5809 appendStringInfoChar(buf, ')');
5811 else
5812 appendStringInfoString(buf, " DISTINCT");
5815 /* Then we tell what to select (the targetlist) */
5816 get_target_list(query->targetList, context, resultDesc);
5818 /* Add the FROM clause if needed */
5819 get_from_clause(query, " FROM ", context);
5821 /* Add the WHERE clause if given */
5822 if (query->jointree->quals != NULL)
5824 appendContextKeyword(context, " WHERE ",
5825 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5826 get_rule_expr(query->jointree->quals, context, false);
5829 /* Add the GROUP BY clause if given */
5830 if (query->groupClause != NULL || query->groupingSets != NULL)
5832 ParseExprKind save_exprkind;
5834 appendContextKeyword(context, " GROUP BY ",
5835 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
5836 if (query->groupDistinct)
5837 appendStringInfoString(buf, "DISTINCT ");
5839 save_exprkind = context->special_exprkind;
5840 context->special_exprkind = EXPR_KIND_GROUP_BY;
5842 if (query->groupingSets == NIL)
5844 sep = "";
5845 foreach(l, query->groupClause)
5847 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5849 appendStringInfoString(buf, sep);
5850 get_rule_sortgroupclause(grp->tleSortGroupRef, query->targetList,
5851 false, context);
5852 sep = ", ";
5855 else
5857 sep = "";
5858 foreach(l, query->groupingSets)
5860 GroupingSet *grp = lfirst(l);
5862 appendStringInfoString(buf, sep);
5863 get_rule_groupingset(grp, query->targetList, true, context);
5864 sep = ", ";
5868 context->special_exprkind = save_exprkind;
5871 /* Add the HAVING clause if given */
5872 if (query->havingQual != NULL)
5874 appendContextKeyword(context, " HAVING ",
5875 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5876 get_rule_expr(query->havingQual, context, false);
5879 /* Add the WINDOW clause if needed */
5880 if (query->windowClause != NIL)
5881 get_rule_windowclause(query, context);
5884 /* ----------
5885 * get_target_list - Parse back a SELECT target list
5887 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
5888 * ----------
5890 static void
5891 get_target_list(List *targetList, deparse_context *context,
5892 TupleDesc resultDesc)
5894 StringInfo buf = context->buf;
5895 StringInfoData targetbuf;
5896 bool last_was_multiline = false;
5897 char *sep;
5898 int colno;
5899 ListCell *l;
5901 /* we use targetbuf to hold each TLE's text temporarily */
5902 initStringInfo(&targetbuf);
5904 sep = " ";
5905 colno = 0;
5906 foreach(l, targetList)
5908 TargetEntry *tle = (TargetEntry *) lfirst(l);
5909 char *colname;
5910 char *attname;
5912 if (tle->resjunk)
5913 continue; /* ignore junk entries */
5915 appendStringInfoString(buf, sep);
5916 sep = ", ";
5917 colno++;
5920 * Put the new field text into targetbuf so we can decide after we've
5921 * got it whether or not it needs to go on a new line.
5923 resetStringInfo(&targetbuf);
5924 context->buf = &targetbuf;
5927 * We special-case Var nodes rather than using get_rule_expr. This is
5928 * needed because get_rule_expr will display a whole-row Var as
5929 * "foo.*", which is the preferred notation in most contexts, but at
5930 * the top level of a SELECT list it's not right (the parser will
5931 * expand that notation into multiple columns, yielding behavior
5932 * different from a whole-row Var). We need to call get_variable
5933 * directly so that we can tell it to do the right thing, and so that
5934 * we can get the attribute name which is the default AS label.
5936 if (tle->expr && (IsA(tle->expr, Var)))
5938 attname = get_variable((Var *) tle->expr, 0, true, context);
5940 else
5942 get_rule_expr((Node *) tle->expr, context, true);
5943 /* We'll show the AS name unless it's this: */
5944 attname = "?column?";
5948 * Figure out what the result column should be called. In the context
5949 * of a view, use the view's tuple descriptor (so as to pick up the
5950 * effects of any column RENAME that's been done on the view).
5951 * Otherwise, just use what we can find in the TLE.
5953 if (resultDesc && colno <= resultDesc->natts)
5954 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
5955 else
5956 colname = tle->resname;
5958 /* Show AS unless the column's name is correct as-is */
5959 if (colname) /* resname could be NULL */
5961 if (attname == NULL || strcmp(attname, colname) != 0)
5962 appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
5965 /* Restore context's output buffer */
5966 context->buf = buf;
5968 /* Consider line-wrapping if enabled */
5969 if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
5971 int leading_nl_pos;
5973 /* Does the new field start with a new line? */
5974 if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
5975 leading_nl_pos = 0;
5976 else
5977 leading_nl_pos = -1;
5979 /* If so, we shouldn't add anything */
5980 if (leading_nl_pos >= 0)
5982 /* instead, remove any trailing spaces currently in buf */
5983 removeStringInfoSpaces(buf);
5985 else
5987 char *trailing_nl;
5989 /* Locate the start of the current line in the output buffer */
5990 trailing_nl = strrchr(buf->data, '\n');
5991 if (trailing_nl == NULL)
5992 trailing_nl = buf->data;
5993 else
5994 trailing_nl++;
5997 * Add a newline, plus some indentation, if the new field is
5998 * not the first and either the new field would cause an
5999 * overflow or the last field used more than one line.
6001 if (colno > 1 &&
6002 ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
6003 last_was_multiline))
6004 appendContextKeyword(context, "", -PRETTYINDENT_STD,
6005 PRETTYINDENT_STD, PRETTYINDENT_VAR);
6008 /* Remember this field's multiline status for next iteration */
6009 last_was_multiline =
6010 (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
6013 /* Add the new field */
6014 appendBinaryStringInfo(buf, targetbuf.data, targetbuf.len);
6017 /* clean up */
6018 pfree(targetbuf.data);
6021 static void
6022 get_setop_query(Node *setOp, Query *query, deparse_context *context,
6023 TupleDesc resultDesc)
6025 StringInfo buf = context->buf;
6026 bool need_paren;
6028 /* Guard against excessively long or deeply-nested queries */
6029 CHECK_FOR_INTERRUPTS();
6030 check_stack_depth();
6032 if (IsA(setOp, RangeTblRef))
6034 RangeTblRef *rtr = (RangeTblRef *) setOp;
6035 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
6036 Query *subquery = rte->subquery;
6038 Assert(subquery != NULL);
6039 Assert(subquery->setOperations == NULL);
6040 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
6041 need_paren = (subquery->cteList ||
6042 subquery->sortClause ||
6043 subquery->rowMarks ||
6044 subquery->limitOffset ||
6045 subquery->limitCount);
6046 if (need_paren)
6047 appendStringInfoChar(buf, '(');
6048 get_query_def(subquery, buf, context->namespaces, resultDesc,
6049 context->prettyFlags, context->wrapColumn,
6050 context->indentLevel);
6051 if (need_paren)
6052 appendStringInfoChar(buf, ')');
6054 else if (IsA(setOp, SetOperationStmt))
6056 SetOperationStmt *op = (SetOperationStmt *) setOp;
6057 int subindent;
6060 * We force parens when nesting two SetOperationStmts, except when the
6061 * lefthand input is another setop of the same kind. Syntactically,
6062 * we could omit parens in rather more cases, but it seems best to use
6063 * parens to flag cases where the setop operator changes. If we use
6064 * parens, we also increase the indentation level for the child query.
6066 * There are some cases in which parens are needed around a leaf query
6067 * too, but those are more easily handled at the next level down (see
6068 * code above).
6070 if (IsA(op->larg, SetOperationStmt))
6072 SetOperationStmt *lop = (SetOperationStmt *) op->larg;
6074 if (op->op == lop->op && op->all == lop->all)
6075 need_paren = false;
6076 else
6077 need_paren = true;
6079 else
6080 need_paren = false;
6082 if (need_paren)
6084 appendStringInfoChar(buf, '(');
6085 subindent = PRETTYINDENT_STD;
6086 appendContextKeyword(context, "", subindent, 0, 0);
6088 else
6089 subindent = 0;
6091 get_setop_query(op->larg, query, context, resultDesc);
6093 if (need_paren)
6094 appendContextKeyword(context, ") ", -subindent, 0, 0);
6095 else if (PRETTY_INDENT(context))
6096 appendContextKeyword(context, "", -subindent, 0, 0);
6097 else
6098 appendStringInfoChar(buf, ' ');
6100 switch (op->op)
6102 case SETOP_UNION:
6103 appendStringInfoString(buf, "UNION ");
6104 break;
6105 case SETOP_INTERSECT:
6106 appendStringInfoString(buf, "INTERSECT ");
6107 break;
6108 case SETOP_EXCEPT:
6109 appendStringInfoString(buf, "EXCEPT ");
6110 break;
6111 default:
6112 elog(ERROR, "unrecognized set op: %d",
6113 (int) op->op);
6115 if (op->all)
6116 appendStringInfoString(buf, "ALL ");
6118 /* Always parenthesize if RHS is another setop */
6119 need_paren = IsA(op->rarg, SetOperationStmt);
6122 * The indentation code here is deliberately a bit different from that
6123 * for the lefthand input, because we want the line breaks in
6124 * different places.
6126 if (need_paren)
6128 appendStringInfoChar(buf, '(');
6129 subindent = PRETTYINDENT_STD;
6131 else
6132 subindent = 0;
6133 appendContextKeyword(context, "", subindent, 0, 0);
6135 get_setop_query(op->rarg, query, context, resultDesc);
6137 if (PRETTY_INDENT(context))
6138 context->indentLevel -= subindent;
6139 if (need_paren)
6140 appendContextKeyword(context, ")", 0, 0, 0);
6142 else
6144 elog(ERROR, "unrecognized node type: %d",
6145 (int) nodeTag(setOp));
6150 * Display a sort/group clause.
6152 * Also returns the expression tree, so caller need not find it again.
6154 static Node *
6155 get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
6156 deparse_context *context)
6158 StringInfo buf = context->buf;
6159 TargetEntry *tle;
6160 Node *expr;
6162 tle = get_sortgroupref_tle(ref, tlist);
6163 expr = (Node *) tle->expr;
6166 * Use column-number form if requested by caller. Otherwise, if
6167 * expression is a constant, force it to be dumped with an explicit cast
6168 * as decoration --- this is because a simple integer constant is
6169 * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
6170 * dump it without any decoration. If it's anything more complex than a
6171 * simple Var, then force extra parens around it, to ensure it can't be
6172 * misinterpreted as a cube() or rollup() construct.
6174 if (force_colno)
6176 Assert(!tle->resjunk);
6177 appendStringInfo(buf, "%d", tle->resno);
6179 else if (expr && IsA(expr, Const))
6180 get_const_expr((Const *) expr, context, 1);
6181 else if (!expr || IsA(expr, Var))
6182 get_rule_expr(expr, context, true);
6183 else
6186 * We must force parens for function-like expressions even if
6187 * PRETTY_PAREN is off, since those are the ones in danger of
6188 * misparsing. For other expressions we need to force them only if
6189 * PRETTY_PAREN is on, since otherwise the expression will output them
6190 * itself. (We can't skip the parens.)
6192 bool need_paren = (PRETTY_PAREN(context)
6193 || IsA(expr, FuncExpr)
6194 || IsA(expr, Aggref)
6195 || IsA(expr, WindowFunc));
6197 if (need_paren)
6198 appendStringInfoChar(context->buf, '(');
6199 get_rule_expr(expr, context, true);
6200 if (need_paren)
6201 appendStringInfoChar(context->buf, ')');
6204 return expr;
6208 * Display a GroupingSet
6210 static void
6211 get_rule_groupingset(GroupingSet *gset, List *targetlist,
6212 bool omit_parens, deparse_context *context)
6214 ListCell *l;
6215 StringInfo buf = context->buf;
6216 bool omit_child_parens = true;
6217 char *sep = "";
6219 switch (gset->kind)
6221 case GROUPING_SET_EMPTY:
6222 appendStringInfoString(buf, "()");
6223 return;
6225 case GROUPING_SET_SIMPLE:
6227 if (!omit_parens || list_length(gset->content) != 1)
6228 appendStringInfoChar(buf, '(');
6230 foreach(l, gset->content)
6232 Index ref = lfirst_int(l);
6234 appendStringInfoString(buf, sep);
6235 get_rule_sortgroupclause(ref, targetlist,
6236 false, context);
6237 sep = ", ";
6240 if (!omit_parens || list_length(gset->content) != 1)
6241 appendStringInfoChar(buf, ')');
6243 return;
6245 case GROUPING_SET_ROLLUP:
6246 appendStringInfoString(buf, "ROLLUP(");
6247 break;
6248 case GROUPING_SET_CUBE:
6249 appendStringInfoString(buf, "CUBE(");
6250 break;
6251 case GROUPING_SET_SETS:
6252 appendStringInfoString(buf, "GROUPING SETS (");
6253 omit_child_parens = false;
6254 break;
6257 foreach(l, gset->content)
6259 appendStringInfoString(buf, sep);
6260 get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context);
6261 sep = ", ";
6264 appendStringInfoChar(buf, ')');
6268 * Display an ORDER BY list.
6270 static void
6271 get_rule_orderby(List *orderList, List *targetList,
6272 bool force_colno, deparse_context *context)
6274 StringInfo buf = context->buf;
6275 const char *sep;
6276 ListCell *l;
6278 sep = "";
6279 foreach(l, orderList)
6281 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
6282 Node *sortexpr;
6283 Oid sortcoltype;
6284 TypeCacheEntry *typentry;
6286 appendStringInfoString(buf, sep);
6287 sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList,
6288 force_colno, context);
6289 sortcoltype = exprType(sortexpr);
6290 /* See whether operator is default < or > for datatype */
6291 typentry = lookup_type_cache(sortcoltype,
6292 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
6293 if (srt->sortop == typentry->lt_opr)
6295 /* ASC is default, so emit nothing for it */
6296 if (srt->nulls_first)
6297 appendStringInfoString(buf, " NULLS FIRST");
6299 else if (srt->sortop == typentry->gt_opr)
6301 appendStringInfoString(buf, " DESC");
6302 /* DESC defaults to NULLS FIRST */
6303 if (!srt->nulls_first)
6304 appendStringInfoString(buf, " NULLS LAST");
6306 else
6308 appendStringInfo(buf, " USING %s",
6309 generate_operator_name(srt->sortop,
6310 sortcoltype,
6311 sortcoltype));
6312 /* be specific to eliminate ambiguity */
6313 if (srt->nulls_first)
6314 appendStringInfoString(buf, " NULLS FIRST");
6315 else
6316 appendStringInfoString(buf, " NULLS LAST");
6318 sep = ", ";
6323 * Display a WINDOW clause.
6325 * Note that the windowClause list might contain only anonymous window
6326 * specifications, in which case we should print nothing here.
6328 static void
6329 get_rule_windowclause(Query *query, deparse_context *context)
6331 StringInfo buf = context->buf;
6332 const char *sep;
6333 ListCell *l;
6335 sep = NULL;
6336 foreach(l, query->windowClause)
6338 WindowClause *wc = (WindowClause *) lfirst(l);
6340 if (wc->name == NULL)
6341 continue; /* ignore anonymous windows */
6343 if (sep == NULL)
6344 appendContextKeyword(context, " WINDOW ",
6345 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6346 else
6347 appendStringInfoString(buf, sep);
6349 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
6351 get_rule_windowspec(wc, query->targetList, context);
6353 sep = ", ";
6358 * Display a window definition
6360 static void
6361 get_rule_windowspec(WindowClause *wc, List *targetList,
6362 deparse_context *context)
6364 StringInfo buf = context->buf;
6365 bool needspace = false;
6366 const char *sep;
6367 ListCell *l;
6369 appendStringInfoChar(buf, '(');
6370 if (wc->refname)
6372 appendStringInfoString(buf, quote_identifier(wc->refname));
6373 needspace = true;
6375 /* partition clauses are always inherited, so only print if no refname */
6376 if (wc->partitionClause && !wc->refname)
6378 if (needspace)
6379 appendStringInfoChar(buf, ' ');
6380 appendStringInfoString(buf, "PARTITION BY ");
6381 sep = "";
6382 foreach(l, wc->partitionClause)
6384 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
6386 appendStringInfoString(buf, sep);
6387 get_rule_sortgroupclause(grp->tleSortGroupRef, targetList,
6388 false, context);
6389 sep = ", ";
6391 needspace = true;
6393 /* print ordering clause only if not inherited */
6394 if (wc->orderClause && !wc->copiedOrder)
6396 if (needspace)
6397 appendStringInfoChar(buf, ' ');
6398 appendStringInfoString(buf, "ORDER BY ");
6399 get_rule_orderby(wc->orderClause, targetList, false, context);
6400 needspace = true;
6402 /* framing clause is never inherited, so print unless it's default */
6403 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
6405 if (needspace)
6406 appendStringInfoChar(buf, ' ');
6407 if (wc->frameOptions & FRAMEOPTION_RANGE)
6408 appendStringInfoString(buf, "RANGE ");
6409 else if (wc->frameOptions & FRAMEOPTION_ROWS)
6410 appendStringInfoString(buf, "ROWS ");
6411 else if (wc->frameOptions & FRAMEOPTION_GROUPS)
6412 appendStringInfoString(buf, "GROUPS ");
6413 else
6414 Assert(false);
6415 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
6416 appendStringInfoString(buf, "BETWEEN ");
6417 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
6418 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
6419 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
6420 appendStringInfoString(buf, "CURRENT ROW ");
6421 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET)
6423 get_rule_expr(wc->startOffset, context, false);
6424 if (wc->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
6425 appendStringInfoString(buf, " PRECEDING ");
6426 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
6427 appendStringInfoString(buf, " FOLLOWING ");
6428 else
6429 Assert(false);
6431 else
6432 Assert(false);
6433 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
6435 appendStringInfoString(buf, "AND ");
6436 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
6437 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
6438 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
6439 appendStringInfoString(buf, "CURRENT ROW ");
6440 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET)
6442 get_rule_expr(wc->endOffset, context, false);
6443 if (wc->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
6444 appendStringInfoString(buf, " PRECEDING ");
6445 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
6446 appendStringInfoString(buf, " FOLLOWING ");
6447 else
6448 Assert(false);
6450 else
6451 Assert(false);
6453 if (wc->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
6454 appendStringInfoString(buf, "EXCLUDE CURRENT ROW ");
6455 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
6456 appendStringInfoString(buf, "EXCLUDE GROUP ");
6457 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
6458 appendStringInfoString(buf, "EXCLUDE TIES ");
6459 /* we will now have a trailing space; remove it */
6460 buf->len--;
6462 appendStringInfoChar(buf, ')');
6465 /* ----------
6466 * get_insert_query_def - Parse back an INSERT parsetree
6467 * ----------
6469 static void
6470 get_insert_query_def(Query *query, deparse_context *context)
6472 StringInfo buf = context->buf;
6473 RangeTblEntry *select_rte = NULL;
6474 RangeTblEntry *values_rte = NULL;
6475 RangeTblEntry *rte;
6476 char *sep;
6477 ListCell *l;
6478 List *strippedexprs;
6480 /* Insert the WITH clause if given */
6481 get_with_clause(query, context);
6484 * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6485 * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6487 foreach(l, query->rtable)
6489 rte = (RangeTblEntry *) lfirst(l);
6491 if (rte->rtekind == RTE_SUBQUERY)
6493 if (select_rte)
6494 elog(ERROR, "too many subquery RTEs in INSERT");
6495 select_rte = rte;
6498 if (rte->rtekind == RTE_VALUES)
6500 if (values_rte)
6501 elog(ERROR, "too many values RTEs in INSERT");
6502 values_rte = rte;
6505 if (select_rte && values_rte)
6506 elog(ERROR, "both subquery and values RTEs in INSERT");
6509 * Start the query with INSERT INTO relname
6511 rte = rt_fetch(query->resultRelation, query->rtable);
6512 Assert(rte->rtekind == RTE_RELATION);
6514 if (PRETTY_INDENT(context))
6516 context->indentLevel += PRETTYINDENT_STD;
6517 appendStringInfoChar(buf, ' ');
6519 appendStringInfo(buf, "INSERT INTO %s ",
6520 generate_relation_name(rte->relid, NIL));
6521 /* INSERT requires AS keyword for target alias */
6522 if (rte->alias != NULL)
6523 appendStringInfo(buf, "AS %s ",
6524 quote_identifier(rte->alias->aliasname));
6527 * Add the insert-column-names list. Any indirection decoration needed on
6528 * the column names can be inferred from the top targetlist.
6530 strippedexprs = NIL;
6531 sep = "";
6532 if (query->targetList)
6533 appendStringInfoChar(buf, '(');
6534 foreach(l, query->targetList)
6536 TargetEntry *tle = (TargetEntry *) lfirst(l);
6538 if (tle->resjunk)
6539 continue; /* ignore junk entries */
6541 appendStringInfoString(buf, sep);
6542 sep = ", ";
6545 * Put out name of target column; look in the catalogs, not at
6546 * tle->resname, since resname will fail to track RENAME.
6548 appendStringInfoString(buf,
6549 quote_identifier(get_attname(rte->relid,
6550 tle->resno,
6551 false)));
6554 * Print any indirection needed (subfields or subscripts), and strip
6555 * off the top-level nodes representing the indirection assignments.
6556 * Add the stripped expressions to strippedexprs. (If it's a
6557 * single-VALUES statement, the stripped expressions are the VALUES to
6558 * print below. Otherwise they're just Vars and not really
6559 * interesting.)
6561 strippedexprs = lappend(strippedexprs,
6562 processIndirection((Node *) tle->expr,
6563 context));
6565 if (query->targetList)
6566 appendStringInfoString(buf, ") ");
6568 if (query->override)
6570 if (query->override == OVERRIDING_SYSTEM_VALUE)
6571 appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6572 else if (query->override == OVERRIDING_USER_VALUE)
6573 appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6576 if (select_rte)
6578 /* Add the SELECT */
6579 get_query_def(select_rte->subquery, buf, context->namespaces, NULL,
6580 context->prettyFlags, context->wrapColumn,
6581 context->indentLevel);
6583 else if (values_rte)
6585 /* Add the multi-VALUES expression lists */
6586 get_values_def(values_rte->values_lists, context);
6588 else if (strippedexprs)
6590 /* Add the single-VALUES expression list */
6591 appendContextKeyword(context, "VALUES (",
6592 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6593 get_rule_expr((Node *) strippedexprs, context, false);
6594 appendStringInfoChar(buf, ')');
6596 else
6598 /* No expressions, so it must be DEFAULT VALUES */
6599 appendStringInfoString(buf, "DEFAULT VALUES");
6602 /* Add ON CONFLICT if present */
6603 if (query->onConflict)
6605 OnConflictExpr *confl = query->onConflict;
6607 appendStringInfoString(buf, " ON CONFLICT");
6609 if (confl->arbiterElems)
6611 /* Add the single-VALUES expression list */
6612 appendStringInfoChar(buf, '(');
6613 get_rule_expr((Node *) confl->arbiterElems, context, false);
6614 appendStringInfoChar(buf, ')');
6616 /* Add a WHERE clause (for partial indexes) if given */
6617 if (confl->arbiterWhere != NULL)
6619 bool save_varprefix;
6622 * Force non-prefixing of Vars, since parser assumes that they
6623 * belong to target relation. WHERE clause does not use
6624 * InferenceElem, so this is separately required.
6626 save_varprefix = context->varprefix;
6627 context->varprefix = false;
6629 appendContextKeyword(context, " WHERE ",
6630 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6631 get_rule_expr(confl->arbiterWhere, context, false);
6633 context->varprefix = save_varprefix;
6636 else if (OidIsValid(confl->constraint))
6638 char *constraint = get_constraint_name(confl->constraint);
6640 if (!constraint)
6641 elog(ERROR, "cache lookup failed for constraint %u",
6642 confl->constraint);
6643 appendStringInfo(buf, " ON CONSTRAINT %s",
6644 quote_identifier(constraint));
6647 if (confl->action == ONCONFLICT_NOTHING)
6649 appendStringInfoString(buf, " DO NOTHING");
6651 else
6653 appendStringInfoString(buf, " DO UPDATE SET ");
6654 /* Deparse targetlist */
6655 get_update_query_targetlist_def(query, confl->onConflictSet,
6656 context, rte);
6658 /* Add a WHERE clause if given */
6659 if (confl->onConflictWhere != NULL)
6661 appendContextKeyword(context, " WHERE ",
6662 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6663 get_rule_expr(confl->onConflictWhere, context, false);
6668 /* Add RETURNING if present */
6669 if (query->returningList)
6671 appendContextKeyword(context, " RETURNING",
6672 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6673 get_target_list(query->returningList, context, NULL);
6678 /* ----------
6679 * get_update_query_def - Parse back an UPDATE parsetree
6680 * ----------
6682 static void
6683 get_update_query_def(Query *query, deparse_context *context)
6685 StringInfo buf = context->buf;
6686 RangeTblEntry *rte;
6688 /* Insert the WITH clause if given */
6689 get_with_clause(query, context);
6692 * Start the query with UPDATE relname SET
6694 rte = rt_fetch(query->resultRelation, query->rtable);
6695 Assert(rte->rtekind == RTE_RELATION);
6696 if (PRETTY_INDENT(context))
6698 appendStringInfoChar(buf, ' ');
6699 context->indentLevel += PRETTYINDENT_STD;
6701 appendStringInfo(buf, "UPDATE %s%s",
6702 only_marker(rte),
6703 generate_relation_name(rte->relid, NIL));
6704 if (rte->alias != NULL)
6705 appendStringInfo(buf, " %s",
6706 quote_identifier(rte->alias->aliasname));
6707 appendStringInfoString(buf, " SET ");
6709 /* Deparse targetlist */
6710 get_update_query_targetlist_def(query, query->targetList, context, rte);
6712 /* Add the FROM clause if needed */
6713 get_from_clause(query, " FROM ", context);
6715 /* Add a WHERE clause if given */
6716 if (query->jointree->quals != NULL)
6718 appendContextKeyword(context, " WHERE ",
6719 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6720 get_rule_expr(query->jointree->quals, context, false);
6723 /* Add RETURNING if present */
6724 if (query->returningList)
6726 appendContextKeyword(context, " RETURNING",
6727 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6728 get_target_list(query->returningList, context, NULL);
6733 /* ----------
6734 * get_update_query_targetlist_def - Parse back an UPDATE targetlist
6735 * ----------
6737 static void
6738 get_update_query_targetlist_def(Query *query, List *targetList,
6739 deparse_context *context, RangeTblEntry *rte)
6741 StringInfo buf = context->buf;
6742 ListCell *l;
6743 ListCell *next_ma_cell;
6744 int remaining_ma_columns;
6745 const char *sep;
6746 SubLink *cur_ma_sublink;
6747 List *ma_sublinks;
6750 * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks
6751 * into a list. We expect them to appear, in ID order, in resjunk tlist
6752 * entries.
6754 ma_sublinks = NIL;
6755 if (query->hasSubLinks) /* else there can't be any */
6757 foreach(l, targetList)
6759 TargetEntry *tle = (TargetEntry *) lfirst(l);
6761 if (tle->resjunk && IsA(tle->expr, SubLink))
6763 SubLink *sl = (SubLink *) tle->expr;
6765 if (sl->subLinkType == MULTIEXPR_SUBLINK)
6767 ma_sublinks = lappend(ma_sublinks, sl);
6768 Assert(sl->subLinkId == list_length(ma_sublinks));
6773 next_ma_cell = list_head(ma_sublinks);
6774 cur_ma_sublink = NULL;
6775 remaining_ma_columns = 0;
6777 /* Add the comma separated list of 'attname = value' */
6778 sep = "";
6779 foreach(l, targetList)
6781 TargetEntry *tle = (TargetEntry *) lfirst(l);
6782 Node *expr;
6784 if (tle->resjunk)
6785 continue; /* ignore junk entries */
6787 /* Emit separator (OK whether we're in multiassignment or not) */
6788 appendStringInfoString(buf, sep);
6789 sep = ", ";
6792 * Check to see if we're starting a multiassignment group: if so,
6793 * output a left paren.
6795 if (next_ma_cell != NULL && cur_ma_sublink == NULL)
6798 * We must dig down into the expr to see if it's a PARAM_MULTIEXPR
6799 * Param. That could be buried under FieldStores and
6800 * SubscriptingRefs and CoerceToDomains (cf processIndirection()),
6801 * and underneath those there could be an implicit type coercion.
6802 * Because we would ignore implicit type coercions anyway, we
6803 * don't need to be as careful as processIndirection() is about
6804 * descending past implicit CoerceToDomains.
6806 expr = (Node *) tle->expr;
6807 while (expr)
6809 if (IsA(expr, FieldStore))
6811 FieldStore *fstore = (FieldStore *) expr;
6813 expr = (Node *) linitial(fstore->newvals);
6815 else if (IsA(expr, SubscriptingRef))
6817 SubscriptingRef *sbsref = (SubscriptingRef *) expr;
6819 if (sbsref->refassgnexpr == NULL)
6820 break;
6822 expr = (Node *) sbsref->refassgnexpr;
6824 else if (IsA(expr, CoerceToDomain))
6826 CoerceToDomain *cdomain = (CoerceToDomain *) expr;
6828 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
6829 break;
6830 expr = (Node *) cdomain->arg;
6832 else
6833 break;
6835 expr = strip_implicit_coercions(expr);
6837 if (expr && IsA(expr, Param) &&
6838 ((Param *) expr)->paramkind == PARAM_MULTIEXPR)
6840 cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
6841 next_ma_cell = lnext(ma_sublinks, next_ma_cell);
6842 remaining_ma_columns = count_nonjunk_tlist_entries(((Query *) cur_ma_sublink->subselect)->targetList);
6843 Assert(((Param *) expr)->paramid ==
6844 ((cur_ma_sublink->subLinkId << 16) | 1));
6845 appendStringInfoChar(buf, '(');
6850 * Put out name of target column; look in the catalogs, not at
6851 * tle->resname, since resname will fail to track RENAME.
6853 appendStringInfoString(buf,
6854 quote_identifier(get_attname(rte->relid,
6855 tle->resno,
6856 false)));
6859 * Print any indirection needed (subfields or subscripts), and strip
6860 * off the top-level nodes representing the indirection assignments.
6862 expr = processIndirection((Node *) tle->expr, context);
6865 * If we're in a multiassignment, skip printing anything more, unless
6866 * this is the last column; in which case, what we print should be the
6867 * sublink, not the Param.
6869 if (cur_ma_sublink != NULL)
6871 if (--remaining_ma_columns > 0)
6872 continue; /* not the last column of multiassignment */
6873 appendStringInfoChar(buf, ')');
6874 expr = (Node *) cur_ma_sublink;
6875 cur_ma_sublink = NULL;
6878 appendStringInfoString(buf, " = ");
6880 get_rule_expr(expr, context, false);
6885 /* ----------
6886 * get_delete_query_def - Parse back a DELETE parsetree
6887 * ----------
6889 static void
6890 get_delete_query_def(Query *query, deparse_context *context)
6892 StringInfo buf = context->buf;
6893 RangeTblEntry *rte;
6895 /* Insert the WITH clause if given */
6896 get_with_clause(query, context);
6899 * Start the query with DELETE FROM relname
6901 rte = rt_fetch(query->resultRelation, query->rtable);
6902 Assert(rte->rtekind == RTE_RELATION);
6903 if (PRETTY_INDENT(context))
6905 appendStringInfoChar(buf, ' ');
6906 context->indentLevel += PRETTYINDENT_STD;
6908 appendStringInfo(buf, "DELETE FROM %s%s",
6909 only_marker(rte),
6910 generate_relation_name(rte->relid, NIL));
6911 if (rte->alias != NULL)
6912 appendStringInfo(buf, " %s",
6913 quote_identifier(rte->alias->aliasname));
6915 /* Add the USING clause if given */
6916 get_from_clause(query, " USING ", context);
6918 /* Add a WHERE clause if given */
6919 if (query->jointree->quals != NULL)
6921 appendContextKeyword(context, " WHERE ",
6922 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6923 get_rule_expr(query->jointree->quals, context, false);
6926 /* Add RETURNING if present */
6927 if (query->returningList)
6929 appendContextKeyword(context, " RETURNING",
6930 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
6931 get_target_list(query->returningList, context, NULL);
6936 /* ----------
6937 * get_utility_query_def - Parse back a UTILITY parsetree
6938 * ----------
6940 static void
6941 get_utility_query_def(Query *query, deparse_context *context)
6943 StringInfo buf = context->buf;
6945 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
6947 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
6949 appendContextKeyword(context, "",
6950 0, PRETTYINDENT_STD, 1);
6951 appendStringInfo(buf, "NOTIFY %s",
6952 quote_identifier(stmt->conditionname));
6953 if (stmt->payload)
6955 appendStringInfoString(buf, ", ");
6956 simple_quote_literal(buf, stmt->payload);
6959 else
6961 /* Currently only NOTIFY utility commands can appear in rules */
6962 elog(ERROR, "unexpected utility statement type");
6967 * Display a Var appropriately.
6969 * In some cases (currently only when recursing into an unnamed join)
6970 * the Var's varlevelsup has to be interpreted with respect to a context
6971 * above the current one; levelsup indicates the offset.
6973 * If istoplevel is true, the Var is at the top level of a SELECT's
6974 * targetlist, which means we need special treatment of whole-row Vars.
6975 * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a
6976 * dirty hack to prevent "tab.*" from being expanded into multiple columns.
6977 * (The parser will strip the useless coercion, so no inefficiency is added in
6978 * dump and reload.) We used to print just "tab" in such cases, but that is
6979 * ambiguous and will yield the wrong result if "tab" is also a plain column
6980 * name in the query.
6982 * Returns the attname of the Var, or NULL if the Var has no attname (because
6983 * it is a whole-row Var or a subplan output reference).
6985 static char *
6986 get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
6988 StringInfo buf = context->buf;
6989 RangeTblEntry *rte;
6990 AttrNumber attnum;
6991 int netlevelsup;
6992 deparse_namespace *dpns;
6993 int varno;
6994 AttrNumber varattno;
6995 deparse_columns *colinfo;
6996 char *refname;
6997 char *attname;
6999 /* Find appropriate nesting depth */
7000 netlevelsup = var->varlevelsup + levelsup;
7001 if (netlevelsup >= list_length(context->namespaces))
7002 elog(ERROR, "bogus varlevelsup: %d offset %d",
7003 var->varlevelsup, levelsup);
7004 dpns = (deparse_namespace *) list_nth(context->namespaces,
7005 netlevelsup);
7008 * If we have a syntactic referent for the Var, and we're working from a
7009 * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7010 * on the semantic referent. (Forcing use of the semantic referent when
7011 * printing plan trees is a design choice that's perhaps more motivated by
7012 * backwards compatibility than anything else. But it does have the
7013 * advantage of making plans more explicit.)
7015 if (var->varnosyn > 0 && dpns->plan == NULL)
7017 varno = var->varnosyn;
7018 varattno = var->varattnosyn;
7020 else
7022 varno = var->varno;
7023 varattno = var->varattno;
7027 * Try to find the relevant RTE in this rtable. In a plan tree, it's
7028 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7029 * down into the subplans, or INDEX_VAR, which is resolved similarly. Also
7030 * find the aliases previously assigned for this RTE.
7032 if (varno >= 1 && varno <= list_length(dpns->rtable))
7035 * We might have been asked to map child Vars to some parent relation.
7037 if (context->appendparents && dpns->appendrels)
7039 int pvarno = varno;
7040 AttrNumber pvarattno = varattno;
7041 AppendRelInfo *appinfo = dpns->appendrels[pvarno];
7042 bool found = false;
7044 /* Only map up to inheritance parents, not UNION ALL appendrels */
7045 while (appinfo &&
7046 rt_fetch(appinfo->parent_relid,
7047 dpns->rtable)->rtekind == RTE_RELATION)
7049 found = false;
7050 if (pvarattno > 0) /* system columns stay as-is */
7052 if (pvarattno > appinfo->num_child_cols)
7053 break; /* safety check */
7054 pvarattno = appinfo->parent_colnos[pvarattno - 1];
7055 if (pvarattno == 0)
7056 break; /* Var is local to child */
7059 pvarno = appinfo->parent_relid;
7060 found = true;
7062 /* If the parent is itself a child, continue up. */
7063 Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable));
7064 appinfo = dpns->appendrels[pvarno];
7068 * If we found an ancestral rel, and that rel is included in
7069 * appendparents, print that column not the original one.
7071 if (found && bms_is_member(pvarno, context->appendparents))
7073 varno = pvarno;
7074 varattno = pvarattno;
7078 rte = rt_fetch(varno, dpns->rtable);
7079 refname = (char *) list_nth(dpns->rtable_names, varno - 1);
7080 colinfo = deparse_columns_fetch(varno, dpns);
7081 attnum = varattno;
7083 else
7085 resolve_special_varno((Node *) var, context,
7086 get_special_variable, NULL);
7087 return NULL;
7091 * The planner will sometimes emit Vars referencing resjunk elements of a
7092 * subquery's target list (this is currently only possible if it chooses
7093 * to generate a "physical tlist" for a SubqueryScan or CteScan node).
7094 * Although we prefer to print subquery-referencing Vars using the
7095 * subquery's alias, that's not possible for resjunk items since they have
7096 * no alias. So in that case, drill down to the subplan and print the
7097 * contents of the referenced tlist item. This works because in a plan
7098 * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
7099 * we'll have set dpns->inner_plan to reference the child plan node.
7101 if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
7102 attnum > list_length(rte->eref->colnames) &&
7103 dpns->inner_plan)
7105 TargetEntry *tle;
7106 deparse_namespace save_dpns;
7108 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7109 if (!tle)
7110 elog(ERROR, "invalid attnum %d for relation \"%s\"",
7111 attnum, rte->eref->aliasname);
7113 Assert(netlevelsup == 0);
7114 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7117 * Force parentheses because our caller probably assumed a Var is a
7118 * simple expression.
7120 if (!IsA(tle->expr, Var))
7121 appendStringInfoChar(buf, '(');
7122 get_rule_expr((Node *) tle->expr, context, true);
7123 if (!IsA(tle->expr, Var))
7124 appendStringInfoChar(buf, ')');
7126 pop_child_plan(dpns, &save_dpns);
7127 return NULL;
7131 * If it's an unnamed join, look at the expansion of the alias variable.
7132 * If it's a simple reference to one of the input vars, then recursively
7133 * print the name of that var instead. When it's not a simple reference,
7134 * we have to just print the unqualified join column name. (This can only
7135 * happen with "dangerous" merged columns in a JOIN USING; we took pains
7136 * previously to make the unqualified column name unique in such cases.)
7138 * This wouldn't work in decompiling plan trees, because we don't store
7139 * joinaliasvars lists after planning; but a plan tree should never
7140 * contain a join alias variable.
7142 if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
7144 if (rte->joinaliasvars == NIL)
7145 elog(ERROR, "cannot decompile join alias var in plan tree");
7146 if (attnum > 0)
7148 Var *aliasvar;
7150 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
7151 /* we intentionally don't strip implicit coercions here */
7152 if (aliasvar && IsA(aliasvar, Var))
7154 return get_variable(aliasvar, var->varlevelsup + levelsup,
7155 istoplevel, context);
7160 * Unnamed join has no refname. (Note: since it's unnamed, there is
7161 * no way the user could have referenced it to create a whole-row Var
7162 * for it. So we don't have to cover that case below.)
7164 Assert(refname == NULL);
7167 if (attnum == InvalidAttrNumber)
7168 attname = NULL;
7169 else if (attnum > 0)
7171 /* Get column name to use from the colinfo struct */
7172 if (attnum > colinfo->num_cols)
7173 elog(ERROR, "invalid attnum %d for relation \"%s\"",
7174 attnum, rte->eref->aliasname);
7175 attname = colinfo->colnames[attnum - 1];
7176 if (attname == NULL) /* dropped column? */
7177 elog(ERROR, "invalid attnum %d for relation \"%s\"",
7178 attnum, rte->eref->aliasname);
7180 else
7182 /* System column - name is fixed, get it from the catalog */
7183 attname = get_rte_attribute_name(rte, attnum);
7186 if (refname && (context->varprefix || attname == NULL))
7188 appendStringInfoString(buf, quote_identifier(refname));
7189 appendStringInfoChar(buf, '.');
7191 if (attname)
7192 appendStringInfoString(buf, quote_identifier(attname));
7193 else
7195 appendStringInfoChar(buf, '*');
7196 if (istoplevel)
7197 appendStringInfo(buf, "::%s",
7198 format_type_with_typemod(var->vartype,
7199 var->vartypmod));
7202 return attname;
7206 * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR. This
7207 * routine is actually a callback for resolve_special_varno, which handles
7208 * finding the correct TargetEntry. We get the expression contained in that
7209 * TargetEntry and just need to deparse it, a job we can throw back on
7210 * get_rule_expr.
7212 static void
7213 get_special_variable(Node *node, deparse_context *context, void *callback_arg)
7215 StringInfo buf = context->buf;
7218 * For a non-Var referent, force parentheses because our caller probably
7219 * assumed a Var is a simple expression.
7221 if (!IsA(node, Var))
7222 appendStringInfoChar(buf, '(');
7223 get_rule_expr(node, context, true);
7224 if (!IsA(node, Var))
7225 appendStringInfoChar(buf, ')');
7229 * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR,
7230 * INDEX_VAR) until we find a real Var or some kind of non-Var node; then,
7231 * invoke the callback provided.
7233 static void
7234 resolve_special_varno(Node *node, deparse_context *context,
7235 rsv_callback callback, void *callback_arg)
7237 Var *var;
7238 deparse_namespace *dpns;
7240 /* This function is recursive, so let's be paranoid. */
7241 check_stack_depth();
7243 /* If it's not a Var, invoke the callback. */
7244 if (!IsA(node, Var))
7246 (*callback) (node, context, callback_arg);
7247 return;
7250 /* Find appropriate nesting depth */
7251 var = (Var *) node;
7252 dpns = (deparse_namespace *) list_nth(context->namespaces,
7253 var->varlevelsup);
7256 * If varno is special, recurse. (Don't worry about varnosyn; if we're
7257 * here, we already decided not to use that.)
7259 if (var->varno == OUTER_VAR && dpns->outer_tlist)
7261 TargetEntry *tle;
7262 deparse_namespace save_dpns;
7263 Bitmapset *save_appendparents;
7265 tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
7266 if (!tle)
7267 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
7270 * If we're descending to the first child of an Append or MergeAppend,
7271 * update appendparents. This will affect deparsing of all Vars
7272 * appearing within the eventually-resolved subexpression.
7274 save_appendparents = context->appendparents;
7276 if (IsA(dpns->plan, Append))
7277 context->appendparents = bms_union(context->appendparents,
7278 ((Append *) dpns->plan)->apprelids);
7279 else if (IsA(dpns->plan, MergeAppend))
7280 context->appendparents = bms_union(context->appendparents,
7281 ((MergeAppend *) dpns->plan)->apprelids);
7283 push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7284 resolve_special_varno((Node *) tle->expr, context,
7285 callback, callback_arg);
7286 pop_child_plan(dpns, &save_dpns);
7287 context->appendparents = save_appendparents;
7288 return;
7290 else if (var->varno == INNER_VAR && dpns->inner_tlist)
7292 TargetEntry *tle;
7293 deparse_namespace save_dpns;
7295 tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
7296 if (!tle)
7297 elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
7299 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7300 resolve_special_varno((Node *) tle->expr, context,
7301 callback, callback_arg);
7302 pop_child_plan(dpns, &save_dpns);
7303 return;
7305 else if (var->varno == INDEX_VAR && dpns->index_tlist)
7307 TargetEntry *tle;
7309 tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
7310 if (!tle)
7311 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
7313 resolve_special_varno((Node *) tle->expr, context,
7314 callback, callback_arg);
7315 return;
7317 else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
7318 elog(ERROR, "bogus varno: %d", var->varno);
7320 /* Not special. Just invoke the callback. */
7321 (*callback) (node, context, callback_arg);
7325 * Get the name of a field of an expression of composite type. The
7326 * expression is usually a Var, but we handle other cases too.
7328 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
7330 * This is fairly straightforward when the expression has a named composite
7331 * type; we need only look up the type in the catalogs. However, the type
7332 * could also be RECORD. Since no actual table or view column is allowed to
7333 * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
7334 * or to a subquery output. We drill down to find the ultimate defining
7335 * expression and attempt to infer the field name from it. We ereport if we
7336 * can't determine the name.
7338 * Similarly, a PARAM of type RECORD has to refer to some expression of
7339 * a determinable composite type.
7341 static const char *
7342 get_name_for_var_field(Var *var, int fieldno,
7343 int levelsup, deparse_context *context)
7345 RangeTblEntry *rte;
7346 AttrNumber attnum;
7347 int netlevelsup;
7348 deparse_namespace *dpns;
7349 int varno;
7350 AttrNumber varattno;
7351 TupleDesc tupleDesc;
7352 Node *expr;
7355 * If it's a RowExpr that was expanded from a whole-row Var, use the
7356 * column names attached to it.
7358 if (IsA(var, RowExpr))
7360 RowExpr *r = (RowExpr *) var;
7362 if (fieldno > 0 && fieldno <= list_length(r->colnames))
7363 return strVal(list_nth(r->colnames, fieldno - 1));
7367 * If it's a Param of type RECORD, try to find what the Param refers to.
7369 if (IsA(var, Param))
7371 Param *param = (Param *) var;
7372 ListCell *ancestor_cell;
7374 expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7375 if (expr)
7377 /* Found a match, so recurse to decipher the field name */
7378 deparse_namespace save_dpns;
7379 const char *result;
7381 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7382 result = get_name_for_var_field((Var *) expr, fieldno,
7383 0, context);
7384 pop_ancestor_plan(dpns, &save_dpns);
7385 return result;
7390 * If it's a Var of type RECORD, we have to find what the Var refers to;
7391 * if not, we can use get_expr_result_tupdesc().
7393 if (!IsA(var, Var) ||
7394 var->vartype != RECORDOID)
7396 tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7397 /* Got the tupdesc, so we can extract the field name */
7398 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7399 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7402 /* Find appropriate nesting depth */
7403 netlevelsup = var->varlevelsup + levelsup;
7404 if (netlevelsup >= list_length(context->namespaces))
7405 elog(ERROR, "bogus varlevelsup: %d offset %d",
7406 var->varlevelsup, levelsup);
7407 dpns = (deparse_namespace *) list_nth(context->namespaces,
7408 netlevelsup);
7411 * If we have a syntactic referent for the Var, and we're working from a
7412 * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7413 * on the semantic referent. (See comments in get_variable().)
7415 if (var->varnosyn > 0 && dpns->plan == NULL)
7417 varno = var->varnosyn;
7418 varattno = var->varattnosyn;
7420 else
7422 varno = var->varno;
7423 varattno = var->varattno;
7427 * Try to find the relevant RTE in this rtable. In a plan tree, it's
7428 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7429 * down into the subplans, or INDEX_VAR, which is resolved similarly.
7431 * Note: unlike get_variable and resolve_special_varno, we need not worry
7432 * about inheritance mapping: a child Var should have the same datatype as
7433 * its parent, and here we're really only interested in the Var's type.
7435 if (varno >= 1 && varno <= list_length(dpns->rtable))
7437 rte = rt_fetch(varno, dpns->rtable);
7438 attnum = varattno;
7440 else if (varno == OUTER_VAR && dpns->outer_tlist)
7442 TargetEntry *tle;
7443 deparse_namespace save_dpns;
7444 const char *result;
7446 tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7447 if (!tle)
7448 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7450 Assert(netlevelsup == 0);
7451 push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7453 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7454 levelsup, context);
7456 pop_child_plan(dpns, &save_dpns);
7457 return result;
7459 else if (varno == INNER_VAR && dpns->inner_tlist)
7461 TargetEntry *tle;
7462 deparse_namespace save_dpns;
7463 const char *result;
7465 tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7466 if (!tle)
7467 elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7469 Assert(netlevelsup == 0);
7470 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7472 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7473 levelsup, context);
7475 pop_child_plan(dpns, &save_dpns);
7476 return result;
7478 else if (varno == INDEX_VAR && dpns->index_tlist)
7480 TargetEntry *tle;
7481 const char *result;
7483 tle = get_tle_by_resno(dpns->index_tlist, varattno);
7484 if (!tle)
7485 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7487 Assert(netlevelsup == 0);
7489 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7490 levelsup, context);
7492 return result;
7494 else
7496 elog(ERROR, "bogus varno: %d", varno);
7497 return NULL; /* keep compiler quiet */
7500 if (attnum == InvalidAttrNumber)
7502 /* Var is whole-row reference to RTE, so select the right field */
7503 return get_rte_attribute_name(rte, fieldno);
7507 * This part has essentially the same logic as the parser's
7508 * expandRecordVariable() function, but we are dealing with a different
7509 * representation of the input context, and we only need one field name
7510 * not a TupleDesc. Also, we need special cases for finding subquery and
7511 * CTE subplans when deparsing Plan trees.
7513 expr = (Node *) var; /* default if we can't drill down */
7515 switch (rte->rtekind)
7517 case RTE_RELATION:
7518 case RTE_VALUES:
7519 case RTE_NAMEDTUPLESTORE:
7520 case RTE_RESULT:
7523 * This case should not occur: a column of a table, values list,
7524 * or ENR shouldn't have type RECORD. Fall through and fail (most
7525 * likely) at the bottom.
7527 break;
7528 case RTE_SUBQUERY:
7529 /* Subselect-in-FROM: examine sub-select's output expr */
7531 if (rte->subquery)
7533 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
7534 attnum);
7536 if (ste == NULL || ste->resjunk)
7537 elog(ERROR, "subquery %s does not have attribute %d",
7538 rte->eref->aliasname, attnum);
7539 expr = (Node *) ste->expr;
7540 if (IsA(expr, Var))
7543 * Recurse into the sub-select to see what its Var
7544 * refers to. We have to build an additional level of
7545 * namespace to keep in step with varlevelsup in the
7546 * subselect.
7548 deparse_namespace mydpns;
7549 const char *result;
7551 set_deparse_for_query(&mydpns, rte->subquery,
7552 context->namespaces);
7554 context->namespaces = lcons(&mydpns,
7555 context->namespaces);
7557 result = get_name_for_var_field((Var *) expr, fieldno,
7558 0, context);
7560 context->namespaces =
7561 list_delete_first(context->namespaces);
7563 return result;
7565 /* else fall through to inspect the expression */
7567 else
7570 * We're deparsing a Plan tree so we don't have complete
7571 * RTE entries (in particular, rte->subquery is NULL). But
7572 * the only place we'd see a Var directly referencing a
7573 * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7574 * look into the child plan's tlist instead.
7576 TargetEntry *tle;
7577 deparse_namespace save_dpns;
7578 const char *result;
7580 if (!dpns->inner_plan)
7581 elog(ERROR, "failed to find plan for subquery %s",
7582 rte->eref->aliasname);
7583 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7584 if (!tle)
7585 elog(ERROR, "bogus varattno for subquery var: %d",
7586 attnum);
7587 Assert(netlevelsup == 0);
7588 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7590 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7591 levelsup, context);
7593 pop_child_plan(dpns, &save_dpns);
7594 return result;
7597 break;
7598 case RTE_JOIN:
7599 /* Join RTE --- recursively inspect the alias variable */
7600 if (rte->joinaliasvars == NIL)
7601 elog(ERROR, "cannot decompile join alias var in plan tree");
7602 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7603 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7604 Assert(expr != NULL);
7605 /* we intentionally don't strip implicit coercions here */
7606 if (IsA(expr, Var))
7607 return get_name_for_var_field((Var *) expr, fieldno,
7608 var->varlevelsup + levelsup,
7609 context);
7610 /* else fall through to inspect the expression */
7611 break;
7612 case RTE_FUNCTION:
7613 case RTE_TABLEFUNC:
7616 * We couldn't get here unless a function is declared with one of
7617 * its result columns as RECORD, which is not allowed.
7619 break;
7620 case RTE_CTE:
7621 /* CTE reference: examine subquery's output expr */
7623 CommonTableExpr *cte = NULL;
7624 Index ctelevelsup;
7625 ListCell *lc;
7628 * Try to find the referenced CTE using the namespace stack.
7630 ctelevelsup = rte->ctelevelsup + netlevelsup;
7631 if (ctelevelsup >= list_length(context->namespaces))
7632 lc = NULL;
7633 else
7635 deparse_namespace *ctedpns;
7637 ctedpns = (deparse_namespace *)
7638 list_nth(context->namespaces, ctelevelsup);
7639 foreach(lc, ctedpns->ctes)
7641 cte = (CommonTableExpr *) lfirst(lc);
7642 if (strcmp(cte->ctename, rte->ctename) == 0)
7643 break;
7646 if (lc != NULL)
7648 Query *ctequery = (Query *) cte->ctequery;
7649 TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte),
7650 attnum);
7652 if (ste == NULL || ste->resjunk)
7653 elog(ERROR, "subquery %s does not have attribute %d",
7654 rte->eref->aliasname, attnum);
7655 expr = (Node *) ste->expr;
7656 if (IsA(expr, Var))
7659 * Recurse into the CTE to see what its Var refers to.
7660 * We have to build an additional level of namespace
7661 * to keep in step with varlevelsup in the CTE.
7662 * Furthermore it could be an outer CTE, so we may
7663 * have to delete some levels of namespace.
7665 List *save_nslist = context->namespaces;
7666 List *new_nslist;
7667 deparse_namespace mydpns;
7668 const char *result;
7670 set_deparse_for_query(&mydpns, ctequery,
7671 context->namespaces);
7673 new_nslist = list_copy_tail(context->namespaces,
7674 ctelevelsup);
7675 context->namespaces = lcons(&mydpns, new_nslist);
7677 result = get_name_for_var_field((Var *) expr, fieldno,
7678 0, context);
7680 context->namespaces = save_nslist;
7682 return result;
7684 /* else fall through to inspect the expression */
7686 else
7689 * We're deparsing a Plan tree so we don't have a CTE
7690 * list. But the only places we'd see a Var directly
7691 * referencing a CTE RTE are in CteScan or WorkTableScan
7692 * plan nodes. For those cases, set_deparse_plan arranged
7693 * for dpns->inner_plan to be the plan node that emits the
7694 * CTE or RecursiveUnion result, and we can look at its
7695 * tlist instead.
7697 TargetEntry *tle;
7698 deparse_namespace save_dpns;
7699 const char *result;
7701 if (!dpns->inner_plan)
7702 elog(ERROR, "failed to find plan for CTE %s",
7703 rte->eref->aliasname);
7704 tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7705 if (!tle)
7706 elog(ERROR, "bogus varattno for subquery var: %d",
7707 attnum);
7708 Assert(netlevelsup == 0);
7709 push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7711 result = get_name_for_var_field((Var *) tle->expr, fieldno,
7712 levelsup, context);
7714 pop_child_plan(dpns, &save_dpns);
7715 return result;
7718 break;
7722 * We now have an expression we can't expand any more, so see if
7723 * get_expr_result_tupdesc() can do anything with it.
7725 tupleDesc = get_expr_result_tupdesc(expr, false);
7726 /* Got the tupdesc, so we can extract the field name */
7727 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7728 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7732 * Try to find the referenced expression for a PARAM_EXEC Param that might
7733 * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
7735 * If successful, return the expression and set *dpns_p and *ancestor_cell_p
7736 * appropriately for calling push_ancestor_plan(). If no referent can be
7737 * found, return NULL.
7739 static Node *
7740 find_param_referent(Param *param, deparse_context *context,
7741 deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
7743 /* Initialize output parameters to prevent compiler warnings */
7744 *dpns_p = NULL;
7745 *ancestor_cell_p = NULL;
7748 * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7749 * SubPlan argument. This will necessarily be in some ancestor of the
7750 * current expression's Plan node.
7752 if (param->paramkind == PARAM_EXEC)
7754 deparse_namespace *dpns;
7755 Plan *child_plan;
7756 bool in_same_plan_level;
7757 ListCell *lc;
7759 dpns = (deparse_namespace *) linitial(context->namespaces);
7760 child_plan = dpns->plan;
7761 in_same_plan_level = true;
7763 foreach(lc, dpns->ancestors)
7765 Node *ancestor = (Node *) lfirst(lc);
7766 ListCell *lc2;
7769 * NestLoops transmit params to their inner child only; also, once
7770 * we've crawled up out of a subplan, this couldn't possibly be
7771 * the right match.
7773 if (IsA(ancestor, NestLoop) &&
7774 child_plan == innerPlan(ancestor) &&
7775 in_same_plan_level)
7777 NestLoop *nl = (NestLoop *) ancestor;
7779 foreach(lc2, nl->nestParams)
7781 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7783 if (nlp->paramno == param->paramid)
7785 /* Found a match, so return it */
7786 *dpns_p = dpns;
7787 *ancestor_cell_p = lc;
7788 return (Node *) nlp->paramval;
7794 * If ancestor is a SubPlan, check the arguments it provides.
7796 if (IsA(ancestor, SubPlan))
7798 SubPlan *subplan = (SubPlan *) ancestor;
7799 ListCell *lc3;
7800 ListCell *lc4;
7802 forboth(lc3, subplan->parParam, lc4, subplan->args)
7804 int paramid = lfirst_int(lc3);
7805 Node *arg = (Node *) lfirst(lc4);
7807 if (paramid == param->paramid)
7810 * Found a match, so return it. But, since Vars in
7811 * the arg are to be evaluated in the surrounding
7812 * context, we have to point to the next ancestor item
7813 * that is *not* a SubPlan.
7815 ListCell *rest;
7817 for_each_cell(rest, dpns->ancestors,
7818 lnext(dpns->ancestors, lc))
7820 Node *ancestor2 = (Node *) lfirst(rest);
7822 if (!IsA(ancestor2, SubPlan))
7824 *dpns_p = dpns;
7825 *ancestor_cell_p = rest;
7826 return arg;
7829 elog(ERROR, "SubPlan cannot be outermost ancestor");
7833 /* We have emerged from a subplan. */
7834 in_same_plan_level = false;
7836 /* SubPlan isn't a kind of Plan, so skip the rest */
7837 continue;
7841 * Check to see if we're emerging from an initplan of the current
7842 * ancestor plan. Initplans never have any parParams, so no need
7843 * to search that list, but we need to know if we should reset
7844 * in_same_plan_level.
7846 foreach(lc2, ((Plan *) ancestor)->initPlan)
7848 SubPlan *subplan = lfirst_node(SubPlan, lc2);
7850 if (child_plan != (Plan *) list_nth(dpns->subplans,
7851 subplan->plan_id - 1))
7852 continue;
7854 /* No parameters to be had here. */
7855 Assert(subplan->parParam == NIL);
7857 /* We have emerged from an initplan. */
7858 in_same_plan_level = false;
7859 break;
7862 /* No luck, crawl up to next ancestor */
7863 child_plan = (Plan *) ancestor;
7867 /* No referent found */
7868 return NULL;
7872 * Display a Param appropriately.
7874 static void
7875 get_parameter(Param *param, deparse_context *context)
7877 Node *expr;
7878 deparse_namespace *dpns;
7879 ListCell *ancestor_cell;
7882 * If it's a PARAM_EXEC parameter, try to locate the expression from which
7883 * the parameter was computed. Note that failing to find a referent isn't
7884 * an error, since the Param might well be a subplan output rather than an
7885 * input.
7887 expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7888 if (expr)
7890 /* Found a match, so print it */
7891 deparse_namespace save_dpns;
7892 bool save_varprefix;
7893 bool need_paren;
7895 /* Switch attention to the ancestor plan node */
7896 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7899 * Force prefixing of Vars, since they won't belong to the relation
7900 * being scanned in the original plan node.
7902 save_varprefix = context->varprefix;
7903 context->varprefix = true;
7906 * A Param's expansion is typically a Var, Aggref, or upper-level
7907 * Param, which wouldn't need extra parentheses. Otherwise, insert
7908 * parens to ensure the expression looks atomic.
7910 need_paren = !(IsA(expr, Var) ||
7911 IsA(expr, Aggref) ||
7912 IsA(expr, Param));
7913 if (need_paren)
7914 appendStringInfoChar(context->buf, '(');
7916 get_rule_expr(expr, context, false);
7918 if (need_paren)
7919 appendStringInfoChar(context->buf, ')');
7921 context->varprefix = save_varprefix;
7923 pop_ancestor_plan(dpns, &save_dpns);
7925 return;
7929 * If it's an external parameter, see if the outermost namespace provides
7930 * function argument names.
7932 if (param->paramkind == PARAM_EXTERN && context->namespaces != NIL)
7934 dpns = llast(context->namespaces);
7935 if (dpns->argnames &&
7936 param->paramid > 0 &&
7937 param->paramid <= dpns->numargs)
7939 char *argname = dpns->argnames[param->paramid - 1];
7941 if (argname)
7943 bool should_qualify = false;
7944 ListCell *lc;
7947 * Qualify the parameter name if there are any other deparse
7948 * namespaces with range tables. This avoids qualifying in
7949 * trivial cases like "RETURN a + b", but makes it safe in all
7950 * other cases.
7952 foreach(lc, context->namespaces)
7954 deparse_namespace *dpns = lfirst(lc);
7956 if (list_length(dpns->rtable_names) > 0)
7958 should_qualify = true;
7959 break;
7962 if (should_qualify)
7964 appendStringInfoString(context->buf, quote_identifier(dpns->funcname));
7965 appendStringInfoChar(context->buf, '.');
7968 appendStringInfoString(context->buf, quote_identifier(argname));
7969 return;
7975 * Not PARAM_EXEC, or couldn't find referent: just print $N.
7977 appendStringInfo(context->buf, "$%d", param->paramid);
7981 * get_simple_binary_op_name
7983 * helper function for isSimpleNode
7984 * will return single char binary operator name, or NULL if it's not
7986 static const char *
7987 get_simple_binary_op_name(OpExpr *expr)
7989 List *args = expr->args;
7991 if (list_length(args) == 2)
7993 /* binary operator */
7994 Node *arg1 = (Node *) linitial(args);
7995 Node *arg2 = (Node *) lsecond(args);
7996 const char *op;
7998 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
7999 if (strlen(op) == 1)
8000 return op;
8002 return NULL;
8007 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
8009 * true : simple in the context of parent node's type
8010 * false : not simple
8012 static bool
8013 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
8015 if (!node)
8016 return false;
8018 switch (nodeTag(node))
8020 case T_Var:
8021 case T_Const:
8022 case T_Param:
8023 case T_CoerceToDomainValue:
8024 case T_SetToDefault:
8025 case T_CurrentOfExpr:
8026 /* single words: always simple */
8027 return true;
8029 case T_SubscriptingRef:
8030 case T_ArrayExpr:
8031 case T_RowExpr:
8032 case T_CoalesceExpr:
8033 case T_MinMaxExpr:
8034 case T_SQLValueFunction:
8035 case T_XmlExpr:
8036 case T_NextValueExpr:
8037 case T_NullIfExpr:
8038 case T_Aggref:
8039 case T_WindowFunc:
8040 case T_FuncExpr:
8041 /* function-like: name(..) or name[..] */
8042 return true;
8044 /* CASE keywords act as parentheses */
8045 case T_CaseExpr:
8046 return true;
8048 case T_FieldSelect:
8051 * appears simple since . has top precedence, unless parent is
8052 * T_FieldSelect itself!
8054 return !IsA(parentNode, FieldSelect);
8056 case T_FieldStore:
8059 * treat like FieldSelect (probably doesn't matter)
8061 return !IsA(parentNode, FieldStore);
8063 case T_CoerceToDomain:
8064 /* maybe simple, check args */
8065 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
8066 node, prettyFlags);
8067 case T_RelabelType:
8068 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
8069 node, prettyFlags);
8070 case T_CoerceViaIO:
8071 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
8072 node, prettyFlags);
8073 case T_ArrayCoerceExpr:
8074 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
8075 node, prettyFlags);
8076 case T_ConvertRowtypeExpr:
8077 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
8078 node, prettyFlags);
8080 case T_OpExpr:
8082 /* depends on parent node type; needs further checking */
8083 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
8085 const char *op;
8086 const char *parentOp;
8087 bool is_lopriop;
8088 bool is_hipriop;
8089 bool is_lopriparent;
8090 bool is_hipriparent;
8092 op = get_simple_binary_op_name((OpExpr *) node);
8093 if (!op)
8094 return false;
8096 /* We know only the basic operators + - and * / % */
8097 is_lopriop = (strchr("+-", *op) != NULL);
8098 is_hipriop = (strchr("*/%", *op) != NULL);
8099 if (!(is_lopriop || is_hipriop))
8100 return false;
8102 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
8103 if (!parentOp)
8104 return false;
8106 is_lopriparent = (strchr("+-", *parentOp) != NULL);
8107 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
8108 if (!(is_lopriparent || is_hipriparent))
8109 return false;
8111 if (is_hipriop && is_lopriparent)
8112 return true; /* op binds tighter than parent */
8114 if (is_lopriop && is_hipriparent)
8115 return false;
8118 * Operators are same priority --- can skip parens only if
8119 * we have (a - b) - c, not a - (b - c).
8121 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
8122 return true;
8124 return false;
8126 /* else do the same stuff as for T_SubLink et al. */
8128 /* FALLTHROUGH */
8130 case T_SubLink:
8131 case T_NullTest:
8132 case T_BooleanTest:
8133 case T_DistinctExpr:
8134 switch (nodeTag(parentNode))
8136 case T_FuncExpr:
8138 /* special handling for casts */
8139 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8141 if (type == COERCE_EXPLICIT_CAST ||
8142 type == COERCE_IMPLICIT_CAST)
8143 return false;
8144 return true; /* own parentheses */
8146 case T_BoolExpr: /* lower precedence */
8147 case T_SubscriptingRef: /* other separators */
8148 case T_ArrayExpr: /* other separators */
8149 case T_RowExpr: /* other separators */
8150 case T_CoalesceExpr: /* own parentheses */
8151 case T_MinMaxExpr: /* own parentheses */
8152 case T_XmlExpr: /* own parentheses */
8153 case T_NullIfExpr: /* other separators */
8154 case T_Aggref: /* own parentheses */
8155 case T_WindowFunc: /* own parentheses */
8156 case T_CaseExpr: /* other separators */
8157 return true;
8158 default:
8159 return false;
8162 case T_BoolExpr:
8163 switch (nodeTag(parentNode))
8165 case T_BoolExpr:
8166 if (prettyFlags & PRETTYFLAG_PAREN)
8168 BoolExprType type;
8169 BoolExprType parentType;
8171 type = ((BoolExpr *) node)->boolop;
8172 parentType = ((BoolExpr *) parentNode)->boolop;
8173 switch (type)
8175 case NOT_EXPR:
8176 case AND_EXPR:
8177 if (parentType == AND_EXPR || parentType == OR_EXPR)
8178 return true;
8179 break;
8180 case OR_EXPR:
8181 if (parentType == OR_EXPR)
8182 return true;
8183 break;
8186 return false;
8187 case T_FuncExpr:
8189 /* special handling for casts */
8190 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
8192 if (type == COERCE_EXPLICIT_CAST ||
8193 type == COERCE_IMPLICIT_CAST)
8194 return false;
8195 return true; /* own parentheses */
8197 case T_SubscriptingRef: /* other separators */
8198 case T_ArrayExpr: /* other separators */
8199 case T_RowExpr: /* other separators */
8200 case T_CoalesceExpr: /* own parentheses */
8201 case T_MinMaxExpr: /* own parentheses */
8202 case T_XmlExpr: /* own parentheses */
8203 case T_NullIfExpr: /* other separators */
8204 case T_Aggref: /* own parentheses */
8205 case T_WindowFunc: /* own parentheses */
8206 case T_CaseExpr: /* other separators */
8207 return true;
8208 default:
8209 return false;
8212 default:
8213 break;
8215 /* those we don't know: in dubio complexo */
8216 return false;
8221 * appendContextKeyword - append a keyword to buffer
8223 * If prettyPrint is enabled, perform a line break, and adjust indentation.
8224 * Otherwise, just append the keyword.
8226 static void
8227 appendContextKeyword(deparse_context *context, const char *str,
8228 int indentBefore, int indentAfter, int indentPlus)
8230 StringInfo buf = context->buf;
8232 if (PRETTY_INDENT(context))
8234 int indentAmount;
8236 context->indentLevel += indentBefore;
8238 /* remove any trailing spaces currently in the buffer ... */
8239 removeStringInfoSpaces(buf);
8240 /* ... then add a newline and some spaces */
8241 appendStringInfoChar(buf, '\n');
8243 if (context->indentLevel < PRETTYINDENT_LIMIT)
8244 indentAmount = Max(context->indentLevel, 0) + indentPlus;
8245 else
8248 * If we're indented more than PRETTYINDENT_LIMIT characters, try
8249 * to conserve horizontal space by reducing the per-level
8250 * indentation. For best results the scale factor here should
8251 * divide all the indent amounts that get added to indentLevel
8252 * (PRETTYINDENT_STD, etc). It's important that the indentation
8253 * not grow unboundedly, else deeply-nested trees use O(N^2)
8254 * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
8256 indentAmount = PRETTYINDENT_LIMIT +
8257 (context->indentLevel - PRETTYINDENT_LIMIT) /
8258 (PRETTYINDENT_STD / 2);
8259 indentAmount %= PRETTYINDENT_LIMIT;
8260 /* scale/wrap logic affects indentLevel, but not indentPlus */
8261 indentAmount += indentPlus;
8263 appendStringInfoSpaces(buf, indentAmount);
8265 appendStringInfoString(buf, str);
8267 context->indentLevel += indentAfter;
8268 if (context->indentLevel < 0)
8269 context->indentLevel = 0;
8271 else
8272 appendStringInfoString(buf, str);
8276 * removeStringInfoSpaces - delete trailing spaces from a buffer.
8278 * Possibly this should move to stringinfo.c at some point.
8280 static void
8281 removeStringInfoSpaces(StringInfo str)
8283 while (str->len > 0 && str->data[str->len - 1] == ' ')
8284 str->data[--(str->len)] = '\0';
8289 * get_rule_expr_paren - deparse expr using get_rule_expr,
8290 * embracing the string with parentheses if necessary for prettyPrint.
8292 * Never embrace if prettyFlags=0, because it's done in the calling node.
8294 * Any node that does *not* embrace its argument node by sql syntax (with
8295 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
8296 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
8297 * added.
8299 static void
8300 get_rule_expr_paren(Node *node, deparse_context *context,
8301 bool showimplicit, Node *parentNode)
8303 bool need_paren;
8305 need_paren = PRETTY_PAREN(context) &&
8306 !isSimpleNode(node, parentNode, context->prettyFlags);
8308 if (need_paren)
8309 appendStringInfoChar(context->buf, '(');
8311 get_rule_expr(node, context, showimplicit);
8313 if (need_paren)
8314 appendStringInfoChar(context->buf, ')');
8318 /* ----------
8319 * get_rule_expr - Parse back an expression
8321 * Note: showimplicit determines whether we display any implicit cast that
8322 * is present at the top of the expression tree. It is a passed argument,
8323 * not a field of the context struct, because we change the value as we
8324 * recurse down into the expression. In general we suppress implicit casts
8325 * when the result type is known with certainty (eg, the arguments of an
8326 * OR must be boolean). We display implicit casts for arguments of functions
8327 * and operators, since this is needed to be certain that the same function
8328 * or operator will be chosen when the expression is re-parsed.
8329 * ----------
8331 static void
8332 get_rule_expr(Node *node, deparse_context *context,
8333 bool showimplicit)
8335 StringInfo buf = context->buf;
8337 if (node == NULL)
8338 return;
8340 /* Guard against excessively long or deeply-nested queries */
8341 CHECK_FOR_INTERRUPTS();
8342 check_stack_depth();
8345 * Each level of get_rule_expr must emit an indivisible term
8346 * (parenthesized if necessary) to ensure result is reparsed into the same
8347 * expression tree. The only exception is that when the input is a List,
8348 * we emit the component items comma-separated with no surrounding
8349 * decoration; this is convenient for most callers.
8351 switch (nodeTag(node))
8353 case T_Var:
8354 (void) get_variable((Var *) node, 0, false, context);
8355 break;
8357 case T_Const:
8358 get_const_expr((Const *) node, context, 0);
8359 break;
8361 case T_Param:
8362 get_parameter((Param *) node, context);
8363 break;
8365 case T_Aggref:
8366 get_agg_expr((Aggref *) node, context, (Aggref *) node);
8367 break;
8369 case T_GroupingFunc:
8371 GroupingFunc *gexpr = (GroupingFunc *) node;
8373 appendStringInfoString(buf, "GROUPING(");
8374 get_rule_expr((Node *) gexpr->args, context, true);
8375 appendStringInfoChar(buf, ')');
8377 break;
8379 case T_WindowFunc:
8380 get_windowfunc_expr((WindowFunc *) node, context);
8381 break;
8383 case T_SubscriptingRef:
8385 SubscriptingRef *sbsref = (SubscriptingRef *) node;
8386 bool need_parens;
8389 * If the argument is a CaseTestExpr, we must be inside a
8390 * FieldStore, ie, we are assigning to an element of an array
8391 * within a composite column. Since we already punted on
8392 * displaying the FieldStore's target information, just punt
8393 * here too, and display only the assignment source
8394 * expression.
8396 if (IsA(sbsref->refexpr, CaseTestExpr))
8398 Assert(sbsref->refassgnexpr);
8399 get_rule_expr((Node *) sbsref->refassgnexpr,
8400 context, showimplicit);
8401 break;
8405 * Parenthesize the argument unless it's a simple Var or a
8406 * FieldSelect. (In particular, if it's another
8407 * SubscriptingRef, we *must* parenthesize to avoid
8408 * confusion.)
8410 need_parens = !IsA(sbsref->refexpr, Var) &&
8411 !IsA(sbsref->refexpr, FieldSelect);
8412 if (need_parens)
8413 appendStringInfoChar(buf, '(');
8414 get_rule_expr((Node *) sbsref->refexpr, context, showimplicit);
8415 if (need_parens)
8416 appendStringInfoChar(buf, ')');
8419 * If there's a refassgnexpr, we want to print the node in the
8420 * format "container[subscripts] := refassgnexpr". This is
8421 * not legal SQL, so decompilation of INSERT or UPDATE
8422 * statements should always use processIndirection as part of
8423 * the statement-level syntax. We should only see this when
8424 * EXPLAIN tries to print the targetlist of a plan resulting
8425 * from such a statement.
8427 if (sbsref->refassgnexpr)
8429 Node *refassgnexpr;
8432 * Use processIndirection to print this node's subscripts
8433 * as well as any additional field selections or
8434 * subscripting in immediate descendants. It returns the
8435 * RHS expr that is actually being "assigned".
8437 refassgnexpr = processIndirection(node, context);
8438 appendStringInfoString(buf, " := ");
8439 get_rule_expr(refassgnexpr, context, showimplicit);
8441 else
8443 /* Just an ordinary container fetch, so print subscripts */
8444 printSubscripts(sbsref, context);
8447 break;
8449 case T_FuncExpr:
8450 get_func_expr((FuncExpr *) node, context, showimplicit);
8451 break;
8453 case T_NamedArgExpr:
8455 NamedArgExpr *na = (NamedArgExpr *) node;
8457 appendStringInfo(buf, "%s => ", quote_identifier(na->name));
8458 get_rule_expr((Node *) na->arg, context, showimplicit);
8460 break;
8462 case T_OpExpr:
8463 get_oper_expr((OpExpr *) node, context);
8464 break;
8466 case T_DistinctExpr:
8468 DistinctExpr *expr = (DistinctExpr *) node;
8469 List *args = expr->args;
8470 Node *arg1 = (Node *) linitial(args);
8471 Node *arg2 = (Node *) lsecond(args);
8473 if (!PRETTY_PAREN(context))
8474 appendStringInfoChar(buf, '(');
8475 get_rule_expr_paren(arg1, context, true, node);
8476 appendStringInfoString(buf, " IS DISTINCT FROM ");
8477 get_rule_expr_paren(arg2, context, true, node);
8478 if (!PRETTY_PAREN(context))
8479 appendStringInfoChar(buf, ')');
8481 break;
8483 case T_NullIfExpr:
8485 NullIfExpr *nullifexpr = (NullIfExpr *) node;
8487 appendStringInfoString(buf, "NULLIF(");
8488 get_rule_expr((Node *) nullifexpr->args, context, true);
8489 appendStringInfoChar(buf, ')');
8491 break;
8493 case T_ScalarArrayOpExpr:
8495 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
8496 List *args = expr->args;
8497 Node *arg1 = (Node *) linitial(args);
8498 Node *arg2 = (Node *) lsecond(args);
8500 if (!PRETTY_PAREN(context))
8501 appendStringInfoChar(buf, '(');
8502 get_rule_expr_paren(arg1, context, true, node);
8503 appendStringInfo(buf, " %s %s (",
8504 generate_operator_name(expr->opno,
8505 exprType(arg1),
8506 get_base_element_type(exprType(arg2))),
8507 expr->useOr ? "ANY" : "ALL");
8508 get_rule_expr_paren(arg2, context, true, node);
8511 * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
8512 * a bare sub-SELECT. Since we're here, the sub-SELECT must
8513 * be meant as a scalar sub-SELECT yielding an array value to
8514 * be used in ScalarArrayOpExpr; but the grammar will
8515 * preferentially interpret such a construct as an ANY/ALL
8516 * SubLink. To prevent misparsing the output that way, insert
8517 * a dummy coercion (which will be stripped by parse analysis,
8518 * so no inefficiency is added in dump and reload). This is
8519 * indeed most likely what the user wrote to get the construct
8520 * accepted in the first place.
8522 if (IsA(arg2, SubLink) &&
8523 ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
8524 appendStringInfo(buf, "::%s",
8525 format_type_with_typemod(exprType(arg2),
8526 exprTypmod(arg2)));
8527 appendStringInfoChar(buf, ')');
8528 if (!PRETTY_PAREN(context))
8529 appendStringInfoChar(buf, ')');
8531 break;
8533 case T_BoolExpr:
8535 BoolExpr *expr = (BoolExpr *) node;
8536 Node *first_arg = linitial(expr->args);
8537 ListCell *arg;
8539 switch (expr->boolop)
8541 case AND_EXPR:
8542 if (!PRETTY_PAREN(context))
8543 appendStringInfoChar(buf, '(');
8544 get_rule_expr_paren(first_arg, context,
8545 false, node);
8546 for_each_from(arg, expr->args, 1)
8548 appendStringInfoString(buf, " AND ");
8549 get_rule_expr_paren((Node *) lfirst(arg), context,
8550 false, node);
8552 if (!PRETTY_PAREN(context))
8553 appendStringInfoChar(buf, ')');
8554 break;
8556 case OR_EXPR:
8557 if (!PRETTY_PAREN(context))
8558 appendStringInfoChar(buf, '(');
8559 get_rule_expr_paren(first_arg, context,
8560 false, node);
8561 for_each_from(arg, expr->args, 1)
8563 appendStringInfoString(buf, " OR ");
8564 get_rule_expr_paren((Node *) lfirst(arg), context,
8565 false, node);
8567 if (!PRETTY_PAREN(context))
8568 appendStringInfoChar(buf, ')');
8569 break;
8571 case NOT_EXPR:
8572 if (!PRETTY_PAREN(context))
8573 appendStringInfoChar(buf, '(');
8574 appendStringInfoString(buf, "NOT ");
8575 get_rule_expr_paren(first_arg, context,
8576 false, node);
8577 if (!PRETTY_PAREN(context))
8578 appendStringInfoChar(buf, ')');
8579 break;
8581 default:
8582 elog(ERROR, "unrecognized boolop: %d",
8583 (int) expr->boolop);
8586 break;
8588 case T_SubLink:
8589 get_sublink_expr((SubLink *) node, context);
8590 break;
8592 case T_SubPlan:
8594 SubPlan *subplan = (SubPlan *) node;
8597 * We cannot see an already-planned subplan in rule deparsing,
8598 * only while EXPLAINing a query plan. We don't try to
8599 * reconstruct the original SQL, just reference the subplan
8600 * that appears elsewhere in EXPLAIN's result.
8602 if (subplan->useHashTable)
8603 appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
8604 else
8605 appendStringInfo(buf, "(%s)", subplan->plan_name);
8607 break;
8609 case T_AlternativeSubPlan:
8611 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
8612 ListCell *lc;
8615 * This case cannot be reached in normal usage, since no
8616 * AlternativeSubPlan can appear either in parsetrees or
8617 * finished plan trees. We keep it just in case somebody
8618 * wants to use this code to print planner data structures.
8620 appendStringInfoString(buf, "(alternatives: ");
8621 foreach(lc, asplan->subplans)
8623 SubPlan *splan = lfirst_node(SubPlan, lc);
8625 if (splan->useHashTable)
8626 appendStringInfo(buf, "hashed %s", splan->plan_name);
8627 else
8628 appendStringInfoString(buf, splan->plan_name);
8629 if (lnext(asplan->subplans, lc))
8630 appendStringInfoString(buf, " or ");
8632 appendStringInfoChar(buf, ')');
8634 break;
8636 case T_FieldSelect:
8638 FieldSelect *fselect = (FieldSelect *) node;
8639 Node *arg = (Node *) fselect->arg;
8640 int fno = fselect->fieldnum;
8641 const char *fieldname;
8642 bool need_parens;
8645 * Parenthesize the argument unless it's an SubscriptingRef or
8646 * another FieldSelect. Note in particular that it would be
8647 * WRONG to not parenthesize a Var argument; simplicity is not
8648 * the issue here, having the right number of names is.
8650 need_parens = !IsA(arg, SubscriptingRef) &&
8651 !IsA(arg, FieldSelect);
8652 if (need_parens)
8653 appendStringInfoChar(buf, '(');
8654 get_rule_expr(arg, context, true);
8655 if (need_parens)
8656 appendStringInfoChar(buf, ')');
8659 * Get and print the field name.
8661 fieldname = get_name_for_var_field((Var *) arg, fno,
8662 0, context);
8663 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
8665 break;
8667 case T_FieldStore:
8669 FieldStore *fstore = (FieldStore *) node;
8670 bool need_parens;
8673 * There is no good way to represent a FieldStore as real SQL,
8674 * so decompilation of INSERT or UPDATE statements should
8675 * always use processIndirection as part of the
8676 * statement-level syntax. We should only get here when
8677 * EXPLAIN tries to print the targetlist of a plan resulting
8678 * from such a statement. The plan case is even harder than
8679 * ordinary rules would be, because the planner tries to
8680 * collapse multiple assignments to the same field or subfield
8681 * into one FieldStore; so we can see a list of target fields
8682 * not just one, and the arguments could be FieldStores
8683 * themselves. We don't bother to try to print the target
8684 * field names; we just print the source arguments, with a
8685 * ROW() around them if there's more than one. This isn't
8686 * terribly complete, but it's probably good enough for
8687 * EXPLAIN's purposes; especially since anything more would be
8688 * either hopelessly confusing or an even poorer
8689 * representation of what the plan is actually doing.
8691 need_parens = (list_length(fstore->newvals) != 1);
8692 if (need_parens)
8693 appendStringInfoString(buf, "ROW(");
8694 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
8695 if (need_parens)
8696 appendStringInfoChar(buf, ')');
8698 break;
8700 case T_RelabelType:
8702 RelabelType *relabel = (RelabelType *) node;
8703 Node *arg = (Node *) relabel->arg;
8705 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
8706 !showimplicit)
8708 /* don't show the implicit cast */
8709 get_rule_expr_paren(arg, context, false, node);
8711 else
8713 get_coercion_expr(arg, context,
8714 relabel->resulttype,
8715 relabel->resulttypmod,
8716 node);
8719 break;
8721 case T_CoerceViaIO:
8723 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
8724 Node *arg = (Node *) iocoerce->arg;
8726 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
8727 !showimplicit)
8729 /* don't show the implicit cast */
8730 get_rule_expr_paren(arg, context, false, node);
8732 else
8734 get_coercion_expr(arg, context,
8735 iocoerce->resulttype,
8737 node);
8740 break;
8742 case T_ArrayCoerceExpr:
8744 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
8745 Node *arg = (Node *) acoerce->arg;
8747 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
8748 !showimplicit)
8750 /* don't show the implicit cast */
8751 get_rule_expr_paren(arg, context, false, node);
8753 else
8755 get_coercion_expr(arg, context,
8756 acoerce->resulttype,
8757 acoerce->resulttypmod,
8758 node);
8761 break;
8763 case T_ConvertRowtypeExpr:
8765 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
8766 Node *arg = (Node *) convert->arg;
8768 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
8769 !showimplicit)
8771 /* don't show the implicit cast */
8772 get_rule_expr_paren(arg, context, false, node);
8774 else
8776 get_coercion_expr(arg, context,
8777 convert->resulttype, -1,
8778 node);
8781 break;
8783 case T_CollateExpr:
8785 CollateExpr *collate = (CollateExpr *) node;
8786 Node *arg = (Node *) collate->arg;
8788 if (!PRETTY_PAREN(context))
8789 appendStringInfoChar(buf, '(');
8790 get_rule_expr_paren(arg, context, showimplicit, node);
8791 appendStringInfo(buf, " COLLATE %s",
8792 generate_collation_name(collate->collOid));
8793 if (!PRETTY_PAREN(context))
8794 appendStringInfoChar(buf, ')');
8796 break;
8798 case T_CaseExpr:
8800 CaseExpr *caseexpr = (CaseExpr *) node;
8801 ListCell *temp;
8803 appendContextKeyword(context, "CASE",
8804 0, PRETTYINDENT_VAR, 0);
8805 if (caseexpr->arg)
8807 appendStringInfoChar(buf, ' ');
8808 get_rule_expr((Node *) caseexpr->arg, context, true);
8810 foreach(temp, caseexpr->args)
8812 CaseWhen *when = (CaseWhen *) lfirst(temp);
8813 Node *w = (Node *) when->expr;
8815 if (caseexpr->arg)
8818 * The parser should have produced WHEN clauses of the
8819 * form "CaseTestExpr = RHS", possibly with an
8820 * implicit coercion inserted above the CaseTestExpr.
8821 * For accurate decompilation of rules it's essential
8822 * that we show just the RHS. However in an
8823 * expression that's been through the optimizer, the
8824 * WHEN clause could be almost anything (since the
8825 * equality operator could have been expanded into an
8826 * inline function). If we don't recognize the form
8827 * of the WHEN clause, just punt and display it as-is.
8829 if (IsA(w, OpExpr))
8831 List *args = ((OpExpr *) w)->args;
8833 if (list_length(args) == 2 &&
8834 IsA(strip_implicit_coercions(linitial(args)),
8835 CaseTestExpr))
8836 w = (Node *) lsecond(args);
8840 if (!PRETTY_INDENT(context))
8841 appendStringInfoChar(buf, ' ');
8842 appendContextKeyword(context, "WHEN ",
8843 0, 0, 0);
8844 get_rule_expr(w, context, false);
8845 appendStringInfoString(buf, " THEN ");
8846 get_rule_expr((Node *) when->result, context, true);
8848 if (!PRETTY_INDENT(context))
8849 appendStringInfoChar(buf, ' ');
8850 appendContextKeyword(context, "ELSE ",
8851 0, 0, 0);
8852 get_rule_expr((Node *) caseexpr->defresult, context, true);
8853 if (!PRETTY_INDENT(context))
8854 appendStringInfoChar(buf, ' ');
8855 appendContextKeyword(context, "END",
8856 -PRETTYINDENT_VAR, 0, 0);
8858 break;
8860 case T_CaseTestExpr:
8863 * Normally we should never get here, since for expressions
8864 * that can contain this node type we attempt to avoid
8865 * recursing to it. But in an optimized expression we might
8866 * be unable to avoid that (see comments for CaseExpr). If we
8867 * do see one, print it as CASE_TEST_EXPR.
8869 appendStringInfoString(buf, "CASE_TEST_EXPR");
8871 break;
8873 case T_ArrayExpr:
8875 ArrayExpr *arrayexpr = (ArrayExpr *) node;
8877 appendStringInfoString(buf, "ARRAY[");
8878 get_rule_expr((Node *) arrayexpr->elements, context, true);
8879 appendStringInfoChar(buf, ']');
8882 * If the array isn't empty, we assume its elements are
8883 * coerced to the desired type. If it's empty, though, we
8884 * need an explicit coercion to the array type.
8886 if (arrayexpr->elements == NIL)
8887 appendStringInfo(buf, "::%s",
8888 format_type_with_typemod(arrayexpr->array_typeid, -1));
8890 break;
8892 case T_RowExpr:
8894 RowExpr *rowexpr = (RowExpr *) node;
8895 TupleDesc tupdesc = NULL;
8896 ListCell *arg;
8897 int i;
8898 char *sep;
8901 * If it's a named type and not RECORD, we may have to skip
8902 * dropped columns and/or claim there are NULLs for added
8903 * columns.
8905 if (rowexpr->row_typeid != RECORDOID)
8907 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
8908 Assert(list_length(rowexpr->args) <= tupdesc->natts);
8912 * SQL99 allows "ROW" to be omitted when there is more than
8913 * one column, but for simplicity we always print it.
8915 appendStringInfoString(buf, "ROW(");
8916 sep = "";
8917 i = 0;
8918 foreach(arg, rowexpr->args)
8920 Node *e = (Node *) lfirst(arg);
8922 if (tupdesc == NULL ||
8923 !TupleDescAttr(tupdesc, i)->attisdropped)
8925 appendStringInfoString(buf, sep);
8926 /* Whole-row Vars need special treatment here */
8927 get_rule_expr_toplevel(e, context, true);
8928 sep = ", ";
8930 i++;
8932 if (tupdesc != NULL)
8934 while (i < tupdesc->natts)
8936 if (!TupleDescAttr(tupdesc, i)->attisdropped)
8938 appendStringInfoString(buf, sep);
8939 appendStringInfoString(buf, "NULL");
8940 sep = ", ";
8942 i++;
8945 ReleaseTupleDesc(tupdesc);
8947 appendStringInfoChar(buf, ')');
8948 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
8949 appendStringInfo(buf, "::%s",
8950 format_type_with_typemod(rowexpr->row_typeid, -1));
8952 break;
8954 case T_RowCompareExpr:
8956 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
8957 ListCell *arg;
8958 char *sep;
8961 * SQL99 allows "ROW" to be omitted when there is more than
8962 * one column, but for simplicity we always print it.
8964 appendStringInfoString(buf, "(ROW(");
8965 sep = "";
8966 foreach(arg, rcexpr->largs)
8968 Node *e = (Node *) lfirst(arg);
8970 appendStringInfoString(buf, sep);
8971 get_rule_expr(e, context, true);
8972 sep = ", ";
8976 * We assume that the name of the first-column operator will
8977 * do for all the rest too. This is definitely open to
8978 * failure, eg if some but not all operators were renamed
8979 * since the construct was parsed, but there seems no way to
8980 * be perfect.
8982 appendStringInfo(buf, ") %s ROW(",
8983 generate_operator_name(linitial_oid(rcexpr->opnos),
8984 exprType(linitial(rcexpr->largs)),
8985 exprType(linitial(rcexpr->rargs))));
8986 sep = "";
8987 foreach(arg, rcexpr->rargs)
8989 Node *e = (Node *) lfirst(arg);
8991 appendStringInfoString(buf, sep);
8992 get_rule_expr(e, context, true);
8993 sep = ", ";
8995 appendStringInfoString(buf, "))");
8997 break;
8999 case T_CoalesceExpr:
9001 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
9003 appendStringInfoString(buf, "COALESCE(");
9004 get_rule_expr((Node *) coalesceexpr->args, context, true);
9005 appendStringInfoChar(buf, ')');
9007 break;
9009 case T_MinMaxExpr:
9011 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
9013 switch (minmaxexpr->op)
9015 case IS_GREATEST:
9016 appendStringInfoString(buf, "GREATEST(");
9017 break;
9018 case IS_LEAST:
9019 appendStringInfoString(buf, "LEAST(");
9020 break;
9022 get_rule_expr((Node *) minmaxexpr->args, context, true);
9023 appendStringInfoChar(buf, ')');
9025 break;
9027 case T_SQLValueFunction:
9029 SQLValueFunction *svf = (SQLValueFunction *) node;
9032 * Note: this code knows that typmod for time, timestamp, and
9033 * timestamptz just prints as integer.
9035 switch (svf->op)
9037 case SVFOP_CURRENT_DATE:
9038 appendStringInfoString(buf, "CURRENT_DATE");
9039 break;
9040 case SVFOP_CURRENT_TIME:
9041 appendStringInfoString(buf, "CURRENT_TIME");
9042 break;
9043 case SVFOP_CURRENT_TIME_N:
9044 appendStringInfo(buf, "CURRENT_TIME(%d)", svf->typmod);
9045 break;
9046 case SVFOP_CURRENT_TIMESTAMP:
9047 appendStringInfoString(buf, "CURRENT_TIMESTAMP");
9048 break;
9049 case SVFOP_CURRENT_TIMESTAMP_N:
9050 appendStringInfo(buf, "CURRENT_TIMESTAMP(%d)",
9051 svf->typmod);
9052 break;
9053 case SVFOP_LOCALTIME:
9054 appendStringInfoString(buf, "LOCALTIME");
9055 break;
9056 case SVFOP_LOCALTIME_N:
9057 appendStringInfo(buf, "LOCALTIME(%d)", svf->typmod);
9058 break;
9059 case SVFOP_LOCALTIMESTAMP:
9060 appendStringInfoString(buf, "LOCALTIMESTAMP");
9061 break;
9062 case SVFOP_LOCALTIMESTAMP_N:
9063 appendStringInfo(buf, "LOCALTIMESTAMP(%d)",
9064 svf->typmod);
9065 break;
9066 case SVFOP_CURRENT_ROLE:
9067 appendStringInfoString(buf, "CURRENT_ROLE");
9068 break;
9069 case SVFOP_CURRENT_USER:
9070 appendStringInfoString(buf, "CURRENT_USER");
9071 break;
9072 case SVFOP_USER:
9073 appendStringInfoString(buf, "USER");
9074 break;
9075 case SVFOP_SESSION_USER:
9076 appendStringInfoString(buf, "SESSION_USER");
9077 break;
9078 case SVFOP_CURRENT_CATALOG:
9079 appendStringInfoString(buf, "CURRENT_CATALOG");
9080 break;
9081 case SVFOP_CURRENT_SCHEMA:
9082 appendStringInfoString(buf, "CURRENT_SCHEMA");
9083 break;
9086 break;
9088 case T_XmlExpr:
9090 XmlExpr *xexpr = (XmlExpr *) node;
9091 bool needcomma = false;
9092 ListCell *arg;
9093 ListCell *narg;
9094 Const *con;
9096 switch (xexpr->op)
9098 case IS_XMLCONCAT:
9099 appendStringInfoString(buf, "XMLCONCAT(");
9100 break;
9101 case IS_XMLELEMENT:
9102 appendStringInfoString(buf, "XMLELEMENT(");
9103 break;
9104 case IS_XMLFOREST:
9105 appendStringInfoString(buf, "XMLFOREST(");
9106 break;
9107 case IS_XMLPARSE:
9108 appendStringInfoString(buf, "XMLPARSE(");
9109 break;
9110 case IS_XMLPI:
9111 appendStringInfoString(buf, "XMLPI(");
9112 break;
9113 case IS_XMLROOT:
9114 appendStringInfoString(buf, "XMLROOT(");
9115 break;
9116 case IS_XMLSERIALIZE:
9117 appendStringInfoString(buf, "XMLSERIALIZE(");
9118 break;
9119 case IS_DOCUMENT:
9120 break;
9122 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
9124 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
9125 appendStringInfoString(buf, "DOCUMENT ");
9126 else
9127 appendStringInfoString(buf, "CONTENT ");
9129 if (xexpr->name)
9131 appendStringInfo(buf, "NAME %s",
9132 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
9133 needcomma = true;
9135 if (xexpr->named_args)
9137 if (xexpr->op != IS_XMLFOREST)
9139 if (needcomma)
9140 appendStringInfoString(buf, ", ");
9141 appendStringInfoString(buf, "XMLATTRIBUTES(");
9142 needcomma = false;
9144 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
9146 Node *e = (Node *) lfirst(arg);
9147 char *argname = strVal(lfirst(narg));
9149 if (needcomma)
9150 appendStringInfoString(buf, ", ");
9151 get_rule_expr((Node *) e, context, true);
9152 appendStringInfo(buf, " AS %s",
9153 quote_identifier(map_xml_name_to_sql_identifier(argname)));
9154 needcomma = true;
9156 if (xexpr->op != IS_XMLFOREST)
9157 appendStringInfoChar(buf, ')');
9159 if (xexpr->args)
9161 if (needcomma)
9162 appendStringInfoString(buf, ", ");
9163 switch (xexpr->op)
9165 case IS_XMLCONCAT:
9166 case IS_XMLELEMENT:
9167 case IS_XMLFOREST:
9168 case IS_XMLPI:
9169 case IS_XMLSERIALIZE:
9170 /* no extra decoration needed */
9171 get_rule_expr((Node *) xexpr->args, context, true);
9172 break;
9173 case IS_XMLPARSE:
9174 Assert(list_length(xexpr->args) == 2);
9176 get_rule_expr((Node *) linitial(xexpr->args),
9177 context, true);
9179 con = lsecond_node(Const, xexpr->args);
9180 Assert(!con->constisnull);
9181 if (DatumGetBool(con->constvalue))
9182 appendStringInfoString(buf,
9183 " PRESERVE WHITESPACE");
9184 else
9185 appendStringInfoString(buf,
9186 " STRIP WHITESPACE");
9187 break;
9188 case IS_XMLROOT:
9189 Assert(list_length(xexpr->args) == 3);
9191 get_rule_expr((Node *) linitial(xexpr->args),
9192 context, true);
9194 appendStringInfoString(buf, ", VERSION ");
9195 con = (Const *) lsecond(xexpr->args);
9196 if (IsA(con, Const) &&
9197 con->constisnull)
9198 appendStringInfoString(buf, "NO VALUE");
9199 else
9200 get_rule_expr((Node *) con, context, false);
9202 con = lthird_node(Const, xexpr->args);
9203 if (con->constisnull)
9204 /* suppress STANDALONE NO VALUE */ ;
9205 else
9207 switch (DatumGetInt32(con->constvalue))
9209 case XML_STANDALONE_YES:
9210 appendStringInfoString(buf,
9211 ", STANDALONE YES");
9212 break;
9213 case XML_STANDALONE_NO:
9214 appendStringInfoString(buf,
9215 ", STANDALONE NO");
9216 break;
9217 case XML_STANDALONE_NO_VALUE:
9218 appendStringInfoString(buf,
9219 ", STANDALONE NO VALUE");
9220 break;
9221 default:
9222 break;
9225 break;
9226 case IS_DOCUMENT:
9227 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
9228 break;
9232 if (xexpr->op == IS_XMLSERIALIZE)
9233 appendStringInfo(buf, " AS %s",
9234 format_type_with_typemod(xexpr->type,
9235 xexpr->typmod));
9236 if (xexpr->op == IS_DOCUMENT)
9237 appendStringInfoString(buf, " IS DOCUMENT");
9238 else
9239 appendStringInfoChar(buf, ')');
9241 break;
9243 case T_NullTest:
9245 NullTest *ntest = (NullTest *) node;
9247 if (!PRETTY_PAREN(context))
9248 appendStringInfoChar(buf, '(');
9249 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
9252 * For scalar inputs, we prefer to print as IS [NOT] NULL,
9253 * which is shorter and traditional. If it's a rowtype input
9254 * but we're applying a scalar test, must print IS [NOT]
9255 * DISTINCT FROM NULL to be semantically correct.
9257 if (ntest->argisrow ||
9258 !type_is_rowtype(exprType((Node *) ntest->arg)))
9260 switch (ntest->nulltesttype)
9262 case IS_NULL:
9263 appendStringInfoString(buf, " IS NULL");
9264 break;
9265 case IS_NOT_NULL:
9266 appendStringInfoString(buf, " IS NOT NULL");
9267 break;
9268 default:
9269 elog(ERROR, "unrecognized nulltesttype: %d",
9270 (int) ntest->nulltesttype);
9273 else
9275 switch (ntest->nulltesttype)
9277 case IS_NULL:
9278 appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL");
9279 break;
9280 case IS_NOT_NULL:
9281 appendStringInfoString(buf, " IS DISTINCT FROM NULL");
9282 break;
9283 default:
9284 elog(ERROR, "unrecognized nulltesttype: %d",
9285 (int) ntest->nulltesttype);
9288 if (!PRETTY_PAREN(context))
9289 appendStringInfoChar(buf, ')');
9291 break;
9293 case T_BooleanTest:
9295 BooleanTest *btest = (BooleanTest *) node;
9297 if (!PRETTY_PAREN(context))
9298 appendStringInfoChar(buf, '(');
9299 get_rule_expr_paren((Node *) btest->arg, context, false, node);
9300 switch (btest->booltesttype)
9302 case IS_TRUE:
9303 appendStringInfoString(buf, " IS TRUE");
9304 break;
9305 case IS_NOT_TRUE:
9306 appendStringInfoString(buf, " IS NOT TRUE");
9307 break;
9308 case IS_FALSE:
9309 appendStringInfoString(buf, " IS FALSE");
9310 break;
9311 case IS_NOT_FALSE:
9312 appendStringInfoString(buf, " IS NOT FALSE");
9313 break;
9314 case IS_UNKNOWN:
9315 appendStringInfoString(buf, " IS UNKNOWN");
9316 break;
9317 case IS_NOT_UNKNOWN:
9318 appendStringInfoString(buf, " IS NOT UNKNOWN");
9319 break;
9320 default:
9321 elog(ERROR, "unrecognized booltesttype: %d",
9322 (int) btest->booltesttype);
9324 if (!PRETTY_PAREN(context))
9325 appendStringInfoChar(buf, ')');
9327 break;
9329 case T_CoerceToDomain:
9331 CoerceToDomain *ctest = (CoerceToDomain *) node;
9332 Node *arg = (Node *) ctest->arg;
9334 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
9335 !showimplicit)
9337 /* don't show the implicit cast */
9338 get_rule_expr(arg, context, false);
9340 else
9342 get_coercion_expr(arg, context,
9343 ctest->resulttype,
9344 ctest->resulttypmod,
9345 node);
9348 break;
9350 case T_CoerceToDomainValue:
9351 appendStringInfoString(buf, "VALUE");
9352 break;
9354 case T_SetToDefault:
9355 appendStringInfoString(buf, "DEFAULT");
9356 break;
9358 case T_CurrentOfExpr:
9360 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
9362 if (cexpr->cursor_name)
9363 appendStringInfo(buf, "CURRENT OF %s",
9364 quote_identifier(cexpr->cursor_name));
9365 else
9366 appendStringInfo(buf, "CURRENT OF $%d",
9367 cexpr->cursor_param);
9369 break;
9371 case T_NextValueExpr:
9373 NextValueExpr *nvexpr = (NextValueExpr *) node;
9376 * This isn't exactly nextval(), but that seems close enough
9377 * for EXPLAIN's purposes.
9379 appendStringInfoString(buf, "nextval(");
9380 simple_quote_literal(buf,
9381 generate_relation_name(nvexpr->seqid,
9382 NIL));
9383 appendStringInfoChar(buf, ')');
9385 break;
9387 case T_InferenceElem:
9389 InferenceElem *iexpr = (InferenceElem *) node;
9390 bool save_varprefix;
9391 bool need_parens;
9394 * InferenceElem can only refer to target relation, so a
9395 * prefix is not useful, and indeed would cause parse errors.
9397 save_varprefix = context->varprefix;
9398 context->varprefix = false;
9401 * Parenthesize the element unless it's a simple Var or a bare
9402 * function call. Follows pg_get_indexdef_worker().
9404 need_parens = !IsA(iexpr->expr, Var);
9405 if (IsA(iexpr->expr, FuncExpr) &&
9406 ((FuncExpr *) iexpr->expr)->funcformat ==
9407 COERCE_EXPLICIT_CALL)
9408 need_parens = false;
9410 if (need_parens)
9411 appendStringInfoChar(buf, '(');
9412 get_rule_expr((Node *) iexpr->expr,
9413 context, false);
9414 if (need_parens)
9415 appendStringInfoChar(buf, ')');
9417 context->varprefix = save_varprefix;
9419 if (iexpr->infercollid)
9420 appendStringInfo(buf, " COLLATE %s",
9421 generate_collation_name(iexpr->infercollid));
9423 /* Add the operator class name, if not default */
9424 if (iexpr->inferopclass)
9426 Oid inferopclass = iexpr->inferopclass;
9427 Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass);
9429 get_opclass_name(inferopclass, inferopcinputtype, buf);
9432 break;
9434 case T_PartitionBoundSpec:
9436 PartitionBoundSpec *spec = (PartitionBoundSpec *) node;
9437 ListCell *cell;
9438 char *sep;
9440 if (spec->is_default)
9442 appendStringInfoString(buf, "DEFAULT");
9443 break;
9446 switch (spec->strategy)
9448 case PARTITION_STRATEGY_HASH:
9449 Assert(spec->modulus > 0 && spec->remainder >= 0);
9450 Assert(spec->modulus > spec->remainder);
9452 appendStringInfoString(buf, "FOR VALUES");
9453 appendStringInfo(buf, " WITH (modulus %d, remainder %d)",
9454 spec->modulus, spec->remainder);
9455 break;
9457 case PARTITION_STRATEGY_LIST:
9458 Assert(spec->listdatums != NIL);
9460 appendStringInfoString(buf, "FOR VALUES IN (");
9461 sep = "";
9462 foreach(cell, spec->listdatums)
9464 Const *val = lfirst_node(Const, cell);
9466 appendStringInfoString(buf, sep);
9467 get_const_expr(val, context, -1);
9468 sep = ", ";
9471 appendStringInfoChar(buf, ')');
9472 break;
9474 case PARTITION_STRATEGY_RANGE:
9475 Assert(spec->lowerdatums != NIL &&
9476 spec->upperdatums != NIL &&
9477 list_length(spec->lowerdatums) ==
9478 list_length(spec->upperdatums));
9480 appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
9481 get_range_partbound_string(spec->lowerdatums),
9482 get_range_partbound_string(spec->upperdatums));
9483 break;
9485 default:
9486 elog(ERROR, "unrecognized partition strategy: %d",
9487 (int) spec->strategy);
9488 break;
9491 break;
9493 case T_List:
9495 char *sep;
9496 ListCell *l;
9498 sep = "";
9499 foreach(l, (List *) node)
9501 appendStringInfoString(buf, sep);
9502 get_rule_expr((Node *) lfirst(l), context, showimplicit);
9503 sep = ", ";
9506 break;
9508 case T_TableFunc:
9509 get_tablefunc((TableFunc *) node, context, showimplicit);
9510 break;
9512 default:
9513 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
9514 break;
9519 * get_rule_expr_toplevel - Parse back a toplevel expression
9521 * Same as get_rule_expr(), except that if the expr is just a Var, we pass
9522 * istoplevel = true not false to get_variable(). This causes whole-row Vars
9523 * to get printed with decoration that will prevent expansion of "*".
9524 * We need to use this in contexts such as ROW() and VALUES(), where the
9525 * parser would expand "foo.*" appearing at top level. (In principle we'd
9526 * use this in get_target_list() too, but that has additional worries about
9527 * whether to print AS, so it needs to invoke get_variable() directly anyway.)
9529 static void
9530 get_rule_expr_toplevel(Node *node, deparse_context *context,
9531 bool showimplicit)
9533 if (node && IsA(node, Var))
9534 (void) get_variable((Var *) node, 0, true, context);
9535 else
9536 get_rule_expr(node, context, showimplicit);
9540 * get_rule_expr_funccall - Parse back a function-call expression
9542 * Same as get_rule_expr(), except that we guarantee that the output will
9543 * look like a function call, or like one of the things the grammar treats as
9544 * equivalent to a function call (see the func_expr_windowless production).
9545 * This is needed in places where the grammar uses func_expr_windowless and
9546 * you can't substitute a parenthesized a_expr. If what we have isn't going
9547 * to look like a function call, wrap it in a dummy CAST() expression, which
9548 * will satisfy the grammar --- and, indeed, is likely what the user wrote to
9549 * produce such a thing.
9551 static void
9552 get_rule_expr_funccall(Node *node, deparse_context *context,
9553 bool showimplicit)
9555 if (looks_like_function(node))
9556 get_rule_expr(node, context, showimplicit);
9557 else
9559 StringInfo buf = context->buf;
9561 appendStringInfoString(buf, "CAST(");
9562 /* no point in showing any top-level implicit cast */
9563 get_rule_expr(node, context, false);
9564 appendStringInfo(buf, " AS %s)",
9565 format_type_with_typemod(exprType(node),
9566 exprTypmod(node)));
9571 * Helper function to identify node types that satisfy func_expr_windowless.
9572 * If in doubt, "false" is always a safe answer.
9574 static bool
9575 looks_like_function(Node *node)
9577 if (node == NULL)
9578 return false; /* probably shouldn't happen */
9579 switch (nodeTag(node))
9581 case T_FuncExpr:
9582 /* OK, unless it's going to deparse as a cast */
9583 return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL ||
9584 ((FuncExpr *) node)->funcformat == COERCE_SQL_SYNTAX);
9585 case T_NullIfExpr:
9586 case T_CoalesceExpr:
9587 case T_MinMaxExpr:
9588 case T_SQLValueFunction:
9589 case T_XmlExpr:
9590 /* these are all accepted by func_expr_common_subexpr */
9591 return true;
9592 default:
9593 break;
9595 return false;
9600 * get_oper_expr - Parse back an OpExpr node
9602 static void
9603 get_oper_expr(OpExpr *expr, deparse_context *context)
9605 StringInfo buf = context->buf;
9606 Oid opno = expr->opno;
9607 List *args = expr->args;
9609 if (!PRETTY_PAREN(context))
9610 appendStringInfoChar(buf, '(');
9611 if (list_length(args) == 2)
9613 /* binary operator */
9614 Node *arg1 = (Node *) linitial(args);
9615 Node *arg2 = (Node *) lsecond(args);
9617 get_rule_expr_paren(arg1, context, true, (Node *) expr);
9618 appendStringInfo(buf, " %s ",
9619 generate_operator_name(opno,
9620 exprType(arg1),
9621 exprType(arg2)));
9622 get_rule_expr_paren(arg2, context, true, (Node *) expr);
9624 else
9626 /* prefix operator */
9627 Node *arg = (Node *) linitial(args);
9629 appendStringInfo(buf, "%s ",
9630 generate_operator_name(opno,
9631 InvalidOid,
9632 exprType(arg)));
9633 get_rule_expr_paren(arg, context, true, (Node *) expr);
9635 if (!PRETTY_PAREN(context))
9636 appendStringInfoChar(buf, ')');
9640 * get_func_expr - Parse back a FuncExpr node
9642 static void
9643 get_func_expr(FuncExpr *expr, deparse_context *context,
9644 bool showimplicit)
9646 StringInfo buf = context->buf;
9647 Oid funcoid = expr->funcid;
9648 Oid argtypes[FUNC_MAX_ARGS];
9649 int nargs;
9650 List *argnames;
9651 bool use_variadic;
9652 ListCell *l;
9655 * If the function call came from an implicit coercion, then just show the
9656 * first argument --- unless caller wants to see implicit coercions.
9658 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9660 get_rule_expr_paren((Node *) linitial(expr->args), context,
9661 false, (Node *) expr);
9662 return;
9666 * If the function call came from a cast, then show the first argument
9667 * plus an explicit cast operation.
9669 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9670 expr->funcformat == COERCE_IMPLICIT_CAST)
9672 Node *arg = linitial(expr->args);
9673 Oid rettype = expr->funcresulttype;
9674 int32 coercedTypmod;
9676 /* Get the typmod if this is a length-coercion function */
9677 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9679 get_coercion_expr(arg, context,
9680 rettype, coercedTypmod,
9681 (Node *) expr);
9683 return;
9687 * If the function was called using one of the SQL spec's random special
9688 * syntaxes, try to reproduce that. If we don't recognize the function,
9689 * fall through.
9691 if (expr->funcformat == COERCE_SQL_SYNTAX)
9693 if (get_func_sql_syntax(expr, context))
9694 return;
9698 * Normal function: display as proname(args). First we need to extract
9699 * the argument datatypes.
9701 if (list_length(expr->args) > FUNC_MAX_ARGS)
9702 ereport(ERROR,
9703 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9704 errmsg("too many arguments")));
9705 nargs = 0;
9706 argnames = NIL;
9707 foreach(l, expr->args)
9709 Node *arg = (Node *) lfirst(l);
9711 if (IsA(arg, NamedArgExpr))
9712 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9713 argtypes[nargs] = exprType(arg);
9714 nargs++;
9717 appendStringInfo(buf, "%s(",
9718 generate_function_name(funcoid, nargs,
9719 argnames, argtypes,
9720 expr->funcvariadic,
9721 &use_variadic,
9722 context->special_exprkind));
9723 nargs = 0;
9724 foreach(l, expr->args)
9726 if (nargs++ > 0)
9727 appendStringInfoString(buf, ", ");
9728 if (use_variadic && lnext(expr->args, l) == NULL)
9729 appendStringInfoString(buf, "VARIADIC ");
9730 get_rule_expr((Node *) lfirst(l), context, true);
9732 appendStringInfoChar(buf, ')');
9736 * get_agg_expr - Parse back an Aggref node
9738 static void
9739 get_agg_expr(Aggref *aggref, deparse_context *context,
9740 Aggref *original_aggref)
9742 StringInfo buf = context->buf;
9743 Oid argtypes[FUNC_MAX_ARGS];
9744 int nargs;
9745 bool use_variadic;
9748 * For a combining aggregate, we look up and deparse the corresponding
9749 * partial aggregate instead. This is necessary because our input
9750 * argument list has been replaced; the new argument list always has just
9751 * one element, which will point to a partial Aggref that supplies us with
9752 * transition states to combine.
9754 if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9756 TargetEntry *tle;
9758 Assert(list_length(aggref->args) == 1);
9759 tle = linitial_node(TargetEntry, aggref->args);
9760 resolve_special_varno((Node *) tle->expr, context,
9761 get_agg_combine_expr, original_aggref);
9762 return;
9766 * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9767 * to avoid printing this when recursing from the code just above.
9769 if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9770 appendStringInfoString(buf, "PARTIAL ");
9772 /* Extract the argument types as seen by the parser */
9773 nargs = get_aggregate_argtypes(aggref, argtypes);
9775 /* Print the aggregate name, schema-qualified if needed */
9776 appendStringInfo(buf, "%s(%s",
9777 generate_function_name(aggref->aggfnoid, nargs,
9778 NIL, argtypes,
9779 aggref->aggvariadic,
9780 &use_variadic,
9781 context->special_exprkind),
9782 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9784 if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9787 * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9788 * worry about inserting VARIADIC. So we can just dump the direct
9789 * args as-is.
9791 Assert(!aggref->aggvariadic);
9792 get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9793 Assert(aggref->aggorder != NIL);
9794 appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9795 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9797 else
9799 /* aggstar can be set only in zero-argument aggregates */
9800 if (aggref->aggstar)
9801 appendStringInfoChar(buf, '*');
9802 else
9804 ListCell *l;
9805 int i;
9807 i = 0;
9808 foreach(l, aggref->args)
9810 TargetEntry *tle = (TargetEntry *) lfirst(l);
9811 Node *arg = (Node *) tle->expr;
9813 Assert(!IsA(arg, NamedArgExpr));
9814 if (tle->resjunk)
9815 continue;
9816 if (i++ > 0)
9817 appendStringInfoString(buf, ", ");
9818 if (use_variadic && i == nargs)
9819 appendStringInfoString(buf, "VARIADIC ");
9820 get_rule_expr(arg, context, true);
9824 if (aggref->aggorder != NIL)
9826 appendStringInfoString(buf, " ORDER BY ");
9827 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9831 if (aggref->aggfilter != NULL)
9833 appendStringInfoString(buf, ") FILTER (WHERE ");
9834 get_rule_expr((Node *) aggref->aggfilter, context, false);
9837 appendStringInfoChar(buf, ')');
9841 * This is a helper function for get_agg_expr(). It's used when we deparse
9842 * a combining Aggref; resolve_special_varno locates the corresponding partial
9843 * Aggref and then calls this.
9845 static void
9846 get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
9848 Aggref *aggref;
9849 Aggref *original_aggref = callback_arg;
9851 if (!IsA(node, Aggref))
9852 elog(ERROR, "combining Aggref does not point to an Aggref");
9854 aggref = (Aggref *) node;
9855 get_agg_expr(aggref, context, original_aggref);
9859 * get_windowfunc_expr - Parse back a WindowFunc node
9861 static void
9862 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
9864 StringInfo buf = context->buf;
9865 Oid argtypes[FUNC_MAX_ARGS];
9866 int nargs;
9867 List *argnames;
9868 ListCell *l;
9870 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
9871 ereport(ERROR,
9872 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9873 errmsg("too many arguments")));
9874 nargs = 0;
9875 argnames = NIL;
9876 foreach(l, wfunc->args)
9878 Node *arg = (Node *) lfirst(l);
9880 if (IsA(arg, NamedArgExpr))
9881 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9882 argtypes[nargs] = exprType(arg);
9883 nargs++;
9886 appendStringInfo(buf, "%s(",
9887 generate_function_name(wfunc->winfnoid, nargs,
9888 argnames, argtypes,
9889 false, NULL,
9890 context->special_exprkind));
9891 /* winstar can be set only in zero-argument aggregates */
9892 if (wfunc->winstar)
9893 appendStringInfoChar(buf, '*');
9894 else
9895 get_rule_expr((Node *) wfunc->args, context, true);
9897 if (wfunc->aggfilter != NULL)
9899 appendStringInfoString(buf, ") FILTER (WHERE ");
9900 get_rule_expr((Node *) wfunc->aggfilter, context, false);
9903 appendStringInfoString(buf, ") OVER ");
9905 foreach(l, context->windowClause)
9907 WindowClause *wc = (WindowClause *) lfirst(l);
9909 if (wc->winref == wfunc->winref)
9911 if (wc->name)
9912 appendStringInfoString(buf, quote_identifier(wc->name));
9913 else
9914 get_rule_windowspec(wc, context->windowTList, context);
9915 break;
9918 if (l == NULL)
9920 if (context->windowClause)
9921 elog(ERROR, "could not find window clause for winref %u",
9922 wfunc->winref);
9925 * In EXPLAIN, we don't have window context information available, so
9926 * we have to settle for this:
9928 appendStringInfoString(buf, "(?)");
9933 * get_func_sql_syntax - Parse back a SQL-syntax function call
9935 * Returns true if we successfully deparsed, false if we did not
9936 * recognize the function.
9938 static bool
9939 get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
9941 StringInfo buf = context->buf;
9942 Oid funcoid = expr->funcid;
9944 switch (funcoid)
9946 case F_TIMEZONE_INTERVAL_TIMESTAMP:
9947 case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
9948 case F_TIMEZONE_INTERVAL_TIMETZ:
9949 case F_TIMEZONE_TEXT_TIMESTAMP:
9950 case F_TIMEZONE_TEXT_TIMESTAMPTZ:
9951 case F_TIMEZONE_TEXT_TIMETZ:
9952 /* AT TIME ZONE ... note reversed argument order */
9953 appendStringInfoChar(buf, '(');
9954 get_rule_expr((Node *) lsecond(expr->args), context, false);
9955 appendStringInfoString(buf, " AT TIME ZONE ");
9956 get_rule_expr((Node *) linitial(expr->args), context, false);
9957 appendStringInfoChar(buf, ')');
9958 return true;
9960 case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
9961 case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
9962 case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
9963 case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
9964 case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
9965 case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
9966 case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
9967 case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
9968 case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
9969 case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
9970 case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
9971 case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
9972 case F_OVERLAPS_TIME_TIME_TIME_TIME:
9973 /* (x1, x2) OVERLAPS (y1, y2) */
9974 appendStringInfoString(buf, "((");
9975 get_rule_expr((Node *) linitial(expr->args), context, false);
9976 appendStringInfoString(buf, ", ");
9977 get_rule_expr((Node *) lsecond(expr->args), context, false);
9978 appendStringInfoString(buf, ") OVERLAPS (");
9979 get_rule_expr((Node *) lthird(expr->args), context, false);
9980 appendStringInfoString(buf, ", ");
9981 get_rule_expr((Node *) lfourth(expr->args), context, false);
9982 appendStringInfoString(buf, "))");
9983 return true;
9985 case F_EXTRACT_TEXT_DATE:
9986 case F_EXTRACT_TEXT_TIME:
9987 case F_EXTRACT_TEXT_TIMETZ:
9988 case F_EXTRACT_TEXT_TIMESTAMP:
9989 case F_EXTRACT_TEXT_TIMESTAMPTZ:
9990 case F_EXTRACT_TEXT_INTERVAL:
9991 /* EXTRACT (x FROM y) */
9992 appendStringInfoString(buf, "EXTRACT(");
9994 Const *con = (Const *) linitial(expr->args);
9996 Assert(IsA(con, Const) &&
9997 con->consttype == TEXTOID &&
9998 !con->constisnull);
9999 appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
10001 appendStringInfoString(buf, " FROM ");
10002 get_rule_expr((Node *) lsecond(expr->args), context, false);
10003 appendStringInfoChar(buf, ')');
10004 return true;
10006 case F_IS_NORMALIZED:
10007 /* IS xxx NORMALIZED */
10008 appendStringInfoString(buf, "((");
10009 get_rule_expr((Node *) linitial(expr->args), context, false);
10010 appendStringInfoString(buf, ") IS");
10011 if (list_length(expr->args) == 2)
10013 Const *con = (Const *) lsecond(expr->args);
10015 Assert(IsA(con, Const) &&
10016 con->consttype == TEXTOID &&
10017 !con->constisnull);
10018 appendStringInfo(buf, " %s",
10019 TextDatumGetCString(con->constvalue));
10021 appendStringInfoString(buf, " NORMALIZED)");
10022 return true;
10024 case F_PG_COLLATION_FOR:
10025 /* COLLATION FOR */
10026 appendStringInfoString(buf, "COLLATION FOR (");
10027 get_rule_expr((Node *) linitial(expr->args), context, false);
10028 appendStringInfoChar(buf, ')');
10029 return true;
10032 * XXX EXTRACT, a/k/a date_part(), is intentionally not covered
10033 * yet. Add it after we change the return type to numeric.
10036 case F_NORMALIZE:
10037 /* NORMALIZE() */
10038 appendStringInfoString(buf, "NORMALIZE(");
10039 get_rule_expr((Node *) linitial(expr->args), context, false);
10040 if (list_length(expr->args) == 2)
10042 Const *con = (Const *) lsecond(expr->args);
10044 Assert(IsA(con, Const) &&
10045 con->consttype == TEXTOID &&
10046 !con->constisnull);
10047 appendStringInfo(buf, ", %s",
10048 TextDatumGetCString(con->constvalue));
10050 appendStringInfoChar(buf, ')');
10051 return true;
10053 case F_OVERLAY_BIT_BIT_INT4:
10054 case F_OVERLAY_BIT_BIT_INT4_INT4:
10055 case F_OVERLAY_BYTEA_BYTEA_INT4:
10056 case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
10057 case F_OVERLAY_TEXT_TEXT_INT4:
10058 case F_OVERLAY_TEXT_TEXT_INT4_INT4:
10059 /* OVERLAY() */
10060 appendStringInfoString(buf, "OVERLAY(");
10061 get_rule_expr((Node *) linitial(expr->args), context, false);
10062 appendStringInfoString(buf, " PLACING ");
10063 get_rule_expr((Node *) lsecond(expr->args), context, false);
10064 appendStringInfoString(buf, " FROM ");
10065 get_rule_expr((Node *) lthird(expr->args), context, false);
10066 if (list_length(expr->args) == 4)
10068 appendStringInfoString(buf, " FOR ");
10069 get_rule_expr((Node *) lfourth(expr->args), context, false);
10071 appendStringInfoChar(buf, ')');
10072 return true;
10074 case F_POSITION_BIT_BIT:
10075 case F_POSITION_BYTEA_BYTEA:
10076 case F_POSITION_TEXT_TEXT:
10077 /* POSITION() ... extra parens since args are b_expr not a_expr */
10078 appendStringInfoString(buf, "POSITION((");
10079 get_rule_expr((Node *) lsecond(expr->args), context, false);
10080 appendStringInfoString(buf, ") IN (");
10081 get_rule_expr((Node *) linitial(expr->args), context, false);
10082 appendStringInfoString(buf, "))");
10083 return true;
10085 case F_SUBSTRING_BIT_INT4:
10086 case F_SUBSTRING_BIT_INT4_INT4:
10087 case F_SUBSTRING_BYTEA_INT4:
10088 case F_SUBSTRING_BYTEA_INT4_INT4:
10089 case F_SUBSTRING_TEXT_INT4:
10090 case F_SUBSTRING_TEXT_INT4_INT4:
10091 /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
10092 appendStringInfoString(buf, "SUBSTRING(");
10093 get_rule_expr((Node *) linitial(expr->args), context, false);
10094 appendStringInfoString(buf, " FROM ");
10095 get_rule_expr((Node *) lsecond(expr->args), context, false);
10096 if (list_length(expr->args) == 3)
10098 appendStringInfoString(buf, " FOR ");
10099 get_rule_expr((Node *) lthird(expr->args), context, false);
10101 appendStringInfoChar(buf, ')');
10102 return true;
10104 case F_SUBSTRING_TEXT_TEXT_TEXT:
10105 /* SUBSTRING SIMILAR/ESCAPE */
10106 appendStringInfoString(buf, "SUBSTRING(");
10107 get_rule_expr((Node *) linitial(expr->args), context, false);
10108 appendStringInfoString(buf, " SIMILAR ");
10109 get_rule_expr((Node *) lsecond(expr->args), context, false);
10110 appendStringInfoString(buf, " ESCAPE ");
10111 get_rule_expr((Node *) lthird(expr->args), context, false);
10112 appendStringInfoChar(buf, ')');
10113 return true;
10115 case F_BTRIM_BYTEA_BYTEA:
10116 case F_BTRIM_TEXT:
10117 case F_BTRIM_TEXT_TEXT:
10118 /* TRIM() */
10119 appendStringInfoString(buf, "TRIM(BOTH");
10120 if (list_length(expr->args) == 2)
10122 appendStringInfoChar(buf, ' ');
10123 get_rule_expr((Node *) lsecond(expr->args), context, false);
10125 appendStringInfoString(buf, " FROM ");
10126 get_rule_expr((Node *) linitial(expr->args), context, false);
10127 appendStringInfoChar(buf, ')');
10128 return true;
10130 case F_LTRIM_BYTEA_BYTEA:
10131 case F_LTRIM_TEXT:
10132 case F_LTRIM_TEXT_TEXT:
10133 /* TRIM() */
10134 appendStringInfoString(buf, "TRIM(LEADING");
10135 if (list_length(expr->args) == 2)
10137 appendStringInfoChar(buf, ' ');
10138 get_rule_expr((Node *) lsecond(expr->args), context, false);
10140 appendStringInfoString(buf, " FROM ");
10141 get_rule_expr((Node *) linitial(expr->args), context, false);
10142 appendStringInfoChar(buf, ')');
10143 return true;
10145 case F_RTRIM_BYTEA_BYTEA:
10146 case F_RTRIM_TEXT:
10147 case F_RTRIM_TEXT_TEXT:
10148 /* TRIM() */
10149 appendStringInfoString(buf, "TRIM(TRAILING");
10150 if (list_length(expr->args) == 2)
10152 appendStringInfoChar(buf, ' ');
10153 get_rule_expr((Node *) lsecond(expr->args), context, false);
10155 appendStringInfoString(buf, " FROM ");
10156 get_rule_expr((Node *) linitial(expr->args), context, false);
10157 appendStringInfoChar(buf, ')');
10158 return true;
10160 case F_XMLEXISTS:
10161 /* XMLEXISTS ... extra parens because args are c_expr */
10162 appendStringInfoString(buf, "XMLEXISTS((");
10163 get_rule_expr((Node *) linitial(expr->args), context, false);
10164 appendStringInfoString(buf, ") PASSING (");
10165 get_rule_expr((Node *) lsecond(expr->args), context, false);
10166 appendStringInfoString(buf, "))");
10167 return true;
10169 return false;
10172 /* ----------
10173 * get_coercion_expr
10175 * Make a string representation of a value coerced to a specific type
10176 * ----------
10178 static void
10179 get_coercion_expr(Node *arg, deparse_context *context,
10180 Oid resulttype, int32 resulttypmod,
10181 Node *parentNode)
10183 StringInfo buf = context->buf;
10186 * Since parse_coerce.c doesn't immediately collapse application of
10187 * length-coercion functions to constants, what we'll typically see in
10188 * such cases is a Const with typmod -1 and a length-coercion function
10189 * right above it. Avoid generating redundant output. However, beware of
10190 * suppressing casts when the user actually wrote something like
10191 * 'foo'::text::char(3).
10193 * Note: it might seem that we are missing the possibility of needing to
10194 * print a COLLATE clause for such a Const. However, a Const could only
10195 * have nondefault collation in a post-constant-folding tree, in which the
10196 * length coercion would have been folded too. See also the special
10197 * handling of CollateExpr in coerce_to_target_type(): any collation
10198 * marking will be above the coercion node, not below it.
10200 if (arg && IsA(arg, Const) &&
10201 ((Const *) arg)->consttype == resulttype &&
10202 ((Const *) arg)->consttypmod == -1)
10204 /* Show the constant without normal ::typename decoration */
10205 get_const_expr((Const *) arg, context, -1);
10207 else
10209 if (!PRETTY_PAREN(context))
10210 appendStringInfoChar(buf, '(');
10211 get_rule_expr_paren(arg, context, false, parentNode);
10212 if (!PRETTY_PAREN(context))
10213 appendStringInfoChar(buf, ')');
10217 * Never emit resulttype(arg) functional notation. A pg_proc entry could
10218 * take precedence, and a resulttype in pg_temp would require schema
10219 * qualification that format_type_with_typemod() would usually omit. We've
10220 * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
10221 * would work fine.
10223 appendStringInfo(buf, "::%s",
10224 format_type_with_typemod(resulttype, resulttypmod));
10227 /* ----------
10228 * get_const_expr
10230 * Make a string representation of a Const
10232 * showtype can be -1 to never show "::typename" decoration, or +1 to always
10233 * show it, or 0 to show it only if the constant wouldn't be assumed to be
10234 * the right type by default.
10236 * If the Const's collation isn't default for its type, show that too.
10237 * We mustn't do this when showtype is -1 (since that means the caller will
10238 * print "::typename", and we can't put a COLLATE clause in between). It's
10239 * caller's responsibility that collation isn't missed in such cases.
10240 * ----------
10242 static void
10243 get_const_expr(Const *constval, deparse_context *context, int showtype)
10245 StringInfo buf = context->buf;
10246 Oid typoutput;
10247 bool typIsVarlena;
10248 char *extval;
10249 bool needlabel = false;
10251 if (constval->constisnull)
10254 * Always label the type of a NULL constant to prevent misdecisions
10255 * about type when reparsing.
10257 appendStringInfoString(buf, "NULL");
10258 if (showtype >= 0)
10260 appendStringInfo(buf, "::%s",
10261 format_type_with_typemod(constval->consttype,
10262 constval->consttypmod));
10263 get_const_collation(constval, context);
10265 return;
10268 getTypeOutputInfo(constval->consttype,
10269 &typoutput, &typIsVarlena);
10271 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
10273 switch (constval->consttype)
10275 case INT4OID:
10278 * INT4 can be printed without any decoration, unless it is
10279 * negative; in that case print it as '-nnn'::integer to ensure
10280 * that the output will re-parse as a constant, not as a constant
10281 * plus operator. In most cases we could get away with printing
10282 * (-nnn) instead, because of the way that gram.y handles negative
10283 * literals; but that doesn't work for INT_MIN, and it doesn't
10284 * seem that much prettier anyway.
10286 if (extval[0] != '-')
10287 appendStringInfoString(buf, extval);
10288 else
10290 appendStringInfo(buf, "'%s'", extval);
10291 needlabel = true; /* we must attach a cast */
10293 break;
10295 case NUMERICOID:
10298 * NUMERIC can be printed without quotes if it looks like a float
10299 * constant (not an integer, and not Infinity or NaN) and doesn't
10300 * have a leading sign (for the same reason as for INT4).
10302 if (isdigit((unsigned char) extval[0]) &&
10303 strcspn(extval, "eE.") != strlen(extval))
10305 appendStringInfoString(buf, extval);
10307 else
10309 appendStringInfo(buf, "'%s'", extval);
10310 needlabel = true; /* we must attach a cast */
10312 break;
10314 case BOOLOID:
10315 if (strcmp(extval, "t") == 0)
10316 appendStringInfoString(buf, "true");
10317 else
10318 appendStringInfoString(buf, "false");
10319 break;
10321 default:
10322 simple_quote_literal(buf, extval);
10323 break;
10326 pfree(extval);
10328 if (showtype < 0)
10329 return;
10332 * For showtype == 0, append ::typename unless the constant will be
10333 * implicitly typed as the right type when it is read in.
10335 * XXX this code has to be kept in sync with the behavior of the parser,
10336 * especially make_const.
10338 switch (constval->consttype)
10340 case BOOLOID:
10341 case UNKNOWNOID:
10342 /* These types can be left unlabeled */
10343 needlabel = false;
10344 break;
10345 case INT4OID:
10346 /* We determined above whether a label is needed */
10347 break;
10348 case NUMERICOID:
10351 * Float-looking constants will be typed as numeric, which we
10352 * checked above; but if there's a nondefault typmod we need to
10353 * show it.
10355 needlabel |= (constval->consttypmod >= 0);
10356 break;
10357 default:
10358 needlabel = true;
10359 break;
10361 if (needlabel || showtype > 0)
10362 appendStringInfo(buf, "::%s",
10363 format_type_with_typemod(constval->consttype,
10364 constval->consttypmod));
10366 get_const_collation(constval, context);
10370 * helper for get_const_expr: append COLLATE if needed
10372 static void
10373 get_const_collation(Const *constval, deparse_context *context)
10375 StringInfo buf = context->buf;
10377 if (OidIsValid(constval->constcollid))
10379 Oid typcollation = get_typcollation(constval->consttype);
10381 if (constval->constcollid != typcollation)
10383 appendStringInfo(buf, " COLLATE %s",
10384 generate_collation_name(constval->constcollid));
10390 * simple_quote_literal - Format a string as a SQL literal, append to buf
10392 static void
10393 simple_quote_literal(StringInfo buf, const char *val)
10395 const char *valptr;
10398 * We form the string literal according to the prevailing setting of
10399 * standard_conforming_strings; we never use E''. User is responsible for
10400 * making sure result is used correctly.
10402 appendStringInfoChar(buf, '\'');
10403 for (valptr = val; *valptr; valptr++)
10405 char ch = *valptr;
10407 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
10408 appendStringInfoChar(buf, ch);
10409 appendStringInfoChar(buf, ch);
10411 appendStringInfoChar(buf, '\'');
10415 /* ----------
10416 * get_sublink_expr - Parse back a sublink
10417 * ----------
10419 static void
10420 get_sublink_expr(SubLink *sublink, deparse_context *context)
10422 StringInfo buf = context->buf;
10423 Query *query = (Query *) (sublink->subselect);
10424 char *opname = NULL;
10425 bool need_paren;
10427 if (sublink->subLinkType == ARRAY_SUBLINK)
10428 appendStringInfoString(buf, "ARRAY(");
10429 else
10430 appendStringInfoChar(buf, '(');
10433 * Note that we print the name of only the first operator, when there are
10434 * multiple combining operators. This is an approximation that could go
10435 * wrong in various scenarios (operators in different schemas, renamed
10436 * operators, etc) but there is not a whole lot we can do about it, since
10437 * the syntax allows only one operator to be shown.
10439 if (sublink->testexpr)
10441 if (IsA(sublink->testexpr, OpExpr))
10443 /* single combining operator */
10444 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
10446 get_rule_expr(linitial(opexpr->args), context, true);
10447 opname = generate_operator_name(opexpr->opno,
10448 exprType(linitial(opexpr->args)),
10449 exprType(lsecond(opexpr->args)));
10451 else if (IsA(sublink->testexpr, BoolExpr))
10453 /* multiple combining operators, = or <> cases */
10454 char *sep;
10455 ListCell *l;
10457 appendStringInfoChar(buf, '(');
10458 sep = "";
10459 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
10461 OpExpr *opexpr = lfirst_node(OpExpr, l);
10463 appendStringInfoString(buf, sep);
10464 get_rule_expr(linitial(opexpr->args), context, true);
10465 if (!opname)
10466 opname = generate_operator_name(opexpr->opno,
10467 exprType(linitial(opexpr->args)),
10468 exprType(lsecond(opexpr->args)));
10469 sep = ", ";
10471 appendStringInfoChar(buf, ')');
10473 else if (IsA(sublink->testexpr, RowCompareExpr))
10475 /* multiple combining operators, < <= > >= cases */
10476 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
10478 appendStringInfoChar(buf, '(');
10479 get_rule_expr((Node *) rcexpr->largs, context, true);
10480 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
10481 exprType(linitial(rcexpr->largs)),
10482 exprType(linitial(rcexpr->rargs)));
10483 appendStringInfoChar(buf, ')');
10485 else
10486 elog(ERROR, "unrecognized testexpr type: %d",
10487 (int) nodeTag(sublink->testexpr));
10490 need_paren = true;
10492 switch (sublink->subLinkType)
10494 case EXISTS_SUBLINK:
10495 appendStringInfoString(buf, "EXISTS ");
10496 break;
10498 case ANY_SUBLINK:
10499 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
10500 appendStringInfoString(buf, " IN ");
10501 else
10502 appendStringInfo(buf, " %s ANY ", opname);
10503 break;
10505 case ALL_SUBLINK:
10506 appendStringInfo(buf, " %s ALL ", opname);
10507 break;
10509 case ROWCOMPARE_SUBLINK:
10510 appendStringInfo(buf, " %s ", opname);
10511 break;
10513 case EXPR_SUBLINK:
10514 case MULTIEXPR_SUBLINK:
10515 case ARRAY_SUBLINK:
10516 need_paren = false;
10517 break;
10519 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
10520 default:
10521 elog(ERROR, "unrecognized sublink type: %d",
10522 (int) sublink->subLinkType);
10523 break;
10526 if (need_paren)
10527 appendStringInfoChar(buf, '(');
10529 get_query_def(query, buf, context->namespaces, NULL,
10530 context->prettyFlags, context->wrapColumn,
10531 context->indentLevel);
10533 if (need_paren)
10534 appendStringInfoString(buf, "))");
10535 else
10536 appendStringInfoChar(buf, ')');
10540 /* ----------
10541 * get_tablefunc - Parse back a table function
10542 * ----------
10544 static void
10545 get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
10547 StringInfo buf = context->buf;
10549 /* XMLTABLE is the only existing implementation. */
10551 appendStringInfoString(buf, "XMLTABLE(");
10553 if (tf->ns_uris != NIL)
10555 ListCell *lc1,
10556 *lc2;
10557 bool first = true;
10559 appendStringInfoString(buf, "XMLNAMESPACES (");
10560 forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
10562 Node *expr = (Node *) lfirst(lc1);
10563 String *ns_node = lfirst_node(String, lc2);
10565 if (!first)
10566 appendStringInfoString(buf, ", ");
10567 else
10568 first = false;
10570 if (ns_node != NULL)
10572 get_rule_expr(expr, context, showimplicit);
10573 appendStringInfo(buf, " AS %s", strVal(ns_node));
10575 else
10577 appendStringInfoString(buf, "DEFAULT ");
10578 get_rule_expr(expr, context, showimplicit);
10581 appendStringInfoString(buf, "), ");
10584 appendStringInfoChar(buf, '(');
10585 get_rule_expr((Node *) tf->rowexpr, context, showimplicit);
10586 appendStringInfoString(buf, ") PASSING (");
10587 get_rule_expr((Node *) tf->docexpr, context, showimplicit);
10588 appendStringInfoChar(buf, ')');
10590 if (tf->colexprs != NIL)
10592 ListCell *l1;
10593 ListCell *l2;
10594 ListCell *l3;
10595 ListCell *l4;
10596 ListCell *l5;
10597 int colnum = 0;
10599 appendStringInfoString(buf, " COLUMNS ");
10600 forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods,
10601 l4, tf->colexprs, l5, tf->coldefexprs)
10603 char *colname = strVal(lfirst(l1));
10604 Oid typid = lfirst_oid(l2);
10605 int32 typmod = lfirst_int(l3);
10606 Node *colexpr = (Node *) lfirst(l4);
10607 Node *coldefexpr = (Node *) lfirst(l5);
10608 bool ordinality = (tf->ordinalitycol == colnum);
10609 bool notnull = bms_is_member(colnum, tf->notnulls);
10611 if (colnum > 0)
10612 appendStringInfoString(buf, ", ");
10613 colnum++;
10615 appendStringInfo(buf, "%s %s", quote_identifier(colname),
10616 ordinality ? "FOR ORDINALITY" :
10617 format_type_with_typemod(typid, typmod));
10618 if (ordinality)
10619 continue;
10621 if (coldefexpr != NULL)
10623 appendStringInfoString(buf, " DEFAULT (");
10624 get_rule_expr((Node *) coldefexpr, context, showimplicit);
10625 appendStringInfoChar(buf, ')');
10627 if (colexpr != NULL)
10629 appendStringInfoString(buf, " PATH (");
10630 get_rule_expr((Node *) colexpr, context, showimplicit);
10631 appendStringInfoChar(buf, ')');
10633 if (notnull)
10634 appendStringInfoString(buf, " NOT NULL");
10638 appendStringInfoChar(buf, ')');
10641 /* ----------
10642 * get_from_clause - Parse back a FROM clause
10644 * "prefix" is the keyword that denotes the start of the list of FROM
10645 * elements. It is FROM when used to parse back SELECT and UPDATE, but
10646 * is USING when parsing back DELETE.
10647 * ----------
10649 static void
10650 get_from_clause(Query *query, const char *prefix, deparse_context *context)
10652 StringInfo buf = context->buf;
10653 bool first = true;
10654 ListCell *l;
10657 * We use the query's jointree as a guide to what to print. However, we
10658 * must ignore auto-added RTEs that are marked not inFromCl. (These can
10659 * only appear at the top level of the jointree, so it's sufficient to
10660 * check here.) This check also ensures we ignore the rule pseudo-RTEs
10661 * for NEW and OLD.
10663 foreach(l, query->jointree->fromlist)
10665 Node *jtnode = (Node *) lfirst(l);
10667 if (IsA(jtnode, RangeTblRef))
10669 int varno = ((RangeTblRef *) jtnode)->rtindex;
10670 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10672 if (!rte->inFromCl)
10673 continue;
10676 if (first)
10678 appendContextKeyword(context, prefix,
10679 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
10680 first = false;
10682 get_from_clause_item(jtnode, query, context);
10684 else
10686 StringInfoData itembuf;
10688 appendStringInfoString(buf, ", ");
10691 * Put the new FROM item's text into itembuf so we can decide
10692 * after we've got it whether or not it needs to go on a new line.
10694 initStringInfo(&itembuf);
10695 context->buf = &itembuf;
10697 get_from_clause_item(jtnode, query, context);
10699 /* Restore context's output buffer */
10700 context->buf = buf;
10702 /* Consider line-wrapping if enabled */
10703 if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10705 /* Does the new item start with a new line? */
10706 if (itembuf.len > 0 && itembuf.data[0] == '\n')
10708 /* If so, we shouldn't add anything */
10709 /* instead, remove any trailing spaces currently in buf */
10710 removeStringInfoSpaces(buf);
10712 else
10714 char *trailing_nl;
10716 /* Locate the start of the current line in the buffer */
10717 trailing_nl = strrchr(buf->data, '\n');
10718 if (trailing_nl == NULL)
10719 trailing_nl = buf->data;
10720 else
10721 trailing_nl++;
10724 * Add a newline, plus some indentation, if the new item
10725 * would cause an overflow.
10727 if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10728 appendContextKeyword(context, "", -PRETTYINDENT_STD,
10729 PRETTYINDENT_STD,
10730 PRETTYINDENT_VAR);
10734 /* Add the new item */
10735 appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10737 /* clean up */
10738 pfree(itembuf.data);
10743 static void
10744 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
10746 StringInfo buf = context->buf;
10747 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
10749 if (IsA(jtnode, RangeTblRef))
10751 int varno = ((RangeTblRef *) jtnode)->rtindex;
10752 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10753 char *refname = get_rtable_name(varno, context);
10754 deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10755 RangeTblFunction *rtfunc1 = NULL;
10756 bool printalias;
10758 if (rte->lateral)
10759 appendStringInfoString(buf, "LATERAL ");
10761 /* Print the FROM item proper */
10762 switch (rte->rtekind)
10764 case RTE_RELATION:
10765 /* Normal relation RTE */
10766 appendStringInfo(buf, "%s%s",
10767 only_marker(rte),
10768 generate_relation_name(rte->relid,
10769 context->namespaces));
10770 break;
10771 case RTE_SUBQUERY:
10772 /* Subquery RTE */
10773 appendStringInfoChar(buf, '(');
10774 get_query_def(rte->subquery, buf, context->namespaces, NULL,
10775 context->prettyFlags, context->wrapColumn,
10776 context->indentLevel);
10777 appendStringInfoChar(buf, ')');
10778 break;
10779 case RTE_FUNCTION:
10780 /* Function RTE */
10781 rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10784 * Omit ROWS FROM() syntax for just one function, unless it
10785 * has both a coldeflist and WITH ORDINALITY. If it has both,
10786 * we must use ROWS FROM() syntax to avoid ambiguity about
10787 * whether the coldeflist includes the ordinality column.
10789 if (list_length(rte->functions) == 1 &&
10790 (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10792 get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10793 /* we'll print the coldeflist below, if it has one */
10795 else
10797 bool all_unnest;
10798 ListCell *lc;
10801 * If all the function calls in the list are to unnest,
10802 * and none need a coldeflist, then collapse the list back
10803 * down to UNNEST(args). (If we had more than one
10804 * built-in unnest function, this would get more
10805 * difficult.)
10807 * XXX This is pretty ugly, since it makes not-terribly-
10808 * future-proof assumptions about what the parser would do
10809 * with the output; but the alternative is to emit our
10810 * nonstandard ROWS FROM() notation for what might have
10811 * been a perfectly spec-compliant multi-argument
10812 * UNNEST().
10814 all_unnest = true;
10815 foreach(lc, rte->functions)
10817 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10819 if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10820 ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
10821 rtfunc->funccolnames != NIL)
10823 all_unnest = false;
10824 break;
10828 if (all_unnest)
10830 List *allargs = NIL;
10832 foreach(lc, rte->functions)
10834 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10835 List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10837 allargs = list_concat(allargs, args);
10840 appendStringInfoString(buf, "UNNEST(");
10841 get_rule_expr((Node *) allargs, context, true);
10842 appendStringInfoChar(buf, ')');
10844 else
10846 int funcno = 0;
10848 appendStringInfoString(buf, "ROWS FROM(");
10849 foreach(lc, rte->functions)
10851 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10853 if (funcno > 0)
10854 appendStringInfoString(buf, ", ");
10855 get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10856 if (rtfunc->funccolnames != NIL)
10858 /* Reconstruct the column definition list */
10859 appendStringInfoString(buf, " AS ");
10860 get_from_clause_coldeflist(rtfunc,
10861 NULL,
10862 context);
10864 funcno++;
10866 appendStringInfoChar(buf, ')');
10868 /* prevent printing duplicate coldeflist below */
10869 rtfunc1 = NULL;
10871 if (rte->funcordinality)
10872 appendStringInfoString(buf, " WITH ORDINALITY");
10873 break;
10874 case RTE_TABLEFUNC:
10875 get_tablefunc(rte->tablefunc, context, true);
10876 break;
10877 case RTE_VALUES:
10878 /* Values list RTE */
10879 appendStringInfoChar(buf, '(');
10880 get_values_def(rte->values_lists, context);
10881 appendStringInfoChar(buf, ')');
10882 break;
10883 case RTE_CTE:
10884 appendStringInfoString(buf, quote_identifier(rte->ctename));
10885 break;
10886 default:
10887 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10888 break;
10891 /* Print the relation alias, if needed */
10892 printalias = false;
10893 if (rte->alias != NULL)
10895 /* Always print alias if user provided one */
10896 printalias = true;
10898 else if (colinfo->printaliases)
10900 /* Always print alias if we need to print column aliases */
10901 printalias = true;
10903 else if (rte->rtekind == RTE_RELATION)
10906 * No need to print alias if it's same as relation name (this
10907 * would normally be the case, but not if set_rtable_names had to
10908 * resolve a conflict).
10910 if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10911 printalias = true;
10913 else if (rte->rtekind == RTE_FUNCTION)
10916 * For a function RTE, always print alias. This covers possible
10917 * renaming of the function and/or instability of the
10918 * FigureColname rules for things that aren't simple functions.
10919 * Note we'd need to force it anyway for the columndef list case.
10921 printalias = true;
10923 else if (rte->rtekind == RTE_VALUES)
10925 /* Alias is syntactically required for VALUES */
10926 printalias = true;
10928 else if (rte->rtekind == RTE_CTE)
10931 * No need to print alias if it's same as CTE name (this would
10932 * normally be the case, but not if set_rtable_names had to
10933 * resolve a conflict).
10935 if (strcmp(refname, rte->ctename) != 0)
10936 printalias = true;
10938 if (printalias)
10939 appendStringInfo(buf, " %s", quote_identifier(refname));
10941 /* Print the column definitions or aliases, if needed */
10942 if (rtfunc1 && rtfunc1->funccolnames != NIL)
10944 /* Reconstruct the columndef list, which is also the aliases */
10945 get_from_clause_coldeflist(rtfunc1, colinfo, context);
10947 else
10949 /* Else print column aliases as needed */
10950 get_column_alias_list(colinfo, context);
10953 /* Tablesample clause must go after any alias */
10954 if (rte->rtekind == RTE_RELATION && rte->tablesample)
10955 get_tablesample_def(rte->tablesample, context);
10957 else if (IsA(jtnode, JoinExpr))
10959 JoinExpr *j = (JoinExpr *) jtnode;
10960 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10961 bool need_paren_on_right;
10963 need_paren_on_right = PRETTY_PAREN(context) &&
10964 !IsA(j->rarg, RangeTblRef) &&
10965 !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
10967 if (!PRETTY_PAREN(context) || j->alias != NULL)
10968 appendStringInfoChar(buf, '(');
10970 get_from_clause_item(j->larg, query, context);
10972 switch (j->jointype)
10974 case JOIN_INNER:
10975 if (j->quals)
10976 appendContextKeyword(context, " JOIN ",
10977 -PRETTYINDENT_STD,
10978 PRETTYINDENT_STD,
10979 PRETTYINDENT_JOIN);
10980 else
10981 appendContextKeyword(context, " CROSS JOIN ",
10982 -PRETTYINDENT_STD,
10983 PRETTYINDENT_STD,
10984 PRETTYINDENT_JOIN);
10985 break;
10986 case JOIN_LEFT:
10987 appendContextKeyword(context, " LEFT JOIN ",
10988 -PRETTYINDENT_STD,
10989 PRETTYINDENT_STD,
10990 PRETTYINDENT_JOIN);
10991 break;
10992 case JOIN_FULL:
10993 appendContextKeyword(context, " FULL JOIN ",
10994 -PRETTYINDENT_STD,
10995 PRETTYINDENT_STD,
10996 PRETTYINDENT_JOIN);
10997 break;
10998 case JOIN_RIGHT:
10999 appendContextKeyword(context, " RIGHT JOIN ",
11000 -PRETTYINDENT_STD,
11001 PRETTYINDENT_STD,
11002 PRETTYINDENT_JOIN);
11003 break;
11004 default:
11005 elog(ERROR, "unrecognized join type: %d",
11006 (int) j->jointype);
11009 if (need_paren_on_right)
11010 appendStringInfoChar(buf, '(');
11011 get_from_clause_item(j->rarg, query, context);
11012 if (need_paren_on_right)
11013 appendStringInfoChar(buf, ')');
11015 if (j->usingClause)
11017 ListCell *lc;
11018 bool first = true;
11020 appendStringInfoString(buf, " USING (");
11021 /* Use the assigned names, not what's in usingClause */
11022 foreach(lc, colinfo->usingNames)
11024 char *colname = (char *) lfirst(lc);
11026 if (first)
11027 first = false;
11028 else
11029 appendStringInfoString(buf, ", ");
11030 appendStringInfoString(buf, quote_identifier(colname));
11032 appendStringInfoChar(buf, ')');
11034 if (j->join_using_alias)
11035 appendStringInfo(buf, " AS %s",
11036 quote_identifier(j->join_using_alias->aliasname));
11038 else if (j->quals)
11040 appendStringInfoString(buf, " ON ");
11041 if (!PRETTY_PAREN(context))
11042 appendStringInfoChar(buf, '(');
11043 get_rule_expr(j->quals, context, false);
11044 if (!PRETTY_PAREN(context))
11045 appendStringInfoChar(buf, ')');
11047 else if (j->jointype != JOIN_INNER)
11049 /* If we didn't say CROSS JOIN above, we must provide an ON */
11050 appendStringInfoString(buf, " ON TRUE");
11053 if (!PRETTY_PAREN(context) || j->alias != NULL)
11054 appendStringInfoChar(buf, ')');
11056 /* Yes, it's correct to put alias after the right paren ... */
11057 if (j->alias != NULL)
11060 * Note that it's correct to emit an alias clause if and only if
11061 * there was one originally. Otherwise we'd be converting a named
11062 * join to unnamed or vice versa, which creates semantic
11063 * subtleties we don't want. However, we might print a different
11064 * alias name than was there originally.
11066 appendStringInfo(buf, " %s",
11067 quote_identifier(get_rtable_name(j->rtindex,
11068 context)));
11069 get_column_alias_list(colinfo, context);
11072 else
11073 elog(ERROR, "unrecognized node type: %d",
11074 (int) nodeTag(jtnode));
11078 * get_column_alias_list - print column alias list for an RTE
11080 * Caller must already have printed the relation's alias name.
11082 static void
11083 get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
11085 StringInfo buf = context->buf;
11086 int i;
11087 bool first = true;
11089 /* Don't print aliases if not needed */
11090 if (!colinfo->printaliases)
11091 return;
11093 for (i = 0; i < colinfo->num_new_cols; i++)
11095 char *colname = colinfo->new_colnames[i];
11097 if (first)
11099 appendStringInfoChar(buf, '(');
11100 first = false;
11102 else
11103 appendStringInfoString(buf, ", ");
11104 appendStringInfoString(buf, quote_identifier(colname));
11106 if (!first)
11107 appendStringInfoChar(buf, ')');
11111 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
11113 * When printing a top-level coldeflist (which is syntactically also the
11114 * relation's column alias list), use column names from colinfo. But when
11115 * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
11116 * original coldeflist's names, which are available in rtfunc->funccolnames.
11117 * Pass NULL for colinfo to select the latter behavior.
11119 * The coldeflist is appended immediately (no space) to buf. Caller is
11120 * responsible for ensuring that an alias or AS is present before it.
11122 static void
11123 get_from_clause_coldeflist(RangeTblFunction *rtfunc,
11124 deparse_columns *colinfo,
11125 deparse_context *context)
11127 StringInfo buf = context->buf;
11128 ListCell *l1;
11129 ListCell *l2;
11130 ListCell *l3;
11131 ListCell *l4;
11132 int i;
11134 appendStringInfoChar(buf, '(');
11136 i = 0;
11137 forfour(l1, rtfunc->funccoltypes,
11138 l2, rtfunc->funccoltypmods,
11139 l3, rtfunc->funccolcollations,
11140 l4, rtfunc->funccolnames)
11142 Oid atttypid = lfirst_oid(l1);
11143 int32 atttypmod = lfirst_int(l2);
11144 Oid attcollation = lfirst_oid(l3);
11145 char *attname;
11147 if (colinfo)
11148 attname = colinfo->colnames[i];
11149 else
11150 attname = strVal(lfirst(l4));
11152 Assert(attname); /* shouldn't be any dropped columns here */
11154 if (i > 0)
11155 appendStringInfoString(buf, ", ");
11156 appendStringInfo(buf, "%s %s",
11157 quote_identifier(attname),
11158 format_type_with_typemod(atttypid, atttypmod));
11159 if (OidIsValid(attcollation) &&
11160 attcollation != get_typcollation(atttypid))
11161 appendStringInfo(buf, " COLLATE %s",
11162 generate_collation_name(attcollation));
11164 i++;
11167 appendStringInfoChar(buf, ')');
11171 * get_tablesample_def - print a TableSampleClause
11173 static void
11174 get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
11176 StringInfo buf = context->buf;
11177 Oid argtypes[1];
11178 int nargs;
11179 ListCell *l;
11182 * We should qualify the handler's function name if it wouldn't be
11183 * resolved by lookup in the current search path.
11185 argtypes[0] = INTERNALOID;
11186 appendStringInfo(buf, " TABLESAMPLE %s (",
11187 generate_function_name(tablesample->tsmhandler, 1,
11188 NIL, argtypes,
11189 false, NULL, EXPR_KIND_NONE));
11191 nargs = 0;
11192 foreach(l, tablesample->args)
11194 if (nargs++ > 0)
11195 appendStringInfoString(buf, ", ");
11196 get_rule_expr((Node *) lfirst(l), context, false);
11198 appendStringInfoChar(buf, ')');
11200 if (tablesample->repeatable != NULL)
11202 appendStringInfoString(buf, " REPEATABLE (");
11203 get_rule_expr((Node *) tablesample->repeatable, context, false);
11204 appendStringInfoChar(buf, ')');
11209 * get_opclass_name - fetch name of an index operator class
11211 * The opclass name is appended (after a space) to buf.
11213 * Output is suppressed if the opclass is the default for the given
11214 * actual_datatype. (If you don't want this behavior, just pass
11215 * InvalidOid for actual_datatype.)
11217 static void
11218 get_opclass_name(Oid opclass, Oid actual_datatype,
11219 StringInfo buf)
11221 HeapTuple ht_opc;
11222 Form_pg_opclass opcrec;
11223 char *opcname;
11224 char *nspname;
11226 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
11227 if (!HeapTupleIsValid(ht_opc))
11228 elog(ERROR, "cache lookup failed for opclass %u", opclass);
11229 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
11231 if (!OidIsValid(actual_datatype) ||
11232 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
11234 /* Okay, we need the opclass name. Do we need to qualify it? */
11235 opcname = NameStr(opcrec->opcname);
11236 if (OpclassIsVisible(opclass))
11237 appendStringInfo(buf, " %s", quote_identifier(opcname));
11238 else
11240 nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
11241 appendStringInfo(buf, " %s.%s",
11242 quote_identifier(nspname),
11243 quote_identifier(opcname));
11246 ReleaseSysCache(ht_opc);
11250 * generate_opclass_name
11251 * Compute the name to display for a opclass specified by OID
11253 * The result includes all necessary quoting and schema-prefixing.
11255 char *
11256 generate_opclass_name(Oid opclass)
11258 StringInfoData buf;
11260 initStringInfo(&buf);
11261 get_opclass_name(opclass, InvalidOid, &buf);
11263 return &buf.data[1]; /* get_opclass_name() prepends space */
11267 * processIndirection - take care of array and subfield assignment
11269 * We strip any top-level FieldStore or assignment SubscriptingRef nodes that
11270 * appear in the input, printing them as decoration for the base column
11271 * name (which we assume the caller just printed). We might also need to
11272 * strip CoerceToDomain nodes, but only ones that appear above assignment
11273 * nodes.
11275 * Returns the subexpression that's to be assigned.
11277 static Node *
11278 processIndirection(Node *node, deparse_context *context)
11280 StringInfo buf = context->buf;
11281 CoerceToDomain *cdomain = NULL;
11283 for (;;)
11285 if (node == NULL)
11286 break;
11287 if (IsA(node, FieldStore))
11289 FieldStore *fstore = (FieldStore *) node;
11290 Oid typrelid;
11291 char *fieldname;
11293 /* lookup tuple type */
11294 typrelid = get_typ_typrelid(fstore->resulttype);
11295 if (!OidIsValid(typrelid))
11296 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
11297 format_type_be(fstore->resulttype));
11300 * Print the field name. There should only be one target field in
11301 * stored rules. There could be more than that in executable
11302 * target lists, but this function cannot be used for that case.
11304 Assert(list_length(fstore->fieldnums) == 1);
11305 fieldname = get_attname(typrelid,
11306 linitial_int(fstore->fieldnums), false);
11307 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
11310 * We ignore arg since it should be an uninteresting reference to
11311 * the target column or subcolumn.
11313 node = (Node *) linitial(fstore->newvals);
11315 else if (IsA(node, SubscriptingRef))
11317 SubscriptingRef *sbsref = (SubscriptingRef *) node;
11319 if (sbsref->refassgnexpr == NULL)
11320 break;
11322 printSubscripts(sbsref, context);
11325 * We ignore refexpr since it should be an uninteresting reference
11326 * to the target column or subcolumn.
11328 node = (Node *) sbsref->refassgnexpr;
11330 else if (IsA(node, CoerceToDomain))
11332 cdomain = (CoerceToDomain *) node;
11333 /* If it's an explicit domain coercion, we're done */
11334 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
11335 break;
11336 /* Tentatively descend past the CoerceToDomain */
11337 node = (Node *) cdomain->arg;
11339 else
11340 break;
11344 * If we descended past a CoerceToDomain whose argument turned out not to
11345 * be a FieldStore or array assignment, back up to the CoerceToDomain.
11346 * (This is not enough to be fully correct if there are nested implicit
11347 * CoerceToDomains, but such cases shouldn't ever occur.)
11349 if (cdomain && node == (Node *) cdomain->arg)
11350 node = (Node *) cdomain;
11352 return node;
11355 static void
11356 printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
11358 StringInfo buf = context->buf;
11359 ListCell *lowlist_item;
11360 ListCell *uplist_item;
11362 lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */
11363 foreach(uplist_item, sbsref->refupperindexpr)
11365 appendStringInfoChar(buf, '[');
11366 if (lowlist_item)
11368 /* If subexpression is NULL, get_rule_expr prints nothing */
11369 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
11370 appendStringInfoChar(buf, ':');
11371 lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
11373 /* If subexpression is NULL, get_rule_expr prints nothing */
11374 get_rule_expr((Node *) lfirst(uplist_item), context, false);
11375 appendStringInfoChar(buf, ']');
11380 * quote_identifier - Quote an identifier only if needed
11382 * When quotes are needed, we palloc the required space; slightly
11383 * space-wasteful but well worth it for notational simplicity.
11385 const char *
11386 quote_identifier(const char *ident)
11389 * Can avoid quoting if ident starts with a lowercase letter or underscore
11390 * and contains only lowercase letters, digits, and underscores, *and* is
11391 * not any SQL keyword. Otherwise, supply quotes.
11393 int nquotes = 0;
11394 bool safe;
11395 const char *ptr;
11396 char *result;
11397 char *optr;
11400 * would like to use <ctype.h> macros here, but they might yield unwanted
11401 * locale-specific results...
11403 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
11405 for (ptr = ident; *ptr; ptr++)
11407 char ch = *ptr;
11409 if ((ch >= 'a' && ch <= 'z') ||
11410 (ch >= '0' && ch <= '9') ||
11411 (ch == '_'))
11413 /* okay */
11415 else
11417 safe = false;
11418 if (ch == '"')
11419 nquotes++;
11423 if (quote_all_identifiers)
11424 safe = false;
11426 if (safe)
11429 * Check for keyword. We quote keywords except for unreserved ones.
11430 * (In some cases we could avoid quoting a col_name or type_func_name
11431 * keyword, but it seems much harder than it's worth to tell that.)
11433 * Note: ScanKeywordLookup() does case-insensitive comparison, but
11434 * that's fine, since we already know we have all-lower-case.
11436 int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
11438 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
11439 safe = false;
11442 if (safe)
11443 return ident; /* no change needed */
11445 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
11447 optr = result;
11448 *optr++ = '"';
11449 for (ptr = ident; *ptr; ptr++)
11451 char ch = *ptr;
11453 if (ch == '"')
11454 *optr++ = '"';
11455 *optr++ = ch;
11457 *optr++ = '"';
11458 *optr = '\0';
11460 return result;
11464 * quote_qualified_identifier - Quote a possibly-qualified identifier
11466 * Return a name of the form qualifier.ident, or just ident if qualifier
11467 * is NULL, quoting each component if necessary. The result is palloc'd.
11469 char *
11470 quote_qualified_identifier(const char *qualifier,
11471 const char *ident)
11473 StringInfoData buf;
11475 initStringInfo(&buf);
11476 if (qualifier)
11477 appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
11478 appendStringInfoString(&buf, quote_identifier(ident));
11479 return buf.data;
11483 * get_relation_name
11484 * Get the unqualified name of a relation specified by OID
11486 * This differs from the underlying get_rel_name() function in that it will
11487 * throw error instead of silently returning NULL if the OID is bad.
11489 static char *
11490 get_relation_name(Oid relid)
11492 char *relname = get_rel_name(relid);
11494 if (!relname)
11495 elog(ERROR, "cache lookup failed for relation %u", relid);
11496 return relname;
11500 * generate_relation_name
11501 * Compute the name to display for a relation specified by OID
11503 * The result includes all necessary quoting and schema-prefixing.
11505 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
11506 * We will forcibly qualify the relation name if it equals any CTE name
11507 * visible in the namespace list.
11509 static char *
11510 generate_relation_name(Oid relid, List *namespaces)
11512 HeapTuple tp;
11513 Form_pg_class reltup;
11514 bool need_qual;
11515 ListCell *nslist;
11516 char *relname;
11517 char *nspname;
11518 char *result;
11520 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11521 if (!HeapTupleIsValid(tp))
11522 elog(ERROR, "cache lookup failed for relation %u", relid);
11523 reltup = (Form_pg_class) GETSTRUCT(tp);
11524 relname = NameStr(reltup->relname);
11526 /* Check for conflicting CTE name */
11527 need_qual = false;
11528 foreach(nslist, namespaces)
11530 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
11531 ListCell *ctlist;
11533 foreach(ctlist, dpns->ctes)
11535 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
11537 if (strcmp(cte->ctename, relname) == 0)
11539 need_qual = true;
11540 break;
11543 if (need_qual)
11544 break;
11547 /* Otherwise, qualify the name if not visible in search path */
11548 if (!need_qual)
11549 need_qual = !RelationIsVisible(relid);
11551 if (need_qual)
11552 nspname = get_namespace_name_or_temp(reltup->relnamespace);
11553 else
11554 nspname = NULL;
11556 result = quote_qualified_identifier(nspname, relname);
11558 ReleaseSysCache(tp);
11560 return result;
11564 * generate_qualified_relation_name
11565 * Compute the name to display for a relation specified by OID
11567 * As above, but unconditionally schema-qualify the name.
11569 static char *
11570 generate_qualified_relation_name(Oid relid)
11572 HeapTuple tp;
11573 Form_pg_class reltup;
11574 char *relname;
11575 char *nspname;
11576 char *result;
11578 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11579 if (!HeapTupleIsValid(tp))
11580 elog(ERROR, "cache lookup failed for relation %u", relid);
11581 reltup = (Form_pg_class) GETSTRUCT(tp);
11582 relname = NameStr(reltup->relname);
11584 nspname = get_namespace_name_or_temp(reltup->relnamespace);
11585 if (!nspname)
11586 elog(ERROR, "cache lookup failed for namespace %u",
11587 reltup->relnamespace);
11589 result = quote_qualified_identifier(nspname, relname);
11591 ReleaseSysCache(tp);
11593 return result;
11597 * generate_function_name
11598 * Compute the name to display for a function specified by OID,
11599 * given that it is being called with the specified actual arg names and
11600 * types. (Those matter because of ambiguous-function resolution rules.)
11602 * If we're dealing with a potentially variadic function (in practice, this
11603 * means a FuncExpr or Aggref, not some other way of calling a function), then
11604 * has_variadic must specify whether variadic arguments have been merged,
11605 * and *use_variadic_p will be set to indicate whether to print VARIADIC in
11606 * the output. For non-FuncExpr cases, has_variadic should be false and
11607 * use_variadic_p can be NULL.
11609 * The result includes all necessary quoting and schema-prefixing.
11611 static char *
11612 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
11613 bool has_variadic, bool *use_variadic_p,
11614 ParseExprKind special_exprkind)
11616 char *result;
11617 HeapTuple proctup;
11618 Form_pg_proc procform;
11619 char *proname;
11620 bool use_variadic;
11621 char *nspname;
11622 FuncDetailCode p_result;
11623 Oid p_funcid;
11624 Oid p_rettype;
11625 bool p_retset;
11626 int p_nvargs;
11627 Oid p_vatype;
11628 Oid *p_true_typeids;
11629 bool force_qualify = false;
11631 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
11632 if (!HeapTupleIsValid(proctup))
11633 elog(ERROR, "cache lookup failed for function %u", funcid);
11634 procform = (Form_pg_proc) GETSTRUCT(proctup);
11635 proname = NameStr(procform->proname);
11638 * Due to parser hacks to avoid needing to reserve CUBE, we need to force
11639 * qualification in some special cases.
11641 if (special_exprkind == EXPR_KIND_GROUP_BY)
11643 if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
11644 force_qualify = true;
11648 * Determine whether VARIADIC should be printed. We must do this first
11649 * since it affects the lookup rules in func_get_detail().
11651 * We always print VARIADIC if the function has a merged variadic-array
11652 * argument. Note that this is always the case for functions taking a
11653 * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
11654 * and printed the array elements as separate arguments, the call could
11655 * match a newer non-VARIADIC function.
11657 if (use_variadic_p)
11659 /* Parser should not have set funcvariadic unless fn is variadic */
11660 Assert(!has_variadic || OidIsValid(procform->provariadic));
11661 use_variadic = has_variadic;
11662 *use_variadic_p = use_variadic;
11664 else
11666 Assert(!has_variadic);
11667 use_variadic = false;
11671 * The idea here is to schema-qualify only if the parser would fail to
11672 * resolve the correct function given the unqualified func name with the
11673 * specified argtypes and VARIADIC flag. But if we already decided to
11674 * force qualification, then we can skip the lookup and pretend we didn't
11675 * find it.
11677 if (!force_qualify)
11678 p_result = func_get_detail(list_make1(makeString(proname)),
11679 NIL, argnames, nargs, argtypes,
11680 !use_variadic, true, false,
11681 &p_funcid, &p_rettype,
11682 &p_retset, &p_nvargs, &p_vatype,
11683 &p_true_typeids, NULL);
11684 else
11686 p_result = FUNCDETAIL_NOTFOUND;
11687 p_funcid = InvalidOid;
11690 if ((p_result == FUNCDETAIL_NORMAL ||
11691 p_result == FUNCDETAIL_AGGREGATE ||
11692 p_result == FUNCDETAIL_WINDOWFUNC) &&
11693 p_funcid == funcid)
11694 nspname = NULL;
11695 else
11696 nspname = get_namespace_name_or_temp(procform->pronamespace);
11698 result = quote_qualified_identifier(nspname, proname);
11700 ReleaseSysCache(proctup);
11702 return result;
11706 * generate_operator_name
11707 * Compute the name to display for an operator specified by OID,
11708 * given that it is being called with the specified actual arg types.
11709 * (Arg types matter because of ambiguous-operator resolution rules.
11710 * Pass InvalidOid for unused arg of a unary operator.)
11712 * The result includes all necessary quoting and schema-prefixing,
11713 * plus the OPERATOR() decoration needed to use a qualified operator name
11714 * in an expression.
11716 static char *
11717 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
11719 StringInfoData buf;
11720 HeapTuple opertup;
11721 Form_pg_operator operform;
11722 char *oprname;
11723 char *nspname;
11724 Operator p_result;
11726 initStringInfo(&buf);
11728 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11729 if (!HeapTupleIsValid(opertup))
11730 elog(ERROR, "cache lookup failed for operator %u", operid);
11731 operform = (Form_pg_operator) GETSTRUCT(opertup);
11732 oprname = NameStr(operform->oprname);
11735 * The idea here is to schema-qualify only if the parser would fail to
11736 * resolve the correct operator given the unqualified op name with the
11737 * specified argtypes.
11739 switch (operform->oprkind)
11741 case 'b':
11742 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11743 true, -1);
11744 break;
11745 case 'l':
11746 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11747 true, -1);
11748 break;
11749 default:
11750 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11751 p_result = NULL; /* keep compiler quiet */
11752 break;
11755 if (p_result != NULL && oprid(p_result) == operid)
11756 nspname = NULL;
11757 else
11759 nspname = get_namespace_name_or_temp(operform->oprnamespace);
11760 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11763 appendStringInfoString(&buf, oprname);
11765 if (nspname)
11766 appendStringInfoChar(&buf, ')');
11768 if (p_result != NULL)
11769 ReleaseSysCache(p_result);
11771 ReleaseSysCache(opertup);
11773 return buf.data;
11777 * generate_operator_clause --- generate a binary-operator WHERE clause
11779 * This is used for internally-generated-and-executed SQL queries, where
11780 * precision is essential and readability is secondary. The basic
11781 * requirement is to append "leftop op rightop" to buf, where leftop and
11782 * rightop are given as strings and are assumed to yield types leftoptype
11783 * and rightoptype; the operator is identified by OID. The complexity
11784 * comes from needing to be sure that the parser will select the desired
11785 * operator when the query is parsed. We always name the operator using
11786 * OPERATOR(schema.op) syntax, so as to avoid search-path uncertainties.
11787 * We have to emit casts too, if either input isn't already the input type
11788 * of the operator; else we are at the mercy of the parser's heuristics for
11789 * ambiguous-operator resolution. The caller must ensure that leftop and
11790 * rightop are suitable arguments for a cast operation; it's best to insert
11791 * parentheses if they aren't just variables or parameters.
11793 void
11794 generate_operator_clause(StringInfo buf,
11795 const char *leftop, Oid leftoptype,
11796 Oid opoid,
11797 const char *rightop, Oid rightoptype)
11799 HeapTuple opertup;
11800 Form_pg_operator operform;
11801 char *oprname;
11802 char *nspname;
11804 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11805 if (!HeapTupleIsValid(opertup))
11806 elog(ERROR, "cache lookup failed for operator %u", opoid);
11807 operform = (Form_pg_operator) GETSTRUCT(opertup);
11808 Assert(operform->oprkind == 'b');
11809 oprname = NameStr(operform->oprname);
11811 nspname = get_namespace_name(operform->oprnamespace);
11813 appendStringInfoString(buf, leftop);
11814 if (leftoptype != operform->oprleft)
11815 add_cast_to(buf, operform->oprleft);
11816 appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11817 appendStringInfoString(buf, oprname);
11818 appendStringInfo(buf, ") %s", rightop);
11819 if (rightoptype != operform->oprright)
11820 add_cast_to(buf, operform->oprright);
11822 ReleaseSysCache(opertup);
11826 * Add a cast specification to buf. We spell out the type name the hard way,
11827 * intentionally not using format_type_be(). This is to avoid corner cases
11828 * for CHARACTER, BIT, and perhaps other types, where specifying the type
11829 * using SQL-standard syntax results in undesirable data truncation. By
11830 * doing it this way we can be certain that the cast will have default (-1)
11831 * target typmod.
11833 static void
11834 add_cast_to(StringInfo buf, Oid typid)
11836 HeapTuple typetup;
11837 Form_pg_type typform;
11838 char *typname;
11839 char *nspname;
11841 typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11842 if (!HeapTupleIsValid(typetup))
11843 elog(ERROR, "cache lookup failed for type %u", typid);
11844 typform = (Form_pg_type) GETSTRUCT(typetup);
11846 typname = NameStr(typform->typname);
11847 nspname = get_namespace_name_or_temp(typform->typnamespace);
11849 appendStringInfo(buf, "::%s.%s",
11850 quote_identifier(nspname), quote_identifier(typname));
11852 ReleaseSysCache(typetup);
11856 * generate_qualified_type_name
11857 * Compute the name to display for a type specified by OID
11859 * This is different from format_type_be() in that we unconditionally
11860 * schema-qualify the name. That also means no special syntax for
11861 * SQL-standard type names ... although in current usage, this should
11862 * only get used for domains, so such cases wouldn't occur anyway.
11864 static char *
11865 generate_qualified_type_name(Oid typid)
11867 HeapTuple tp;
11868 Form_pg_type typtup;
11869 char *typname;
11870 char *nspname;
11871 char *result;
11873 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11874 if (!HeapTupleIsValid(tp))
11875 elog(ERROR, "cache lookup failed for type %u", typid);
11876 typtup = (Form_pg_type) GETSTRUCT(tp);
11877 typname = NameStr(typtup->typname);
11879 nspname = get_namespace_name_or_temp(typtup->typnamespace);
11880 if (!nspname)
11881 elog(ERROR, "cache lookup failed for namespace %u",
11882 typtup->typnamespace);
11884 result = quote_qualified_identifier(nspname, typname);
11886 ReleaseSysCache(tp);
11888 return result;
11892 * generate_collation_name
11893 * Compute the name to display for a collation specified by OID
11895 * The result includes all necessary quoting and schema-prefixing.
11897 char *
11898 generate_collation_name(Oid collid)
11900 HeapTuple tp;
11901 Form_pg_collation colltup;
11902 char *collname;
11903 char *nspname;
11904 char *result;
11906 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11907 if (!HeapTupleIsValid(tp))
11908 elog(ERROR, "cache lookup failed for collation %u", collid);
11909 colltup = (Form_pg_collation) GETSTRUCT(tp);
11910 collname = NameStr(colltup->collname);
11912 if (!CollationIsVisible(collid))
11913 nspname = get_namespace_name_or_temp(colltup->collnamespace);
11914 else
11915 nspname = NULL;
11917 result = quote_qualified_identifier(nspname, collname);
11919 ReleaseSysCache(tp);
11921 return result;
11925 * Given a C string, produce a TEXT datum.
11927 * We assume that the input was palloc'd and may be freed.
11929 static text *
11930 string_to_text(char *str)
11932 text *result;
11934 result = cstring_to_text(str);
11935 pfree(str);
11936 return result;
11940 * Generate a C string representing a relation options from text[] datum.
11942 static void
11943 get_reloptions(StringInfo buf, Datum reloptions)
11945 Datum *options;
11946 int noptions;
11947 int i;
11949 deconstruct_array(DatumGetArrayTypeP(reloptions),
11950 TEXTOID, -1, false, TYPALIGN_INT,
11951 &options, NULL, &noptions);
11953 for (i = 0; i < noptions; i++)
11955 char *option = TextDatumGetCString(options[i]);
11956 char *name;
11957 char *separator;
11958 char *value;
11961 * Each array element should have the form name=value. If the "=" is
11962 * missing for some reason, treat it like an empty value.
11964 name = option;
11965 separator = strchr(option, '=');
11966 if (separator)
11968 *separator = '\0';
11969 value = separator + 1;
11971 else
11972 value = "";
11974 if (i > 0)
11975 appendStringInfoString(buf, ", ");
11976 appendStringInfo(buf, "%s=", quote_identifier(name));
11979 * In general we need to quote the value; but to avoid unnecessary
11980 * clutter, do not quote if it is an identifier that would not need
11981 * quoting. (We could also allow numbers, but that is a bit trickier
11982 * than it looks --- for example, are leading zeroes significant? We
11983 * don't want to assume very much here about what custom reloptions
11984 * might mean.)
11986 if (quote_identifier(value) == value)
11987 appendStringInfoString(buf, value);
11988 else
11989 simple_quote_literal(buf, value);
11991 pfree(option);
11996 * Generate a C string representing a relation's reloptions, or NULL if none.
11998 static char *
11999 flatten_reloptions(Oid relid)
12001 char *result = NULL;
12002 HeapTuple tuple;
12003 Datum reloptions;
12004 bool isnull;
12006 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12007 if (!HeapTupleIsValid(tuple))
12008 elog(ERROR, "cache lookup failed for relation %u", relid);
12010 reloptions = SysCacheGetAttr(RELOID, tuple,
12011 Anum_pg_class_reloptions, &isnull);
12012 if (!isnull)
12014 StringInfoData buf;
12016 initStringInfo(&buf);
12017 get_reloptions(&buf, reloptions);
12019 result = buf.data;
12022 ReleaseSysCache(tuple);
12024 return result;
12028 * get_range_partbound_string
12029 * A C string representation of one range partition bound
12031 char *
12032 get_range_partbound_string(List *bound_datums)
12034 deparse_context context;
12035 StringInfo buf = makeStringInfo();
12036 ListCell *cell;
12037 char *sep;
12039 memset(&context, 0, sizeof(deparse_context));
12040 context.buf = buf;
12042 appendStringInfoChar(buf, '(');
12043 sep = "";
12044 foreach(cell, bound_datums)
12046 PartitionRangeDatum *datum =
12047 lfirst_node(PartitionRangeDatum, cell);
12049 appendStringInfoString(buf, sep);
12050 if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
12051 appendStringInfoString(buf, "MINVALUE");
12052 else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
12053 appendStringInfoString(buf, "MAXVALUE");
12054 else
12056 Const *val = castNode(Const, datum->value);
12058 get_const_expr(val, &context, -1);
12060 sep = ", ";
12062 appendStringInfoChar(buf, ')');
12064 return buf->data;