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