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