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