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