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