1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
14 *-------------------------------------------------------------------------
21 #include "access/genam.h"
22 #include "access/sysattr.h"
23 #include "catalog/dependency.h"
24 #include "catalog/indexing.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_constraint.h"
27 #include "catalog/pg_depend.h"
28 #include "catalog/pg_language.h"
29 #include "catalog/pg_opclass.h"
30 #include "catalog/pg_operator.h"
31 #include "catalog/pg_proc.h"
32 #include "catalog/pg_trigger.h"
33 #include "catalog/pg_type.h"
34 #include "commands/defrem.h"
35 #include "commands/tablespace.h"
36 #include "executor/spi.h"
38 #include "nodes/makefuncs.h"
39 #include "nodes/nodeFuncs.h"
40 #include "optimizer/clauses.h"
41 #include "optimizer/tlist.h"
42 #include "parser/gramparse.h"
43 #include "parser/keywords.h"
44 #include "parser/parse_func.h"
45 #include "parser/parse_oper.h"
46 #include "parser/parsetree.h"
47 #include "rewrite/rewriteHandler.h"
48 #include "rewrite/rewriteManip.h"
49 #include "rewrite/rewriteSupport.h"
50 #include "utils/array.h"
51 #include "utils/builtins.h"
52 #include "utils/fmgroids.h"
53 #include "utils/lsyscache.h"
54 #include "utils/tqual.h"
55 #include "utils/syscache.h"
56 #include "utils/typcache.h"
57 #include "utils/xml.h"
61 * Pretty formatting constants
66 #define PRETTYINDENT_STD 8
67 #define PRETTYINDENT_JOIN 13
68 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
69 #define PRETTYINDENT_VAR 4
72 #define PRETTYFLAG_PAREN 1
73 #define PRETTYFLAG_INDENT 2
75 /* macro to test if pretty action needed */
76 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
77 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
85 /* Context info needed for invoking a recursive querytree display routine */
88 StringInfo buf
; /* output buffer to append to */
89 List
*namespaces
; /* List of deparse_namespace nodes */
90 List
*windowClause
; /* Current query level's WINDOW clause */
91 List
*windowTList
; /* targetlist for resolving WINDOW clause */
92 int prettyFlags
; /* enabling of pretty-print functions */
93 int indentLevel
; /* current indent level for prettyprint */
94 bool varprefix
; /* TRUE to print prefixes on Vars */
98 * Each level of query context around a subtree needs a level of Var namespace.
99 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
100 * the current context's namespaces list.
102 * The rangetable is the list of actual RTEs from the query tree, and the
103 * cte list is the list of actual CTEs.
105 * For deparsing plan trees, we provide for outer and inner subplan nodes.
106 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
107 * Also, in the plan-tree case we don't have access to the parse-time CTE
108 * list, so we need a list of subplans instead.
112 List
*rtable
; /* List of RangeTblEntry nodes */
113 List
*ctes
; /* List of CommonTableExpr nodes */
114 List
*subplans
; /* List of subplans, in plan-tree case */
115 Plan
*outer_plan
; /* OUTER subplan, or NULL if none */
116 Plan
*inner_plan
; /* INNER subplan, or NULL if none */
124 static SPIPlanPtr plan_getrulebyoid
= NULL
;
125 static const char *query_getrulebyoid
= "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
126 static SPIPlanPtr plan_getviewrule
= NULL
;
127 static const char *query_getviewrule
= "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
133 * Most of these functions used to use fixed-size buffers to build their
134 * results. Now, they take an (already initialized) StringInfo object
135 * as a parameter, and append their text output to its contents.
138 static char *deparse_expression_pretty(Node
*expr
, List
*dpcontext
,
139 bool forceprefix
, bool showimplicit
,
140 int prettyFlags
, int startIndent
);
141 static char *pg_get_viewdef_worker(Oid viewoid
, int prettyFlags
);
142 static void decompile_column_index_array(Datum column_index_array
, Oid relId
,
144 static char *pg_get_ruledef_worker(Oid ruleoid
, int prettyFlags
);
145 static char *pg_get_indexdef_worker(Oid indexrelid
, int colno
, bool showTblSpc
,
147 static char *pg_get_constraintdef_worker(Oid constraintId
, bool fullCommand
,
149 static text
*pg_get_expr_worker(text
*expr
, Oid relid
, const char *relname
,
151 static int print_function_arguments(StringInfo buf
, HeapTuple proctup
,
152 bool print_table_args
, bool print_defaults
);
153 static void print_function_rettype(StringInfo buf
, HeapTuple proctup
);
154 static void make_ruledef(StringInfo buf
, HeapTuple ruletup
, TupleDesc rulettc
,
156 static void make_viewdef(StringInfo buf
, HeapTuple ruletup
, TupleDesc rulettc
,
158 static void get_query_def(Query
*query
, StringInfo buf
, List
*parentnamespace
,
159 TupleDesc resultDesc
, int prettyFlags
, int startIndent
);
160 static void get_values_def(List
*values_lists
, deparse_context
*context
);
161 static void get_with_clause(Query
*query
, deparse_context
*context
);
162 static void get_select_query_def(Query
*query
, deparse_context
*context
,
163 TupleDesc resultDesc
);
164 static void get_insert_query_def(Query
*query
, deparse_context
*context
);
165 static void get_update_query_def(Query
*query
, deparse_context
*context
);
166 static void get_delete_query_def(Query
*query
, deparse_context
*context
);
167 static void get_utility_query_def(Query
*query
, deparse_context
*context
);
168 static void get_basic_select_query(Query
*query
, deparse_context
*context
,
169 TupleDesc resultDesc
);
170 static void get_target_list(List
*targetList
, deparse_context
*context
,
171 TupleDesc resultDesc
);
172 static void get_setop_query(Node
*setOp
, Query
*query
,
173 deparse_context
*context
,
174 TupleDesc resultDesc
);
175 static Node
*get_rule_sortgroupclause(SortGroupClause
*srt
, List
*tlist
,
177 deparse_context
*context
);
178 static void get_rule_orderby(List
*orderList
, List
*targetList
,
179 bool force_colno
, deparse_context
*context
);
180 static void get_rule_windowclause(Query
*query
, deparse_context
*context
);
181 static void get_rule_windowspec(WindowClause
*wc
, List
*targetList
,
182 deparse_context
*context
);
183 static void push_plan(deparse_namespace
*dpns
, Plan
*subplan
);
184 static char *get_variable(Var
*var
, int levelsup
, bool showstar
,
185 deparse_context
*context
);
186 static RangeTblEntry
*find_rte_by_refname(const char *refname
,
187 deparse_context
*context
);
188 static const char *get_simple_binary_op_name(OpExpr
*expr
);
189 static bool isSimpleNode(Node
*node
, Node
*parentNode
, int prettyFlags
);
190 static void appendStringInfoSpaces(StringInfo buf
, int count
);
191 static void appendContextKeyword(deparse_context
*context
, const char *str
,
192 int indentBefore
, int indentAfter
, int indentPlus
);
193 static void get_rule_expr(Node
*node
, deparse_context
*context
,
195 static void get_oper_expr(OpExpr
*expr
, deparse_context
*context
);
196 static void get_func_expr(FuncExpr
*expr
, deparse_context
*context
,
198 static void get_agg_expr(Aggref
*aggref
, deparse_context
*context
);
199 static void get_windowfunc_expr(WindowFunc
*wfunc
, deparse_context
*context
);
200 static void get_coercion_expr(Node
*arg
, deparse_context
*context
,
201 Oid resulttype
, int32 resulttypmod
,
203 static void get_const_expr(Const
*constval
, deparse_context
*context
,
205 static void simple_quote_literal(StringInfo buf
, const char *val
);
206 static void get_sublink_expr(SubLink
*sublink
, deparse_context
*context
);
207 static void get_from_clause(Query
*query
, const char *prefix
,
208 deparse_context
*context
);
209 static void get_from_clause_item(Node
*jtnode
, Query
*query
,
210 deparse_context
*context
);
211 static void get_from_clause_alias(Alias
*alias
, RangeTblEntry
*rte
,
212 deparse_context
*context
);
213 static void get_from_clause_coldeflist(List
*names
, List
*types
, List
*typmods
,
214 deparse_context
*context
);
215 static void get_opclass_name(Oid opclass
, Oid actual_datatype
,
217 static Node
*processIndirection(Node
*node
, deparse_context
*context
,
219 static void printSubscripts(ArrayRef
*aref
, deparse_context
*context
);
220 static char *generate_relation_name(Oid relid
, List
*namespaces
);
221 static char *generate_function_name(Oid funcid
, int nargs
, Oid
*argtypes
,
223 static char *generate_operator_name(Oid operid
, Oid arg1
, Oid arg2
);
224 static text
*string_to_text(char *str
);
225 static char *flatten_reloptions(Oid relid
);
227 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
231 * get_ruledef - Do it all and return a text
232 * that could be used as a statement
233 * to recreate the rule
237 pg_get_ruledef(PG_FUNCTION_ARGS
)
239 Oid ruleoid
= PG_GETARG_OID(0);
241 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid
, 0)));
246 pg_get_ruledef_ext(PG_FUNCTION_ARGS
)
248 Oid ruleoid
= PG_GETARG_OID(0);
249 bool pretty
= PG_GETARG_BOOL(1);
252 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
253 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid
, prettyFlags
)));
258 pg_get_ruledef_worker(Oid ruleoid
, int prettyFlags
)
268 * Do this first so that string is alloc'd in outer context not SPI's.
270 initStringInfo(&buf
);
273 * Connect to SPI manager
275 if (SPI_connect() != SPI_OK_CONNECT
)
276 elog(ERROR
, "SPI_connect failed");
279 * On the first call prepare the plan to lookup pg_rewrite. We read
280 * pg_rewrite over the SPI manager instead of using the syscache to be
281 * checked for read access on pg_rewrite.
283 if (plan_getrulebyoid
== NULL
)
288 argtypes
[0] = OIDOID
;
289 plan
= SPI_prepare(query_getrulebyoid
, 1, argtypes
);
291 elog(ERROR
, "SPI_prepare failed for \"%s\"", query_getrulebyoid
);
292 plan_getrulebyoid
= SPI_saveplan(plan
);
296 * Get the pg_rewrite tuple for this rule
298 args
[0] = ObjectIdGetDatum(ruleoid
);
300 spirc
= SPI_execute_plan(plan_getrulebyoid
, args
, nulls
, true, 1);
301 if (spirc
!= SPI_OK_SELECT
)
302 elog(ERROR
, "failed to get pg_rewrite tuple for rule %u", ruleoid
);
303 if (SPI_processed
!= 1)
304 appendStringInfo(&buf
, "-");
308 * Get the rule's definition and put it into executor's memory
310 ruletup
= SPI_tuptable
->vals
[0];
311 rulettc
= SPI_tuptable
->tupdesc
;
312 make_ruledef(&buf
, ruletup
, rulettc
, prettyFlags
);
316 * Disconnect from SPI manager
318 if (SPI_finish() != SPI_OK_FINISH
)
319 elog(ERROR
, "SPI_finish failed");
326 * get_viewdef - Mainly the same thing, but we
327 * only return the SELECT part of a view
331 pg_get_viewdef(PG_FUNCTION_ARGS
)
334 Oid viewoid
= PG_GETARG_OID(0);
336 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid
, 0)));
341 pg_get_viewdef_ext(PG_FUNCTION_ARGS
)
344 Oid viewoid
= PG_GETARG_OID(0);
345 bool pretty
= PG_GETARG_BOOL(1);
348 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
349 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid
, prettyFlags
)));
353 pg_get_viewdef_name(PG_FUNCTION_ARGS
)
355 /* By qualified name */
356 text
*viewname
= PG_GETARG_TEXT_P(0);
360 viewrel
= makeRangeVarFromNameList(textToQualifiedNameList(viewname
));
361 viewoid
= RangeVarGetRelid(viewrel
, false);
363 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid
, 0)));
368 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS
)
370 /* By qualified name */
371 text
*viewname
= PG_GETARG_TEXT_P(0);
372 bool pretty
= PG_GETARG_BOOL(1);
377 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
378 viewrel
= makeRangeVarFromNameList(textToQualifiedNameList(viewname
));
379 viewoid
= RangeVarGetRelid(viewrel
, false);
381 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid
, prettyFlags
)));
385 * Common code for by-OID and by-name variants of pg_get_viewdef
388 pg_get_viewdef_worker(Oid viewoid
, int prettyFlags
)
398 * Do this first so that string is alloc'd in outer context not SPI's.
400 initStringInfo(&buf
);
403 * Connect to SPI manager
405 if (SPI_connect() != SPI_OK_CONNECT
)
406 elog(ERROR
, "SPI_connect failed");
409 * On the first call prepare the plan to lookup pg_rewrite. We read
410 * pg_rewrite over the SPI manager instead of using the syscache to be
411 * checked for read access on pg_rewrite.
413 if (plan_getviewrule
== NULL
)
418 argtypes
[0] = OIDOID
;
419 argtypes
[1] = NAMEOID
;
420 plan
= SPI_prepare(query_getviewrule
, 2, argtypes
);
422 elog(ERROR
, "SPI_prepare failed for \"%s\"", query_getviewrule
);
423 plan_getviewrule
= SPI_saveplan(plan
);
427 * Get the pg_rewrite tuple for the view's SELECT rule
429 args
[0] = ObjectIdGetDatum(viewoid
);
430 args
[1] = PointerGetDatum(ViewSelectRuleName
);
433 spirc
= SPI_execute_plan(plan_getviewrule
, args
, nulls
, true, 2);
434 if (spirc
!= SPI_OK_SELECT
)
435 elog(ERROR
, "failed to get pg_rewrite tuple for view %u", viewoid
);
436 if (SPI_processed
!= 1)
437 appendStringInfo(&buf
, "Not a view");
441 * Get the rule's definition and put it into executor's memory
443 ruletup
= SPI_tuptable
->vals
[0];
444 rulettc
= SPI_tuptable
->tupdesc
;
445 make_viewdef(&buf
, ruletup
, rulettc
, prettyFlags
);
449 * Disconnect from SPI manager
451 if (SPI_finish() != SPI_OK_FINISH
)
452 elog(ERROR
, "SPI_finish failed");
458 * get_triggerdef - Get the definition of a trigger
462 pg_get_triggerdef(PG_FUNCTION_ARGS
)
464 Oid trigid
= PG_GETARG_OID(0);
466 Form_pg_trigger trigrec
;
475 * Fetch the pg_trigger tuple by the Oid of the trigger
477 tgrel
= heap_open(TriggerRelationId
, AccessShareLock
);
479 ScanKeyInit(&skey
[0],
480 ObjectIdAttributeNumber
,
481 BTEqualStrategyNumber
, F_OIDEQ
,
482 ObjectIdGetDatum(trigid
));
484 tgscan
= systable_beginscan(tgrel
, TriggerOidIndexId
, true,
485 SnapshotNow
, 1, skey
);
487 ht_trig
= systable_getnext(tgscan
);
489 if (!HeapTupleIsValid(ht_trig
))
490 elog(ERROR
, "could not find tuple for trigger %u", trigid
);
492 trigrec
= (Form_pg_trigger
) GETSTRUCT(ht_trig
);
495 * Start the trigger definition. Note that the trigger's name should never
496 * be schema-qualified, but the trigger rel's name may be.
498 initStringInfo(&buf
);
500 tgname
= NameStr(trigrec
->tgname
);
501 appendStringInfo(&buf
, "CREATE %sTRIGGER %s ",
502 trigrec
->tgisconstraint
? "CONSTRAINT " : "",
503 quote_identifier(tgname
));
505 if (TRIGGER_FOR_BEFORE(trigrec
->tgtype
))
506 appendStringInfo(&buf
, "BEFORE");
508 appendStringInfo(&buf
, "AFTER");
509 if (TRIGGER_FOR_INSERT(trigrec
->tgtype
))
511 appendStringInfo(&buf
, " INSERT");
514 if (TRIGGER_FOR_DELETE(trigrec
->tgtype
))
517 appendStringInfo(&buf
, " OR DELETE");
519 appendStringInfo(&buf
, " DELETE");
522 if (TRIGGER_FOR_UPDATE(trigrec
->tgtype
))
525 appendStringInfo(&buf
, " OR UPDATE");
527 appendStringInfo(&buf
, " UPDATE");
529 if (TRIGGER_FOR_TRUNCATE(trigrec
->tgtype
))
532 appendStringInfo(&buf
, " OR TRUNCATE");
534 appendStringInfo(&buf
, " TRUNCATE");
536 appendStringInfo(&buf
, " ON %s ",
537 generate_relation_name(trigrec
->tgrelid
, NIL
));
539 if (trigrec
->tgisconstraint
)
541 if (trigrec
->tgconstrrelid
!= InvalidOid
)
542 appendStringInfo(&buf
, "FROM %s ",
543 generate_relation_name(trigrec
->tgconstrrelid
,
545 if (!trigrec
->tgdeferrable
)
546 appendStringInfo(&buf
, "NOT ");
547 appendStringInfo(&buf
, "DEFERRABLE INITIALLY ");
548 if (trigrec
->tginitdeferred
)
549 appendStringInfo(&buf
, "DEFERRED ");
551 appendStringInfo(&buf
, "IMMEDIATE ");
555 if (TRIGGER_FOR_ROW(trigrec
->tgtype
))
556 appendStringInfo(&buf
, "FOR EACH ROW ");
558 appendStringInfo(&buf
, "FOR EACH STATEMENT ");
560 appendStringInfo(&buf
, "EXECUTE PROCEDURE %s(",
561 generate_function_name(trigrec
->tgfoid
, 0, NULL
, NULL
));
563 if (trigrec
->tgnargs
> 0)
570 val
= DatumGetByteaP(fastgetattr(ht_trig
,
571 Anum_pg_trigger_tgargs
,
572 tgrel
->rd_att
, &isnull
));
574 elog(ERROR
, "tgargs is null for trigger %u", trigid
);
575 p
= (char *) VARDATA(val
);
576 for (i
= 0; i
< trigrec
->tgnargs
; i
++)
579 appendStringInfo(&buf
, ", ");
580 simple_quote_literal(&buf
, p
);
581 /* advance p to next string embedded in tgargs */
588 /* We deliberately do not put semi-colon at end */
589 appendStringInfo(&buf
, ")");
592 systable_endscan(tgscan
);
594 heap_close(tgrel
, AccessShareLock
);
596 PG_RETURN_TEXT_P(string_to_text(buf
.data
));
600 * get_indexdef - Get the definition of an index
602 * In the extended version, there is a colno argument as well as pretty bool.
603 * if colno == 0, we want a complete index definition.
604 * if colno > 0, we only want the Nth index key's variable or expression.
606 * Note that the SQL-function versions of this omit any info about the
607 * index tablespace; this is intentional because pg_dump wants it that way.
608 * However pg_get_indexdef_string() includes index tablespace if not default.
612 pg_get_indexdef(PG_FUNCTION_ARGS
)
614 Oid indexrelid
= PG_GETARG_OID(0);
616 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid
, 0,
621 pg_get_indexdef_ext(PG_FUNCTION_ARGS
)
623 Oid indexrelid
= PG_GETARG_OID(0);
624 int32 colno
= PG_GETARG_INT32(1);
625 bool pretty
= PG_GETARG_BOOL(2);
628 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
629 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid
, colno
,
630 false, prettyFlags
)));
633 /* Internal version that returns a palloc'd C string */
635 pg_get_indexdef_string(Oid indexrelid
)
637 return pg_get_indexdef_worker(indexrelid
, 0, true, 0);
641 pg_get_indexdef_worker(Oid indexrelid
, int colno
, bool showTblSpc
,
647 Form_pg_index idxrec
;
648 Form_pg_class idxrelrec
;
651 ListCell
*indexpr_item
;
657 Datum indoptionDatum
;
660 int2vector
*indoption
;
666 * Fetch the pg_index tuple by the Oid of the index
668 ht_idx
= SearchSysCache(INDEXRELID
,
669 ObjectIdGetDatum(indexrelid
),
671 if (!HeapTupleIsValid(ht_idx
))
672 elog(ERROR
, "cache lookup failed for index %u", indexrelid
);
673 idxrec
= (Form_pg_index
) GETSTRUCT(ht_idx
);
675 indrelid
= idxrec
->indrelid
;
676 Assert(indexrelid
== idxrec
->indexrelid
);
678 /* Must get indclass and indoption the hard way */
679 indclassDatum
= SysCacheGetAttr(INDEXRELID
, ht_idx
,
680 Anum_pg_index_indclass
, &isnull
);
682 indclass
= (oidvector
*) DatumGetPointer(indclassDatum
);
683 indoptionDatum
= SysCacheGetAttr(INDEXRELID
, ht_idx
,
684 Anum_pg_index_indoption
, &isnull
);
686 indoption
= (int2vector
*) DatumGetPointer(indoptionDatum
);
689 * Fetch the pg_class tuple of the index relation
691 ht_idxrel
= SearchSysCache(RELOID
,
692 ObjectIdGetDatum(indexrelid
),
694 if (!HeapTupleIsValid(ht_idxrel
))
695 elog(ERROR
, "cache lookup failed for relation %u", indexrelid
);
696 idxrelrec
= (Form_pg_class
) GETSTRUCT(ht_idxrel
);
699 * Fetch the pg_am tuple of the index' access method
701 ht_am
= SearchSysCache(AMOID
,
702 ObjectIdGetDatum(idxrelrec
->relam
),
704 if (!HeapTupleIsValid(ht_am
))
705 elog(ERROR
, "cache lookup failed for access method %u",
707 amrec
= (Form_pg_am
) GETSTRUCT(ht_am
);
710 * Get the index expressions, if any. (NOTE: we do not use the relcache
711 * versions of the expressions and predicate, because we want to display
712 * non-const-folded expressions.)
714 if (!heap_attisnull(ht_idx
, Anum_pg_index_indexprs
))
720 exprsDatum
= SysCacheGetAttr(INDEXRELID
, ht_idx
,
721 Anum_pg_index_indexprs
, &isnull
);
723 exprsString
= TextDatumGetCString(exprsDatum
);
724 indexprs
= (List
*) stringToNode(exprsString
);
730 indexpr_item
= list_head(indexprs
);
732 context
= deparse_context_for(get_rel_name(indrelid
), indrelid
);
735 * Start the index definition. Note that the index's name should never be
736 * schema-qualified, but the indexed rel's name may be.
738 initStringInfo(&buf
);
741 appendStringInfo(&buf
, "CREATE %sINDEX %s ON %s USING %s (",
742 idxrec
->indisunique
? "UNIQUE " : "",
743 quote_identifier(NameStr(idxrelrec
->relname
)),
744 generate_relation_name(indrelid
, NIL
),
745 quote_identifier(NameStr(amrec
->amname
)));
748 * Report the indexed attributes
751 for (keyno
= 0; keyno
< idxrec
->indnatts
; keyno
++)
753 AttrNumber attnum
= idxrec
->indkey
.values
[keyno
];
754 int16 opt
= indoption
->values
[keyno
];
757 appendStringInfoString(&buf
, sep
);
762 /* Simple index column */
765 attname
= get_relid_attribute_name(indrelid
, attnum
);
766 if (!colno
|| colno
== keyno
+ 1)
767 appendStringInfoString(&buf
, quote_identifier(attname
));
768 keycoltype
= get_atttype(indrelid
, attnum
);
772 /* expressional index */
775 if (indexpr_item
== NULL
)
776 elog(ERROR
, "too few entries in indexprs list");
777 indexkey
= (Node
*) lfirst(indexpr_item
);
778 indexpr_item
= lnext(indexpr_item
);
780 str
= deparse_expression_pretty(indexkey
, context
, false, false,
782 if (!colno
|| colno
== keyno
+ 1)
784 /* Need parens if it's not a bare function call */
785 if (indexkey
&& IsA(indexkey
, FuncExpr
) &&
786 ((FuncExpr
*) indexkey
)->funcformat
== COERCE_EXPLICIT_CALL
)
787 appendStringInfoString(&buf
, str
);
789 appendStringInfo(&buf
, "(%s)", str
);
791 keycoltype
= exprType(indexkey
);
794 /* Provide decoration only in the colno=0 case */
797 /* Add the operator class name, if not default */
798 get_opclass_name(indclass
->values
[keyno
], keycoltype
, &buf
);
800 /* Add options if relevant */
801 if (amrec
->amcanorder
)
803 /* if it supports sort ordering, report DESC and NULLS opts */
804 if (opt
& INDOPTION_DESC
)
806 appendStringInfo(&buf
, " DESC");
807 /* NULLS FIRST is the default in this case */
808 if (!(opt
& INDOPTION_NULLS_FIRST
))
809 appendStringInfo(&buf
, " NULLS LAST");
813 if (opt
& INDOPTION_NULLS_FIRST
)
814 appendStringInfo(&buf
, " NULLS FIRST");
822 appendStringInfoChar(&buf
, ')');
825 * If it has options, append "WITH (options)"
827 str
= flatten_reloptions(indexrelid
);
830 appendStringInfo(&buf
, " WITH (%s)", str
);
835 * If it's in a nondefault tablespace, say so, but only if requested
841 tblspc
= get_rel_tablespace(indexrelid
);
842 if (OidIsValid(tblspc
))
843 appendStringInfo(&buf
, " TABLESPACE %s",
844 quote_identifier(get_tablespace_name(tblspc
)));
848 * If it's a partial index, decompile and append the predicate
850 if (!heap_attisnull(ht_idx
, Anum_pg_index_indpred
))
857 /* Convert text string to node tree */
858 predDatum
= SysCacheGetAttr(INDEXRELID
, ht_idx
,
859 Anum_pg_index_indpred
, &isnull
);
861 predString
= TextDatumGetCString(predDatum
);
862 node
= (Node
*) stringToNode(predString
);
866 str
= deparse_expression_pretty(node
, context
, false, false,
868 appendStringInfo(&buf
, " WHERE %s", str
);
873 ReleaseSysCache(ht_idx
);
874 ReleaseSysCache(ht_idxrel
);
875 ReleaseSysCache(ht_am
);
882 * pg_get_constraintdef
884 * Returns the definition for the constraint, ie, everything that needs to
885 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
888 pg_get_constraintdef(PG_FUNCTION_ARGS
)
890 Oid constraintId
= PG_GETARG_OID(0);
892 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId
,
897 pg_get_constraintdef_ext(PG_FUNCTION_ARGS
)
899 Oid constraintId
= PG_GETARG_OID(0);
900 bool pretty
= PG_GETARG_BOOL(1);
903 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
904 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId
,
905 false, prettyFlags
)));
908 /* Internal version that returns a palloc'd C string */
910 pg_get_constraintdef_string(Oid constraintId
)
912 return pg_get_constraintdef_worker(constraintId
, true, 0);
916 pg_get_constraintdef_worker(Oid constraintId
, bool fullCommand
,
920 Form_pg_constraint conForm
;
923 tup
= SearchSysCache(CONSTROID
,
924 ObjectIdGetDatum(constraintId
),
926 if (!HeapTupleIsValid(tup
)) /* should not happen */
927 elog(ERROR
, "cache lookup failed for constraint %u", constraintId
);
928 conForm
= (Form_pg_constraint
) GETSTRUCT(tup
);
930 initStringInfo(&buf
);
932 if (fullCommand
&& OidIsValid(conForm
->conrelid
))
934 appendStringInfo(&buf
, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
935 generate_relation_name(conForm
->conrelid
, NIL
),
936 quote_identifier(NameStr(conForm
->conname
)));
939 switch (conForm
->contype
)
941 case CONSTRAINT_FOREIGN
:
947 /* Start off the constraint definition */
948 appendStringInfo(&buf
, "FOREIGN KEY (");
950 /* Fetch and build referencing-column list */
951 val
= SysCacheGetAttr(CONSTROID
, tup
,
952 Anum_pg_constraint_conkey
, &isnull
);
954 elog(ERROR
, "null conkey for constraint %u",
957 decompile_column_index_array(val
, conForm
->conrelid
, &buf
);
959 /* add foreign relation name */
960 appendStringInfo(&buf
, ") REFERENCES %s(",
961 generate_relation_name(conForm
->confrelid
,
964 /* Fetch and build referenced-column list */
965 val
= SysCacheGetAttr(CONSTROID
, tup
,
966 Anum_pg_constraint_confkey
, &isnull
);
968 elog(ERROR
, "null confkey for constraint %u",
971 decompile_column_index_array(val
, conForm
->confrelid
, &buf
);
973 appendStringInfo(&buf
, ")");
976 switch (conForm
->confmatchtype
)
978 case FKCONSTR_MATCH_FULL
:
979 string
= " MATCH FULL";
981 case FKCONSTR_MATCH_PARTIAL
:
982 string
= " MATCH PARTIAL";
984 case FKCONSTR_MATCH_UNSPECIFIED
:
988 elog(ERROR
, "unrecognized confmatchtype: %d",
989 conForm
->confmatchtype
);
990 string
= ""; /* keep compiler quiet */
993 appendStringInfoString(&buf
, string
);
995 /* Add ON UPDATE and ON DELETE clauses, if needed */
996 switch (conForm
->confupdtype
)
998 case FKCONSTR_ACTION_NOACTION
:
999 string
= NULL
; /* suppress default */
1001 case FKCONSTR_ACTION_RESTRICT
:
1002 string
= "RESTRICT";
1004 case FKCONSTR_ACTION_CASCADE
:
1007 case FKCONSTR_ACTION_SETNULL
:
1008 string
= "SET NULL";
1010 case FKCONSTR_ACTION_SETDEFAULT
:
1011 string
= "SET DEFAULT";
1014 elog(ERROR
, "unrecognized confupdtype: %d",
1015 conForm
->confupdtype
);
1016 string
= NULL
; /* keep compiler quiet */
1020 appendStringInfo(&buf
, " ON UPDATE %s", string
);
1022 switch (conForm
->confdeltype
)
1024 case FKCONSTR_ACTION_NOACTION
:
1025 string
= NULL
; /* suppress default */
1027 case FKCONSTR_ACTION_RESTRICT
:
1028 string
= "RESTRICT";
1030 case FKCONSTR_ACTION_CASCADE
:
1033 case FKCONSTR_ACTION_SETNULL
:
1034 string
= "SET NULL";
1036 case FKCONSTR_ACTION_SETDEFAULT
:
1037 string
= "SET DEFAULT";
1040 elog(ERROR
, "unrecognized confdeltype: %d",
1041 conForm
->confdeltype
);
1042 string
= NULL
; /* keep compiler quiet */
1046 appendStringInfo(&buf
, " ON DELETE %s", string
);
1048 if (conForm
->condeferrable
)
1049 appendStringInfo(&buf
, " DEFERRABLE");
1050 if (conForm
->condeferred
)
1051 appendStringInfo(&buf
, " INITIALLY DEFERRED");
1055 case CONSTRAINT_PRIMARY
:
1056 case CONSTRAINT_UNIQUE
:
1062 /* Start off the constraint definition */
1063 if (conForm
->contype
== CONSTRAINT_PRIMARY
)
1064 appendStringInfo(&buf
, "PRIMARY KEY (");
1066 appendStringInfo(&buf
, "UNIQUE (");
1068 /* Fetch and build target column list */
1069 val
= SysCacheGetAttr(CONSTROID
, tup
,
1070 Anum_pg_constraint_conkey
, &isnull
);
1072 elog(ERROR
, "null conkey for constraint %u",
1075 decompile_column_index_array(val
, conForm
->conrelid
, &buf
);
1077 appendStringInfo(&buf
, ")");
1079 indexId
= get_constraint_index(constraintId
);
1081 /* XXX why do we only print these bits if fullCommand? */
1082 if (fullCommand
&& OidIsValid(indexId
))
1084 char *options
= flatten_reloptions(indexId
);
1089 appendStringInfo(&buf
, " WITH (%s)", options
);
1093 tblspc
= get_rel_tablespace(indexId
);
1094 if (OidIsValid(tblspc
))
1095 appendStringInfo(&buf
, " USING INDEX TABLESPACE %s",
1096 quote_identifier(get_tablespace_name(tblspc
)));
1101 case CONSTRAINT_CHECK
:
1110 /* Fetch constraint expression in parsetree form */
1111 val
= SysCacheGetAttr(CONSTROID
, tup
,
1112 Anum_pg_constraint_conbin
, &isnull
);
1114 elog(ERROR
, "null conbin for constraint %u",
1117 conbin
= TextDatumGetCString(val
);
1118 expr
= stringToNode(conbin
);
1120 /* Set up deparsing context for Var nodes in constraint */
1121 if (conForm
->conrelid
!= InvalidOid
)
1123 /* relation constraint */
1124 context
= deparse_context_for(get_rel_name(conForm
->conrelid
),
1129 /* domain constraint --- can't have Vars */
1133 consrc
= deparse_expression_pretty(expr
, context
, false, false,
1137 * Now emit the constraint definition. There are cases where
1138 * the constraint expression will be fully parenthesized and
1139 * we don't need the outer parens ... but there are other
1140 * cases where we do need 'em. Be conservative for now.
1142 * Note that simply checking for leading '(' and trailing ')'
1143 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1145 appendStringInfo(&buf
, "CHECK (%s)", consrc
);
1150 elog(ERROR
, "invalid constraint type \"%c\"", conForm
->contype
);
1155 ReleaseSysCache(tup
);
1162 * Convert an int16[] Datum into a comma-separated list of column names
1163 * for the indicated relation; append the list to buf.
1166 decompile_column_index_array(Datum column_index_array
, Oid relId
,
1173 /* Extract data from array of int16 */
1174 deconstruct_array(DatumGetArrayTypeP(column_index_array
),
1175 INT2OID
, 2, true, 's',
1176 &keys
, NULL
, &nKeys
);
1178 for (j
= 0; j
< nKeys
; j
++)
1182 colName
= get_relid_attribute_name(relId
, DatumGetInt16(keys
[j
]));
1185 appendStringInfoString(buf
, quote_identifier(colName
));
1187 appendStringInfo(buf
, ", %s", quote_identifier(colName
));
1193 * get_expr - Decompile an expression tree
1195 * Input: an expression tree in nodeToString form, and a relation OID
1197 * Output: reverse-listed expression
1199 * Currently, the expression can only refer to a single relation, namely
1200 * the one specified by the second parameter. This is sufficient for
1201 * partial indexes, column default expressions, etc. We also support
1202 * Var-free expressions, for which the OID can be InvalidOid.
1206 pg_get_expr(PG_FUNCTION_ARGS
)
1208 text
*expr
= PG_GETARG_TEXT_P(0);
1209 Oid relid
= PG_GETARG_OID(1);
1212 if (OidIsValid(relid
))
1214 /* Get the name for the relation */
1215 relname
= get_rel_name(relid
);
1218 * If the OID isn't actually valid, don't throw an error, just return
1219 * NULL. This is a bit questionable, but it's what we've done
1220 * historically, and it can help avoid unwanted failures when
1221 * examining catalog entries for just-deleted relations.
1223 if (relname
== NULL
)
1229 PG_RETURN_TEXT_P(pg_get_expr_worker(expr
, relid
, relname
, 0));
1233 pg_get_expr_ext(PG_FUNCTION_ARGS
)
1235 text
*expr
= PG_GETARG_TEXT_P(0);
1236 Oid relid
= PG_GETARG_OID(1);
1237 bool pretty
= PG_GETARG_BOOL(2);
1241 prettyFlags
= pretty
? PRETTYFLAG_PAREN
| PRETTYFLAG_INDENT
: 0;
1243 if (OidIsValid(relid
))
1245 /* Get the name for the relation */
1246 relname
= get_rel_name(relid
);
1247 /* See notes above */
1248 if (relname
== NULL
)
1254 PG_RETURN_TEXT_P(pg_get_expr_worker(expr
, relid
, relname
, prettyFlags
));
1258 pg_get_expr_worker(text
*expr
, Oid relid
, const char *relname
, int prettyFlags
)
1265 /* Convert input TEXT object to C string */
1266 exprstr
= text_to_cstring(expr
);
1268 /* Convert expression to node tree */
1269 node
= (Node
*) stringToNode(exprstr
);
1273 /* Prepare deparse context if needed */
1274 if (OidIsValid(relid
))
1275 context
= deparse_context_for(relname
, relid
);
1280 str
= deparse_expression_pretty(node
, context
, false, false,
1283 return string_to_text(str
);
1288 * get_userbyid - Get a user name by roleid and
1289 * fallback to 'unknown (OID=n)'
1293 pg_get_userbyid(PG_FUNCTION_ARGS
)
1295 Oid roleid
= PG_GETARG_OID(0);
1298 Form_pg_authid role_rec
;
1301 * Allocate space for the result
1303 result
= (Name
) palloc(NAMEDATALEN
);
1304 memset(NameStr(*result
), 0, NAMEDATALEN
);
1307 * Get the pg_authid entry and print the result
1309 roletup
= SearchSysCache(AUTHOID
,
1310 ObjectIdGetDatum(roleid
),
1312 if (HeapTupleIsValid(roletup
))
1314 role_rec
= (Form_pg_authid
) GETSTRUCT(roletup
);
1315 StrNCpy(NameStr(*result
), NameStr(role_rec
->rolname
), NAMEDATALEN
);
1316 ReleaseSysCache(roletup
);
1319 sprintf(NameStr(*result
), "unknown (OID=%u)", roleid
);
1321 PG_RETURN_NAME(result
);
1326 * pg_get_serial_sequence
1327 * Get the name of the sequence used by a serial column,
1328 * formatted suitably for passing to setval, nextval or currval.
1329 * First parameter is not treated as double-quoted, second parameter
1330 * is --- see documentation for reason.
1333 pg_get_serial_sequence(PG_FUNCTION_ARGS
)
1335 text
*tablename
= PG_GETARG_TEXT_P(0);
1336 text
*columnname
= PG_GETARG_TEXT_PP(1);
1341 Oid sequenceId
= InvalidOid
;
1347 /* Get the OID of the table */
1348 tablerv
= makeRangeVarFromNameList(textToQualifiedNameList(tablename
));
1349 tableOid
= RangeVarGetRelid(tablerv
, false);
1351 /* Get the number of the column */
1352 column
= text_to_cstring(columnname
);
1354 attnum
= get_attnum(tableOid
, column
);
1355 if (attnum
== InvalidAttrNumber
)
1357 (errcode(ERRCODE_UNDEFINED_COLUMN
),
1358 errmsg("column \"%s\" of relation \"%s\" does not exist",
1359 column
, tablerv
->relname
)));
1361 /* Search the dependency table for the dependent sequence */
1362 depRel
= heap_open(DependRelationId
, AccessShareLock
);
1364 ScanKeyInit(&key
[0],
1365 Anum_pg_depend_refclassid
,
1366 BTEqualStrategyNumber
, F_OIDEQ
,
1367 ObjectIdGetDatum(RelationRelationId
));
1368 ScanKeyInit(&key
[1],
1369 Anum_pg_depend_refobjid
,
1370 BTEqualStrategyNumber
, F_OIDEQ
,
1371 ObjectIdGetDatum(tableOid
));
1372 ScanKeyInit(&key
[2],
1373 Anum_pg_depend_refobjsubid
,
1374 BTEqualStrategyNumber
, F_INT4EQ
,
1375 Int32GetDatum(attnum
));
1377 scan
= systable_beginscan(depRel
, DependReferenceIndexId
, true,
1378 SnapshotNow
, 3, key
);
1380 while (HeapTupleIsValid(tup
= systable_getnext(scan
)))
1382 Form_pg_depend deprec
= (Form_pg_depend
) GETSTRUCT(tup
);
1385 * We assume any auto dependency of a sequence on a column must be
1386 * what we are looking for. (We need the relkind test because indexes
1387 * can also have auto dependencies on columns.)
1389 if (deprec
->classid
== RelationRelationId
&&
1390 deprec
->objsubid
== 0 &&
1391 deprec
->deptype
== DEPENDENCY_AUTO
&&
1392 get_rel_relkind(deprec
->objid
) == RELKIND_SEQUENCE
)
1394 sequenceId
= deprec
->objid
;
1399 systable_endscan(scan
);
1400 heap_close(depRel
, AccessShareLock
);
1402 if (OidIsValid(sequenceId
))
1405 Form_pg_class classtuple
;
1409 /* Get the sequence's pg_class entry */
1410 classtup
= SearchSysCache(RELOID
,
1411 ObjectIdGetDatum(sequenceId
),
1413 if (!HeapTupleIsValid(classtup
))
1414 elog(ERROR
, "cache lookup failed for relation %u", sequenceId
);
1415 classtuple
= (Form_pg_class
) GETSTRUCT(classtup
);
1417 /* Get the namespace */
1418 nspname
= get_namespace_name(classtuple
->relnamespace
);
1420 elog(ERROR
, "cache lookup failed for namespace %u",
1421 classtuple
->relnamespace
);
1423 /* And construct the result string */
1424 result
= quote_qualified_identifier(nspname
,
1425 NameStr(classtuple
->relname
));
1427 ReleaseSysCache(classtup
);
1429 PG_RETURN_TEXT_P(string_to_text(result
));
1437 * pg_get_functiondef
1438 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1439 * the specified function.
1442 pg_get_functiondef(PG_FUNCTION_ARGS
)
1444 Oid funcid
= PG_GETARG_OID(0);
1450 Form_pg_language lang
;
1459 initStringInfo(&buf
);
1461 /* Look up the function */
1462 proctup
= SearchSysCache(PROCOID
,
1463 ObjectIdGetDatum(funcid
),
1465 if (!HeapTupleIsValid(proctup
))
1466 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1467 proc
= (Form_pg_proc
) GETSTRUCT(proctup
);
1468 name
= NameStr(proc
->proname
);
1472 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
1473 errmsg("\"%s\" is an aggregate function", name
)));
1475 /* Need its pg_language tuple for the language name */
1476 langtup
= SearchSysCache(LANGOID
,
1477 ObjectIdGetDatum(proc
->prolang
),
1479 if (!HeapTupleIsValid(langtup
))
1480 elog(ERROR
, "cache lookup failed for language %u", proc
->prolang
);
1481 lang
= (Form_pg_language
) GETSTRUCT(langtup
);
1484 * We always qualify the function name, to ensure the right function
1487 nsp
= get_namespace_name(proc
->pronamespace
);
1488 appendStringInfo(&buf
, "CREATE OR REPLACE FUNCTION %s(",
1489 quote_qualified_identifier(nsp
, name
));
1490 (void) print_function_arguments(&buf
, proctup
, false, true);
1491 appendStringInfoString(&buf
, ")\n RETURNS ");
1492 print_function_rettype(&buf
, proctup
);
1493 appendStringInfo(&buf
, "\n LANGUAGE %s\n",
1494 quote_identifier(NameStr(lang
->lanname
)));
1496 /* Emit some miscellaneous options on one line */
1499 if (proc
->proiswindow
)
1500 appendStringInfoString(&buf
, " WINDOW");
1501 switch (proc
->provolatile
)
1503 case PROVOLATILE_IMMUTABLE
:
1504 appendStringInfoString(&buf
, " IMMUTABLE");
1506 case PROVOLATILE_STABLE
:
1507 appendStringInfoString(&buf
, " STABLE");
1509 case PROVOLATILE_VOLATILE
:
1512 if (proc
->proisstrict
)
1513 appendStringInfoString(&buf
, " STRICT");
1514 if (proc
->prosecdef
)
1515 appendStringInfoString(&buf
, " SECURITY DEFINER");
1517 /* This code for the default cost and rows should match functioncmds.c */
1518 if (proc
->prolang
== INTERNALlanguageId
||
1519 proc
->prolang
== ClanguageId
)
1523 if (proc
->procost
!= procost
)
1524 appendStringInfo(&buf
, " COST %g", proc
->procost
);
1526 if (proc
->prorows
> 0 && proc
->prorows
!= 1000)
1527 appendStringInfo(&buf
, " ROWS %g", proc
->prorows
);
1529 if (oldlen
!= buf
.len
)
1530 appendStringInfoChar(&buf
, '\n');
1532 /* Emit any proconfig options, one per line */
1533 tmp
= SysCacheGetAttr(PROCOID
, proctup
, Anum_pg_proc_proconfig
, &isnull
);
1536 ArrayType
*a
= DatumGetArrayTypeP(tmp
);
1539 Assert(ARR_ELEMTYPE(a
) == TEXTOID
);
1540 Assert(ARR_NDIM(a
) == 1);
1541 Assert(ARR_LBOUND(a
)[0] == 1);
1543 for (i
= 1; i
<= ARR_DIMS(a
)[0]; i
++)
1547 d
= array_ref(a
, 1, &i
,
1548 -1 /* varlenarray */ ,
1549 -1 /* TEXT's typlen */ ,
1550 false /* TEXT's typbyval */ ,
1551 'i' /* TEXT's typalign */ ,
1555 char *configitem
= TextDatumGetCString(d
);
1558 pos
= strchr(configitem
, '=');
1563 appendStringInfo(&buf
, " SET %s TO ",
1564 quote_identifier(configitem
));
1567 * Some GUC variable names are 'LIST' type and hence must not
1570 if (pg_strcasecmp(configitem
, "DateStyle") == 0
1571 || pg_strcasecmp(configitem
, "search_path") == 0)
1572 appendStringInfoString(&buf
, pos
);
1574 simple_quote_literal(&buf
, pos
);
1575 appendStringInfoChar(&buf
, '\n');
1580 /* And finally the function definition ... */
1581 appendStringInfoString(&buf
, "AS ");
1583 tmp
= SysCacheGetAttr(PROCOID
, proctup
, Anum_pg_proc_probin
, &isnull
);
1586 simple_quote_literal(&buf
, TextDatumGetCString(tmp
));
1587 appendStringInfoString(&buf
, ", "); /* assume prosrc isn't null */
1590 tmp
= SysCacheGetAttr(PROCOID
, proctup
, Anum_pg_proc_prosrc
, &isnull
);
1592 elog(ERROR
, "null prosrc");
1593 prosrc
= TextDatumGetCString(tmp
);
1596 * We always use dollar quoting. Figure out a suitable delimiter.
1598 * Since the user is likely to be editing the function body string,
1599 * we shouldn't use a short delimiter that he might easily create a
1600 * conflict with. Hence prefer "$function$", but extend if needed.
1602 initStringInfo(&dq
);
1603 appendStringInfoString(&dq
, "$function");
1604 while (strstr(prosrc
, dq
.data
) != NULL
)
1605 appendStringInfoChar(&dq
, 'x');
1606 appendStringInfoChar(&dq
, '$');
1608 appendStringInfoString(&buf
, dq
.data
);
1609 appendStringInfoString(&buf
, prosrc
);
1610 appendStringInfoString(&buf
, dq
.data
);
1612 appendStringInfoString(&buf
, "\n");
1614 ReleaseSysCache(langtup
);
1615 ReleaseSysCache(proctup
);
1617 PG_RETURN_TEXT_P(string_to_text(buf
.data
));
1621 * pg_get_function_arguments
1622 * Get a nicely-formatted list of arguments for a function.
1623 * This is everything that would go between the parentheses in
1627 pg_get_function_arguments(PG_FUNCTION_ARGS
)
1629 Oid funcid
= PG_GETARG_OID(0);
1633 initStringInfo(&buf
);
1635 proctup
= SearchSysCache(PROCOID
,
1636 ObjectIdGetDatum(funcid
),
1638 if (!HeapTupleIsValid(proctup
))
1639 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1641 (void) print_function_arguments(&buf
, proctup
, false, true);
1643 ReleaseSysCache(proctup
);
1645 PG_RETURN_TEXT_P(string_to_text(buf
.data
));
1649 * pg_get_function_identity_arguments
1650 * Get a formatted list of arguments for a function.
1651 * This is everything that would go between the parentheses in
1652 * ALTER FUNCTION, etc. In particular, don't print defaults.
1655 pg_get_function_identity_arguments(PG_FUNCTION_ARGS
)
1657 Oid funcid
= PG_GETARG_OID(0);
1661 initStringInfo(&buf
);
1663 proctup
= SearchSysCache(PROCOID
,
1664 ObjectIdGetDatum(funcid
),
1666 if (!HeapTupleIsValid(proctup
))
1667 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1669 (void) print_function_arguments(&buf
, proctup
, false, false);
1671 ReleaseSysCache(proctup
);
1673 PG_RETURN_TEXT_P(string_to_text(buf
.data
));
1677 * pg_get_function_result
1678 * Get a nicely-formatted version of the result type of a function.
1679 * This is what would appear after RETURNS in CREATE FUNCTION.
1682 pg_get_function_result(PG_FUNCTION_ARGS
)
1684 Oid funcid
= PG_GETARG_OID(0);
1688 initStringInfo(&buf
);
1690 proctup
= SearchSysCache(PROCOID
,
1691 ObjectIdGetDatum(funcid
),
1693 if (!HeapTupleIsValid(proctup
))
1694 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1696 print_function_rettype(&buf
, proctup
);
1698 ReleaseSysCache(proctup
);
1700 PG_RETURN_TEXT_P(string_to_text(buf
.data
));
1704 * Guts of pg_get_function_result: append the function's return type
1705 * to the specified buffer.
1708 print_function_rettype(StringInfo buf
, HeapTuple proctup
)
1710 Form_pg_proc proc
= (Form_pg_proc
) GETSTRUCT(proctup
);
1712 StringInfoData rbuf
;
1714 initStringInfo(&rbuf
);
1716 if (proc
->proretset
)
1718 /* It might be a table function; try to print the arguments */
1719 appendStringInfoString(&rbuf
, "TABLE(");
1720 ntabargs
= print_function_arguments(&rbuf
, proctup
, true, false);
1722 appendStringInfoString(&rbuf
, ")");
1724 resetStringInfo(&rbuf
);
1729 /* Not a table function, so do the normal thing */
1730 if (proc
->proretset
)
1731 appendStringInfoString(&rbuf
, "SETOF ");
1732 appendStringInfoString(&rbuf
, format_type_be(proc
->prorettype
));
1735 appendStringInfoString(buf
, rbuf
.data
);
1739 * Common code for pg_get_function_arguments and pg_get_function_result:
1740 * append the desired subset of arguments to buf. We print only TABLE
1741 * arguments when print_table_args is true, and all the others when it's false.
1742 * We print argument defaults only if print_defaults is true.
1743 * Function return value is the number of arguments printed.
1746 print_function_arguments(StringInfo buf
, HeapTuple proctup
,
1747 bool print_table_args
, bool print_defaults
)
1749 Form_pg_proc proc
= (Form_pg_proc
) GETSTRUCT(proctup
);
1757 ListCell
*nextargdefault
= NULL
;
1760 numargs
= get_func_arg_info(proctup
,
1761 &argtypes
, &argnames
, &argmodes
);
1763 nlackdefaults
= numargs
;
1764 if (print_defaults
&& proc
->pronargdefaults
> 0)
1766 Datum proargdefaults
;
1769 proargdefaults
= SysCacheGetAttr(PROCOID
, proctup
,
1770 Anum_pg_proc_proargdefaults
,
1777 str
= TextDatumGetCString(proargdefaults
);
1778 argdefaults
= (List
*) stringToNode(str
);
1779 Assert(IsA(argdefaults
, List
));
1781 nextargdefault
= list_head(argdefaults
);
1782 /* nlackdefaults counts only *input* arguments lacking defaults */
1783 nlackdefaults
= proc
->pronargs
- list_length(argdefaults
);
1789 for (i
= 0; i
< numargs
; i
++)
1791 Oid argtype
= argtypes
[i
];
1792 char *argname
= argnames
? argnames
[i
] : NULL
;
1793 char argmode
= argmodes
? argmodes
[i
] : PROARGMODE_IN
;
1794 const char *modename
;
1803 case PROARGMODE_INOUT
:
1804 modename
= "INOUT ";
1807 case PROARGMODE_OUT
:
1811 case PROARGMODE_VARIADIC
:
1812 modename
= "VARIADIC ";
1815 case PROARGMODE_TABLE
:
1820 elog(ERROR
, "invalid parameter mode '%c'", argmode
);
1821 modename
= NULL
; /* keep compiler quiet */
1826 inputargno
++; /* this is a 1-based counter */
1828 if (print_table_args
!= (argmode
== PROARGMODE_TABLE
))
1832 appendStringInfoString(buf
, ", ");
1833 appendStringInfoString(buf
, modename
);
1834 if (argname
&& argname
[0])
1835 appendStringInfo(buf
, "%s ", quote_identifier(argname
));
1836 appendStringInfoString(buf
, format_type_be(argtype
));
1837 if (print_defaults
&& isinput
&& inputargno
> nlackdefaults
)
1841 Assert(nextargdefault
!= NULL
);
1842 expr
= (Node
*) lfirst(nextargdefault
);
1843 nextargdefault
= lnext(nextargdefault
);
1845 appendStringInfo(buf
, " DEFAULT %s",
1846 deparse_expression(expr
, NIL
, false, false));
1856 * deparse_expression - General utility for deparsing expressions
1858 * calls deparse_expression_pretty with all prettyPrinting disabled
1861 deparse_expression(Node
*expr
, List
*dpcontext
,
1862 bool forceprefix
, bool showimplicit
)
1864 return deparse_expression_pretty(expr
, dpcontext
, forceprefix
,
1865 showimplicit
, 0, 0);
1869 * deparse_expression_pretty - General utility for deparsing expressions
1871 * expr is the node tree to be deparsed. It must be a transformed expression
1872 * tree (ie, not the raw output of gram.y).
1874 * dpcontext is a list of deparse_namespace nodes representing the context
1875 * for interpreting Vars in the node tree.
1877 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1879 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1881 * tries to pretty up the output according to prettyFlags and startIndent.
1883 * The result is a palloc'd string.
1887 deparse_expression_pretty(Node
*expr
, List
*dpcontext
,
1888 bool forceprefix
, bool showimplicit
,
1889 int prettyFlags
, int startIndent
)
1892 deparse_context context
;
1894 initStringInfo(&buf
);
1896 context
.namespaces
= dpcontext
;
1897 context
.windowClause
= NIL
;
1898 context
.windowTList
= NIL
;
1899 context
.varprefix
= forceprefix
;
1900 context
.prettyFlags
= prettyFlags
;
1901 context
.indentLevel
= startIndent
;
1903 get_rule_expr(expr
, &context
, showimplicit
);
1909 * deparse_context_for - Build deparse context for a single relation
1911 * Given the reference name (alias) and OID of a relation, build deparsing
1912 * context for an expression referencing only that relation (as varno 1,
1913 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1917 deparse_context_for(const char *aliasname
, Oid relid
)
1919 deparse_namespace
*dpns
;
1922 dpns
= (deparse_namespace
*) palloc(sizeof(deparse_namespace
));
1924 /* Build a minimal RTE for the rel */
1925 rte
= makeNode(RangeTblEntry
);
1926 rte
->rtekind
= RTE_RELATION
;
1928 rte
->eref
= makeAlias(aliasname
, NIL
);
1930 rte
->inFromCl
= true;
1932 /* Build one-element rtable */
1933 dpns
->rtable
= list_make1(rte
);
1935 dpns
->subplans
= NIL
;
1936 dpns
->outer_plan
= dpns
->inner_plan
= NULL
;
1938 /* Return a one-deep namespace stack */
1939 return list_make1(dpns
);
1943 * deparse_context_for_plan - Build deparse context for a plan node
1945 * When deparsing an expression in a Plan tree, we might have to resolve
1946 * OUTER or INNER references. To do this, the caller must provide the
1947 * parent Plan node. In the normal case of a join plan node, OUTER and
1948 * INNER references can be resolved by drilling down into the left and
1949 * right child plans. A special case is that a nestloop inner indexscan
1950 * might have OUTER Vars, but the outer side of the join is not a child
1951 * plan node. To handle such cases the outer plan node must be passed
1952 * separately. (Pass NULL for outer_plan otherwise.)
1954 * Note: plan and outer_plan really ought to be declared as "Plan *", but
1955 * we use "Node *" to avoid having to include plannodes.h in builtins.h.
1957 * The plan's rangetable list must also be passed. We actually prefer to use
1958 * the rangetable to resolve simple Vars, but the plan inputs are necessary
1959 * for Vars that reference expressions computed in subplan target lists.
1961 * We also need the list of subplans associated with the Plan tree; this
1962 * is for resolving references to CTE subplans.
1965 deparse_context_for_plan(Node
*plan
, Node
*outer_plan
,
1966 List
*rtable
, List
*subplans
)
1968 deparse_namespace
*dpns
;
1970 dpns
= (deparse_namespace
*) palloc(sizeof(deparse_namespace
));
1972 dpns
->rtable
= rtable
;
1974 dpns
->subplans
= subplans
;
1977 * Set up outer_plan and inner_plan from the Plan node (this includes
1978 * various special cases for particular Plan types).
1980 push_plan(dpns
, (Plan
*) plan
);
1983 * If outer_plan is given, that overrides whatever we got from the plan.
1986 dpns
->outer_plan
= (Plan
*) outer_plan
;
1988 /* Return a one-deep namespace stack */
1989 return list_make1(dpns
);
1993 * make_ruledef - reconstruct the CREATE RULE command
1994 * for a given pg_rewrite tuple
1998 make_ruledef(StringInfo buf
, HeapTuple ruletup
, TupleDesc rulettc
,
2008 List
*actions
= NIL
;
2014 * Get the attribute values from the rules tuple
2016 fno
= SPI_fnumber(rulettc
, "rulename");
2017 dat
= SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2019 rulename
= NameStr(*(DatumGetName(dat
)));
2021 fno
= SPI_fnumber(rulettc
, "ev_type");
2022 dat
= SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2024 ev_type
= DatumGetChar(dat
);
2026 fno
= SPI_fnumber(rulettc
, "ev_class");
2027 dat
= SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2029 ev_class
= DatumGetObjectId(dat
);
2031 fno
= SPI_fnumber(rulettc
, "ev_attr");
2032 dat
= SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2034 ev_attr
= DatumGetInt16(dat
);
2036 fno
= SPI_fnumber(rulettc
, "is_instead");
2037 dat
= SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2039 is_instead
= DatumGetBool(dat
);
2041 /* these could be nulls */
2042 fno
= SPI_fnumber(rulettc
, "ev_qual");
2043 ev_qual
= SPI_getvalue(ruletup
, rulettc
, fno
);
2045 fno
= SPI_fnumber(rulettc
, "ev_action");
2046 ev_action
= SPI_getvalue(ruletup
, rulettc
, fno
);
2047 if (ev_action
!= NULL
)
2048 actions
= (List
*) stringToNode(ev_action
);
2051 * Build the rules definition text
2053 appendStringInfo(buf
, "CREATE RULE %s AS",
2054 quote_identifier(rulename
));
2056 if (prettyFlags
& PRETTYFLAG_INDENT
)
2057 appendStringInfoString(buf
, "\n ON ");
2059 appendStringInfoString(buf
, " ON ");
2061 /* The event the rule is fired for */
2065 appendStringInfo(buf
, "SELECT");
2069 appendStringInfo(buf
, "UPDATE");
2073 appendStringInfo(buf
, "INSERT");
2077 appendStringInfo(buf
, "DELETE");
2082 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
2083 errmsg("rule \"%s\" has unsupported event type %d",
2084 rulename
, ev_type
)));
2088 /* The relation the rule is fired on */
2089 appendStringInfo(buf
, " TO %s", generate_relation_name(ev_class
, NIL
));
2091 appendStringInfo(buf
, ".%s",
2092 quote_identifier(get_relid_attribute_name(ev_class
,
2095 /* If the rule has an event qualification, add it */
2096 if (ev_qual
== NULL
)
2098 if (strlen(ev_qual
) > 0 && strcmp(ev_qual
, "<>") != 0)
2102 deparse_context context
;
2103 deparse_namespace dpns
;
2105 if (prettyFlags
& PRETTYFLAG_INDENT
)
2106 appendStringInfoString(buf
, "\n ");
2107 appendStringInfo(buf
, " WHERE ");
2109 qual
= stringToNode(ev_qual
);
2112 * We need to make a context for recognizing any Vars in the qual
2113 * (which can only be references to OLD and NEW). Use the rtable of
2114 * the first query in the action list for this purpose.
2116 query
= (Query
*) linitial(actions
);
2119 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2120 * into the SELECT, and that's what we need to look at. (Ugly kluge
2121 * ... try to fix this when we redesign querytrees.)
2123 query
= getInsertSelectQuery(query
, NULL
);
2125 /* Must acquire locks right away; see notes in get_query_def() */
2126 AcquireRewriteLocks(query
);
2129 context
.namespaces
= list_make1(&dpns
);
2130 context
.windowClause
= NIL
;
2131 context
.windowTList
= NIL
;
2132 context
.varprefix
= (list_length(query
->rtable
) != 1);
2133 context
.prettyFlags
= prettyFlags
;
2134 context
.indentLevel
= PRETTYINDENT_STD
;
2135 dpns
.rtable
= query
->rtable
;
2136 dpns
.ctes
= query
->cteList
;
2137 dpns
.subplans
= NIL
;
2138 dpns
.outer_plan
= dpns
.inner_plan
= NULL
;
2140 get_rule_expr(qual
, &context
, false);
2143 appendStringInfo(buf
, " DO ");
2145 /* The INSTEAD keyword (if so) */
2147 appendStringInfo(buf
, "INSTEAD ");
2149 /* Finally the rules actions */
2150 if (list_length(actions
) > 1)
2155 appendStringInfo(buf
, "(");
2156 foreach(action
, actions
)
2158 query
= (Query
*) lfirst(action
);
2159 get_query_def(query
, buf
, NIL
, NULL
, prettyFlags
, 0);
2161 appendStringInfo(buf
, ";\n");
2163 appendStringInfo(buf
, "; ");
2165 appendStringInfo(buf
, ");");
2167 else if (list_length(actions
) == 0)
2169 appendStringInfo(buf
, "NOTHING;");
2175 query
= (Query
*) linitial(actions
);
2176 get_query_def(query
, buf
, NIL
, NULL
, prettyFlags
, 0);
2177 appendStringInfo(buf
, ";");
2183 * make_viewdef - reconstruct the SELECT part of a
2188 make_viewdef(StringInfo buf
, HeapTuple ruletup
, TupleDesc rulettc
,
2198 List
*actions
= NIL
;
2199 Relation ev_relation
;
2204 * Get the attribute values from the rules tuple
2206 fno
= SPI_fnumber(rulettc
, "ev_type");
2207 ev_type
= (char) SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2209 fno
= SPI_fnumber(rulettc
, "ev_class");
2210 ev_class
= (Oid
) SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2212 fno
= SPI_fnumber(rulettc
, "ev_attr");
2213 ev_attr
= (int2
) SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2215 fno
= SPI_fnumber(rulettc
, "is_instead");
2216 is_instead
= (bool) SPI_getbinval(ruletup
, rulettc
, fno
, &isnull
);
2218 fno
= SPI_fnumber(rulettc
, "ev_qual");
2219 ev_qual
= SPI_getvalue(ruletup
, rulettc
, fno
);
2221 fno
= SPI_fnumber(rulettc
, "ev_action");
2222 ev_action
= SPI_getvalue(ruletup
, rulettc
, fno
);
2223 if (ev_action
!= NULL
)
2224 actions
= (List
*) stringToNode(ev_action
);
2226 if (list_length(actions
) != 1)
2228 appendStringInfo(buf
, "Not a view");
2232 query
= (Query
*) linitial(actions
);
2234 if (ev_type
!= '1' || ev_attr
>= 0 || !is_instead
||
2235 strcmp(ev_qual
, "<>") != 0 || query
->commandType
!= CMD_SELECT
)
2237 appendStringInfo(buf
, "Not a view");
2241 ev_relation
= heap_open(ev_class
, AccessShareLock
);
2243 get_query_def(query
, buf
, NIL
, RelationGetDescr(ev_relation
),
2245 appendStringInfo(buf
, ";");
2247 heap_close(ev_relation
, AccessShareLock
);
2252 * get_query_def - Parse back one query parsetree
2254 * If resultDesc is not NULL, then it is the output tuple descriptor for
2255 * the view represented by a SELECT query.
2259 get_query_def(Query
*query
, StringInfo buf
, List
*parentnamespace
,
2260 TupleDesc resultDesc
, int prettyFlags
, int startIndent
)
2262 deparse_context context
;
2263 deparse_namespace dpns
;
2266 * Before we begin to examine the query, acquire locks on referenced
2267 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2268 * consistent results. Note we assume it's OK to scribble on the passed
2271 AcquireRewriteLocks(query
);
2274 context
.namespaces
= lcons(&dpns
, list_copy(parentnamespace
));
2275 context
.windowClause
= NIL
;
2276 context
.windowTList
= NIL
;
2277 context
.varprefix
= (parentnamespace
!= NIL
||
2278 list_length(query
->rtable
) != 1);
2279 context
.prettyFlags
= prettyFlags
;
2280 context
.indentLevel
= startIndent
;
2282 dpns
.rtable
= query
->rtable
;
2283 dpns
.ctes
= query
->cteList
;
2284 dpns
.subplans
= NIL
;
2285 dpns
.outer_plan
= dpns
.inner_plan
= NULL
;
2287 switch (query
->commandType
)
2290 get_select_query_def(query
, &context
, resultDesc
);
2294 get_update_query_def(query
, &context
);
2298 get_insert_query_def(query
, &context
);
2302 get_delete_query_def(query
, &context
);
2306 appendStringInfo(buf
, "NOTHING");
2310 get_utility_query_def(query
, &context
);
2314 elog(ERROR
, "unrecognized query command type: %d",
2315 query
->commandType
);
2321 * get_values_def - Parse back a VALUES list
2325 get_values_def(List
*values_lists
, deparse_context
*context
)
2327 StringInfo buf
= context
->buf
;
2328 bool first_list
= true;
2331 appendStringInfoString(buf
, "VALUES ");
2333 foreach(vtl
, values_lists
)
2335 List
*sublist
= (List
*) lfirst(vtl
);
2336 bool first_col
= true;
2342 appendStringInfoString(buf
, ", ");
2344 appendStringInfoChar(buf
, '(');
2345 foreach(lc
, sublist
)
2347 Node
*col
= (Node
*) lfirst(lc
);
2352 appendStringInfoChar(buf
, ',');
2355 * Strip any top-level nodes representing indirection assignments,
2356 * then print the result.
2358 get_rule_expr(processIndirection(col
, context
, false),
2361 appendStringInfoChar(buf
, ')');
2366 * get_with_clause - Parse back a WITH clause
2370 get_with_clause(Query
*query
, deparse_context
*context
)
2372 StringInfo buf
= context
->buf
;
2376 if (query
->cteList
== NIL
)
2379 if (PRETTY_INDENT(context
))
2381 context
->indentLevel
+= PRETTYINDENT_STD
;
2382 appendStringInfoChar(buf
, ' ');
2385 if (query
->hasRecursive
)
2386 sep
= "WITH RECURSIVE ";
2389 foreach(l
, query
->cteList
)
2391 CommonTableExpr
*cte
= (CommonTableExpr
*) lfirst(l
);
2393 appendStringInfoString(buf
, sep
);
2394 appendStringInfoString(buf
, quote_identifier(cte
->ctename
));
2395 if (cte
->aliascolnames
)
2400 appendStringInfoChar(buf
, '(');
2401 foreach(col
, cte
->aliascolnames
)
2406 appendStringInfoString(buf
, ", ");
2407 appendStringInfoString(buf
,
2408 quote_identifier(strVal(lfirst(col
))));
2410 appendStringInfoChar(buf
, ')');
2412 appendStringInfoString(buf
, " AS (");
2413 if (PRETTY_INDENT(context
))
2414 appendContextKeyword(context
, "", 0, 0, 0);
2415 get_query_def((Query
*) cte
->ctequery
, buf
, context
->namespaces
, NULL
,
2416 context
->prettyFlags
, context
->indentLevel
);
2417 if (PRETTY_INDENT(context
))
2418 appendContextKeyword(context
, "", 0, 0, 0);
2419 appendStringInfoChar(buf
, ')');
2423 if (PRETTY_INDENT(context
))
2425 context
->indentLevel
-= PRETTYINDENT_STD
;
2426 appendContextKeyword(context
, "", 0, 0, 0);
2429 appendStringInfoChar(buf
, ' ');
2433 * get_select_query_def - Parse back a SELECT parsetree
2437 get_select_query_def(Query
*query
, deparse_context
*context
,
2438 TupleDesc resultDesc
)
2440 StringInfo buf
= context
->buf
;
2441 List
*save_windowclause
;
2442 List
*save_windowtlist
;
2446 /* Insert the WITH clause if given */
2447 get_with_clause(query
, context
);
2449 /* Set up context for possible window functions */
2450 save_windowclause
= context
->windowClause
;
2451 context
->windowClause
= query
->windowClause
;
2452 save_windowtlist
= context
->windowTList
;
2453 context
->windowTList
= query
->targetList
;
2456 * If the Query node has a setOperations tree, then it's the top level of
2457 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2458 * fields are interesting in the top query itself.
2460 if (query
->setOperations
)
2462 get_setop_query(query
->setOperations
, query
, context
, resultDesc
);
2463 /* ORDER BY clauses must be simple in this case */
2468 get_basic_select_query(query
, context
, resultDesc
);
2469 force_colno
= false;
2472 /* Add the ORDER BY clause if given */
2473 if (query
->sortClause
!= NIL
)
2475 appendContextKeyword(context
, " ORDER BY ",
2476 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
2477 get_rule_orderby(query
->sortClause
, query
->targetList
,
2478 force_colno
, context
);
2481 /* Add the LIMIT clause if given */
2482 if (query
->limitOffset
!= NULL
)
2484 appendContextKeyword(context
, " OFFSET ",
2485 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2486 get_rule_expr(query
->limitOffset
, context
, false);
2488 if (query
->limitCount
!= NULL
)
2490 appendContextKeyword(context
, " LIMIT ",
2491 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2492 if (IsA(query
->limitCount
, Const
) &&
2493 ((Const
*) query
->limitCount
)->constisnull
)
2494 appendStringInfo(buf
, "ALL");
2496 get_rule_expr(query
->limitCount
, context
, false);
2499 /* Add FOR UPDATE/SHARE clauses if present */
2500 foreach(l
, query
->rowMarks
)
2502 RowMarkClause
*rc
= (RowMarkClause
*) lfirst(l
);
2503 RangeTblEntry
*rte
= rt_fetch(rc
->rti
, query
->rtable
);
2506 appendContextKeyword(context
, " FOR UPDATE",
2507 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2509 appendContextKeyword(context
, " FOR SHARE",
2510 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2511 appendStringInfo(buf
, " OF %s",
2512 quote_identifier(rte
->eref
->aliasname
));
2514 appendStringInfo(buf
, " NOWAIT");
2517 context
->windowClause
= save_windowclause
;
2518 context
->windowTList
= save_windowtlist
;
2522 get_basic_select_query(Query
*query
, deparse_context
*context
,
2523 TupleDesc resultDesc
)
2525 StringInfo buf
= context
->buf
;
2529 if (PRETTY_INDENT(context
))
2531 context
->indentLevel
+= PRETTYINDENT_STD
;
2532 appendStringInfoChar(buf
, ' ');
2536 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2537 * VALUES part. This reverses what transformValuesClause() did at parse
2538 * time. If the jointree contains just a single VALUES RTE, we assume
2539 * this case applies (without looking at the targetlist...)
2541 if (list_length(query
->jointree
->fromlist
) == 1)
2543 RangeTblRef
*rtr
= (RangeTblRef
*) linitial(query
->jointree
->fromlist
);
2545 if (IsA(rtr
, RangeTblRef
))
2547 RangeTblEntry
*rte
= rt_fetch(rtr
->rtindex
, query
->rtable
);
2549 if (rte
->rtekind
== RTE_VALUES
)
2551 get_values_def(rte
->values_lists
, context
);
2558 * Build up the query string - first we say SELECT
2560 appendStringInfo(buf
, "SELECT");
2562 /* Add the DISTINCT clause if given */
2563 if (query
->distinctClause
!= NIL
)
2565 if (query
->hasDistinctOn
)
2567 appendStringInfo(buf
, " DISTINCT ON (");
2569 foreach(l
, query
->distinctClause
)
2571 SortGroupClause
*srt
= (SortGroupClause
*) lfirst(l
);
2573 appendStringInfoString(buf
, sep
);
2574 get_rule_sortgroupclause(srt
, query
->targetList
,
2578 appendStringInfo(buf
, ")");
2581 appendStringInfo(buf
, " DISTINCT");
2584 /* Then we tell what to select (the targetlist) */
2585 get_target_list(query
->targetList
, context
, resultDesc
);
2587 /* Add the FROM clause if needed */
2588 get_from_clause(query
, " FROM ", context
);
2590 /* Add the WHERE clause if given */
2591 if (query
->jointree
->quals
!= NULL
)
2593 appendContextKeyword(context
, " WHERE ",
2594 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
2595 get_rule_expr(query
->jointree
->quals
, context
, false);
2598 /* Add the GROUP BY clause if given */
2599 if (query
->groupClause
!= NULL
)
2601 appendContextKeyword(context
, " GROUP BY ",
2602 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
2604 foreach(l
, query
->groupClause
)
2606 SortGroupClause
*grp
= (SortGroupClause
*) lfirst(l
);
2608 appendStringInfoString(buf
, sep
);
2609 get_rule_sortgroupclause(grp
, query
->targetList
,
2615 /* Add the HAVING clause if given */
2616 if (query
->havingQual
!= NULL
)
2618 appendContextKeyword(context
, " HAVING ",
2619 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2620 get_rule_expr(query
->havingQual
, context
, false);
2623 /* Add the WINDOW clause if needed */
2624 if (query
->windowClause
!= NIL
)
2625 get_rule_windowclause(query
, context
);
2629 * get_target_list - Parse back a SELECT target list
2631 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2635 get_target_list(List
*targetList
, deparse_context
*context
,
2636 TupleDesc resultDesc
)
2638 StringInfo buf
= context
->buf
;
2645 foreach(l
, targetList
)
2647 TargetEntry
*tle
= (TargetEntry
*) lfirst(l
);
2652 continue; /* ignore junk entries */
2654 appendStringInfoString(buf
, sep
);
2659 * We special-case Var nodes rather than using get_rule_expr. This is
2660 * needed because get_rule_expr will display a whole-row Var as
2661 * "foo.*", which is the preferred notation in most contexts, but at
2662 * the top level of a SELECT list it's not right (the parser will
2663 * expand that notation into multiple columns, yielding behavior
2664 * different from a whole-row Var). We want just "foo", instead.
2666 if (tle
->expr
&& IsA(tle
->expr
, Var
))
2668 attname
= get_variable((Var
*) tle
->expr
, 0, false, context
);
2672 get_rule_expr((Node
*) tle
->expr
, context
, true);
2673 /* We'll show the AS name unless it's this: */
2674 attname
= "?column?";
2678 * Figure out what the result column should be called. In the context
2679 * of a view, use the view's tuple descriptor (so as to pick up the
2680 * effects of any column RENAME that's been done on the view).
2681 * Otherwise, just use what we can find in the TLE.
2683 if (resultDesc
&& colno
<= resultDesc
->natts
)
2684 colname
= NameStr(resultDesc
->attrs
[colno
- 1]->attname
);
2686 colname
= tle
->resname
;
2688 /* Show AS unless the column's name is correct as-is */
2689 if (colname
) /* resname could be NULL */
2691 if (attname
== NULL
|| strcmp(attname
, colname
) != 0)
2692 appendStringInfo(buf
, " AS %s", quote_identifier(colname
));
2698 get_setop_query(Node
*setOp
, Query
*query
, deparse_context
*context
,
2699 TupleDesc resultDesc
)
2701 StringInfo buf
= context
->buf
;
2704 if (IsA(setOp
, RangeTblRef
))
2706 RangeTblRef
*rtr
= (RangeTblRef
*) setOp
;
2707 RangeTblEntry
*rte
= rt_fetch(rtr
->rtindex
, query
->rtable
);
2708 Query
*subquery
= rte
->subquery
;
2710 Assert(subquery
!= NULL
);
2711 Assert(subquery
->setOperations
== NULL
);
2712 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2713 need_paren
= (subquery
->cteList
||
2714 subquery
->sortClause
||
2715 subquery
->rowMarks
||
2716 subquery
->limitOffset
||
2717 subquery
->limitCount
);
2719 appendStringInfoChar(buf
, '(');
2720 get_query_def(subquery
, buf
, context
->namespaces
, resultDesc
,
2721 context
->prettyFlags
, context
->indentLevel
);
2723 appendStringInfoChar(buf
, ')');
2725 else if (IsA(setOp
, SetOperationStmt
))
2727 SetOperationStmt
*op
= (SetOperationStmt
*) setOp
;
2729 if (PRETTY_INDENT(context
))
2731 context
->indentLevel
+= PRETTYINDENT_STD
;
2732 appendStringInfoSpaces(buf
, PRETTYINDENT_STD
);
2736 * We force parens whenever nesting two SetOperationStmts. There are
2737 * some cases in which parens are needed around a leaf query too, but
2738 * those are more easily handled at the next level down (see code
2741 need_paren
= !IsA(op
->larg
, RangeTblRef
);
2744 appendStringInfoChar(buf
, '(');
2745 get_setop_query(op
->larg
, query
, context
, resultDesc
);
2747 appendStringInfoChar(buf
, ')');
2749 if (!PRETTY_INDENT(context
))
2750 appendStringInfoChar(buf
, ' ');
2754 appendContextKeyword(context
, "UNION ",
2755 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2757 case SETOP_INTERSECT
:
2758 appendContextKeyword(context
, "INTERSECT ",
2759 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2762 appendContextKeyword(context
, "EXCEPT ",
2763 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 0);
2766 elog(ERROR
, "unrecognized set op: %d",
2770 appendStringInfo(buf
, "ALL ");
2772 if (PRETTY_INDENT(context
))
2773 appendContextKeyword(context
, "", 0, 0, 0);
2775 need_paren
= !IsA(op
->rarg
, RangeTblRef
);
2778 appendStringInfoChar(buf
, '(');
2779 get_setop_query(op
->rarg
, query
, context
, resultDesc
);
2781 appendStringInfoChar(buf
, ')');
2783 if (PRETTY_INDENT(context
))
2784 context
->indentLevel
-= PRETTYINDENT_STD
;
2788 elog(ERROR
, "unrecognized node type: %d",
2789 (int) nodeTag(setOp
));
2794 * Display a sort/group clause.
2796 * Also returns the expression tree, so caller need not find it again.
2799 get_rule_sortgroupclause(SortGroupClause
*srt
, List
*tlist
, bool force_colno
,
2800 deparse_context
*context
)
2802 StringInfo buf
= context
->buf
;
2806 tle
= get_sortgroupclause_tle(srt
, tlist
);
2807 expr
= (Node
*) tle
->expr
;
2810 * Use column-number form if requested by caller. Otherwise, if
2811 * expression is a constant, force it to be dumped with an explicit
2812 * cast as decoration --- this is because a simple integer constant
2813 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2814 * if we dump it without any decoration. Otherwise, just dump the
2815 * expression normally.
2819 Assert(!tle
->resjunk
);
2820 appendStringInfo(buf
, "%d", tle
->resno
);
2822 else if (expr
&& IsA(expr
, Const
))
2823 get_const_expr((Const
*) expr
, context
, 1);
2825 get_rule_expr(expr
, context
, true);
2831 * Display an ORDER BY list.
2834 get_rule_orderby(List
*orderList
, List
*targetList
,
2835 bool force_colno
, deparse_context
*context
)
2837 StringInfo buf
= context
->buf
;
2842 foreach(l
, orderList
)
2844 SortGroupClause
*srt
= (SortGroupClause
*) lfirst(l
);
2847 TypeCacheEntry
*typentry
;
2849 appendStringInfoString(buf
, sep
);
2850 sortexpr
= get_rule_sortgroupclause(srt
, targetList
,
2851 force_colno
, context
);
2852 sortcoltype
= exprType(sortexpr
);
2853 /* See whether operator is default < or > for datatype */
2854 typentry
= lookup_type_cache(sortcoltype
,
2855 TYPECACHE_LT_OPR
| TYPECACHE_GT_OPR
);
2856 if (srt
->sortop
== typentry
->lt_opr
)
2858 /* ASC is default, so emit nothing for it */
2859 if (srt
->nulls_first
)
2860 appendStringInfo(buf
, " NULLS FIRST");
2862 else if (srt
->sortop
== typentry
->gt_opr
)
2864 appendStringInfo(buf
, " DESC");
2865 /* DESC defaults to NULLS FIRST */
2866 if (!srt
->nulls_first
)
2867 appendStringInfo(buf
, " NULLS LAST");
2871 appendStringInfo(buf
, " USING %s",
2872 generate_operator_name(srt
->sortop
,
2875 /* be specific to eliminate ambiguity */
2876 if (srt
->nulls_first
)
2877 appendStringInfo(buf
, " NULLS FIRST");
2879 appendStringInfo(buf
, " NULLS LAST");
2886 * Display a WINDOW clause.
2888 * Note that the windowClause list might contain only anonymous window
2889 * specifications, in which case we should print nothing here.
2892 get_rule_windowclause(Query
*query
, deparse_context
*context
)
2894 StringInfo buf
= context
->buf
;
2899 foreach(l
, query
->windowClause
)
2901 WindowClause
*wc
= (WindowClause
*) lfirst(l
);
2903 if (wc
->name
== NULL
)
2904 continue; /* ignore anonymous windows */
2907 appendContextKeyword(context
, " WINDOW ",
2908 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
2910 appendStringInfoString(buf
, sep
);
2912 appendStringInfo(buf
, "%s AS ", quote_identifier(wc
->name
));
2914 get_rule_windowspec(wc
, query
->targetList
, context
);
2921 * Display a window definition
2924 get_rule_windowspec(WindowClause
*wc
, List
*targetList
,
2925 deparse_context
*context
)
2927 StringInfo buf
= context
->buf
;
2928 bool needspace
= false;
2932 appendStringInfoChar(buf
, '(');
2935 appendStringInfoString(buf
, quote_identifier(wc
->refname
));
2938 /* partition clauses are always inherited, so only print if no refname */
2939 if (wc
->partitionClause
&& !wc
->refname
)
2942 appendStringInfoChar(buf
, ' ');
2943 appendStringInfoString(buf
, "PARTITION BY ");
2945 foreach(l
, wc
->partitionClause
)
2947 SortGroupClause
*grp
= (SortGroupClause
*) lfirst(l
);
2949 appendStringInfoString(buf
, sep
);
2950 get_rule_sortgroupclause(grp
, targetList
,
2956 /* print ordering clause only if not inherited */
2957 if (wc
->orderClause
&& !wc
->copiedOrder
)
2960 appendStringInfoChar(buf
, ' ');
2961 appendStringInfoString(buf
, "ORDER BY ");
2962 get_rule_orderby(wc
->orderClause
, targetList
, false, context
);
2965 /* framing clause is never inherited, so print unless it's default */
2966 if (wc
->frameOptions
& FRAMEOPTION_NONDEFAULT
)
2969 appendStringInfoChar(buf
, ' ');
2970 if (wc
->frameOptions
& FRAMEOPTION_RANGE
)
2971 appendStringInfoString(buf
, "RANGE ");
2972 else if (wc
->frameOptions
& FRAMEOPTION_ROWS
)
2973 appendStringInfoString(buf
, "ROWS ");
2976 if (wc
->frameOptions
& FRAMEOPTION_BETWEEN
)
2977 appendStringInfoString(buf
, "BETWEEN ");
2978 if (wc
->frameOptions
& FRAMEOPTION_START_UNBOUNDED_PRECEDING
)
2979 appendStringInfoString(buf
, "UNBOUNDED PRECEDING ");
2980 else if (wc
->frameOptions
& FRAMEOPTION_START_CURRENT_ROW
)
2981 appendStringInfoString(buf
, "CURRENT ROW ");
2984 if (wc
->frameOptions
& FRAMEOPTION_BETWEEN
)
2986 appendStringInfoString(buf
, "AND ");
2987 if (wc
->frameOptions
& FRAMEOPTION_END_UNBOUNDED_FOLLOWING
)
2988 appendStringInfoString(buf
, "UNBOUNDED FOLLOWING ");
2989 else if (wc
->frameOptions
& FRAMEOPTION_END_CURRENT_ROW
)
2990 appendStringInfoString(buf
, "CURRENT ROW ");
2994 /* we will now have a trailing space; remove it */
2997 appendStringInfoChar(buf
, ')');
3001 * get_insert_query_def - Parse back an INSERT parsetree
3005 get_insert_query_def(Query
*query
, deparse_context
*context
)
3007 StringInfo buf
= context
->buf
;
3008 RangeTblEntry
*select_rte
= NULL
;
3009 RangeTblEntry
*values_rte
= NULL
;
3012 ListCell
*values_cell
;
3014 List
*strippedexprs
;
3017 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
3018 * a single RTE for the SELECT or VALUES.
3020 foreach(l
, query
->rtable
)
3022 rte
= (RangeTblEntry
*) lfirst(l
);
3024 if (rte
->rtekind
== RTE_SUBQUERY
)
3027 elog(ERROR
, "too many subquery RTEs in INSERT");
3031 if (rte
->rtekind
== RTE_VALUES
)
3034 elog(ERROR
, "too many values RTEs in INSERT");
3038 if (select_rte
&& values_rte
)
3039 elog(ERROR
, "both subquery and values RTEs in INSERT");
3042 * Start the query with INSERT INTO relname
3044 rte
= rt_fetch(query
->resultRelation
, query
->rtable
);
3045 Assert(rte
->rtekind
== RTE_RELATION
);
3047 if (PRETTY_INDENT(context
))
3049 context
->indentLevel
+= PRETTYINDENT_STD
;
3050 appendStringInfoChar(buf
, ' ');
3052 appendStringInfo(buf
, "INSERT INTO %s (",
3053 generate_relation_name(rte
->relid
, NIL
));
3056 * Add the insert-column-names list. To handle indirection properly, we
3057 * need to look for indirection nodes in the top targetlist (if it's
3058 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3059 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3060 * assume that all the expression lists will have similar indirection in
3064 values_cell
= list_head((List
*) linitial(values_rte
->values_lists
));
3067 strippedexprs
= NIL
;
3069 foreach(l
, query
->targetList
)
3071 TargetEntry
*tle
= (TargetEntry
*) lfirst(l
);
3074 continue; /* ignore junk entries */
3076 appendStringInfoString(buf
, sep
);
3080 * Put out name of target column; look in the catalogs, not at
3081 * tle->resname, since resname will fail to track RENAME.
3083 appendStringInfoString(buf
,
3084 quote_identifier(get_relid_attribute_name(rte
->relid
,
3088 * Print any indirection needed (subfields or subscripts), and strip
3089 * off the top-level nodes representing the indirection assignments.
3093 /* we discard the stripped expression in this case */
3094 processIndirection((Node
*) lfirst(values_cell
), context
, true);
3095 values_cell
= lnext(values_cell
);
3099 /* we keep a list of the stripped expressions in this case */
3100 strippedexprs
= lappend(strippedexprs
,
3101 processIndirection((Node
*) tle
->expr
,
3105 appendStringInfo(buf
, ") ");
3109 /* Add the SELECT */
3110 get_query_def(select_rte
->subquery
, buf
, NIL
, NULL
,
3111 context
->prettyFlags
, context
->indentLevel
);
3113 else if (values_rte
)
3115 /* A WITH clause is possible here */
3116 get_with_clause(query
, context
);
3117 /* Add the multi-VALUES expression lists */
3118 get_values_def(values_rte
->values_lists
, context
);
3122 /* A WITH clause is possible here */
3123 get_with_clause(query
, context
);
3124 /* Add the single-VALUES expression list */
3125 appendContextKeyword(context
, "VALUES (",
3126 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 2);
3127 get_rule_expr((Node
*) strippedexprs
, context
, false);
3128 appendStringInfoChar(buf
, ')');
3131 /* Add RETURNING if present */
3132 if (query
->returningList
)
3134 appendContextKeyword(context
, " RETURNING",
3135 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
3136 get_target_list(query
->returningList
, context
, NULL
);
3142 * get_update_query_def - Parse back an UPDATE parsetree
3146 get_update_query_def(Query
*query
, deparse_context
*context
)
3148 StringInfo buf
= context
->buf
;
3154 * Start the query with UPDATE relname SET
3156 rte
= rt_fetch(query
->resultRelation
, query
->rtable
);
3157 Assert(rte
->rtekind
== RTE_RELATION
);
3158 if (PRETTY_INDENT(context
))
3160 appendStringInfoChar(buf
, ' ');
3161 context
->indentLevel
+= PRETTYINDENT_STD
;
3163 appendStringInfo(buf
, "UPDATE %s%s",
3165 generate_relation_name(rte
->relid
, NIL
));
3166 if (rte
->alias
!= NULL
)
3167 appendStringInfo(buf
, " %s",
3168 quote_identifier(rte
->alias
->aliasname
));
3169 appendStringInfoString(buf
, " SET ");
3171 /* Add the comma separated list of 'attname = value' */
3173 foreach(l
, query
->targetList
)
3175 TargetEntry
*tle
= (TargetEntry
*) lfirst(l
);
3179 continue; /* ignore junk entries */
3181 appendStringInfoString(buf
, sep
);
3185 * Put out name of target column; look in the catalogs, not at
3186 * tle->resname, since resname will fail to track RENAME.
3188 appendStringInfoString(buf
,
3189 quote_identifier(get_relid_attribute_name(rte
->relid
,
3193 * Print any indirection needed (subfields or subscripts), and strip
3194 * off the top-level nodes representing the indirection assignments.
3196 expr
= processIndirection((Node
*) tle
->expr
, context
, true);
3198 appendStringInfo(buf
, " = ");
3200 get_rule_expr(expr
, context
, false);
3203 /* Add the FROM clause if needed */
3204 get_from_clause(query
, " FROM ", context
);
3206 /* Add a WHERE clause if given */
3207 if (query
->jointree
->quals
!= NULL
)
3209 appendContextKeyword(context
, " WHERE ",
3210 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
3211 get_rule_expr(query
->jointree
->quals
, context
, false);
3214 /* Add RETURNING if present */
3215 if (query
->returningList
)
3217 appendContextKeyword(context
, " RETURNING",
3218 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
3219 get_target_list(query
->returningList
, context
, NULL
);
3225 * get_delete_query_def - Parse back a DELETE parsetree
3229 get_delete_query_def(Query
*query
, deparse_context
*context
)
3231 StringInfo buf
= context
->buf
;
3235 * Start the query with DELETE FROM relname
3237 rte
= rt_fetch(query
->resultRelation
, query
->rtable
);
3238 Assert(rte
->rtekind
== RTE_RELATION
);
3239 if (PRETTY_INDENT(context
))
3241 appendStringInfoChar(buf
, ' ');
3242 context
->indentLevel
+= PRETTYINDENT_STD
;
3244 appendStringInfo(buf
, "DELETE FROM %s%s",
3246 generate_relation_name(rte
->relid
, NIL
));
3247 if (rte
->alias
!= NULL
)
3248 appendStringInfo(buf
, " %s",
3249 quote_identifier(rte
->alias
->aliasname
));
3251 /* Add the USING clause if given */
3252 get_from_clause(query
, " USING ", context
);
3254 /* Add a WHERE clause if given */
3255 if (query
->jointree
->quals
!= NULL
)
3257 appendContextKeyword(context
, " WHERE ",
3258 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
3259 get_rule_expr(query
->jointree
->quals
, context
, false);
3262 /* Add RETURNING if present */
3263 if (query
->returningList
)
3265 appendContextKeyword(context
, " RETURNING",
3266 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 1);
3267 get_target_list(query
->returningList
, context
, NULL
);
3273 * get_utility_query_def - Parse back a UTILITY parsetree
3277 get_utility_query_def(Query
*query
, deparse_context
*context
)
3279 StringInfo buf
= context
->buf
;
3281 if (query
->utilityStmt
&& IsA(query
->utilityStmt
, NotifyStmt
))
3283 NotifyStmt
*stmt
= (NotifyStmt
*) query
->utilityStmt
;
3285 appendContextKeyword(context
, "",
3286 0, PRETTYINDENT_STD
, 1);
3287 appendStringInfo(buf
, "NOTIFY %s",
3288 quote_identifier(stmt
->conditionname
));
3292 /* Currently only NOTIFY utility commands can appear in rules */
3293 elog(ERROR
, "unexpected utility statement type");
3299 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3301 * When expanding an OUTER or INNER reference, we must push new outer/inner
3302 * subplans in case the referenced expression itself uses OUTER/INNER. We
3303 * modify the top stack entry in-place to avoid affecting levelsup issues
3304 * (although in a Plan tree there really shouldn't be any).
3306 * Caller must save and restore outer_plan and inner_plan around this.
3308 * We also use this to initialize the fields during deparse_context_for_plan.
3311 push_plan(deparse_namespace
*dpns
, Plan
*subplan
)
3314 * We special-case Append to pretend that the first child plan is the
3315 * OUTER referent; otherwise normal.
3317 if (IsA(subplan
, Append
))
3318 dpns
->outer_plan
= (Plan
*) linitial(((Append
*) subplan
)->appendplans
);
3320 dpns
->outer_plan
= outerPlan(subplan
);
3323 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3324 * use OUTER because that could someday conflict with the normal meaning.)
3325 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3327 if (IsA(subplan
, SubqueryScan
))
3328 dpns
->inner_plan
= ((SubqueryScan
*) subplan
)->subplan
;
3329 else if (IsA(subplan
, CteScan
))
3331 int ctePlanId
= ((CteScan
*) subplan
)->ctePlanId
;
3333 if (ctePlanId
> 0 && ctePlanId
<= list_length(dpns
->subplans
))
3334 dpns
->inner_plan
= list_nth(dpns
->subplans
, ctePlanId
- 1);
3336 dpns
->inner_plan
= NULL
;
3339 dpns
->inner_plan
= innerPlan(subplan
);
3344 * Display a Var appropriately.
3346 * In some cases (currently only when recursing into an unnamed join)
3347 * the Var's varlevelsup has to be interpreted with respect to a context
3348 * above the current one; levelsup indicates the offset.
3350 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3351 * if FALSE, merely as "foo".
3353 * Returns the attname of the Var, or NULL if not determinable.
3356 get_variable(Var
*var
, int levelsup
, bool showstar
, deparse_context
*context
)
3358 StringInfo buf
= context
->buf
;
3362 deparse_namespace
*dpns
;
3367 /* Find appropriate nesting depth */
3368 netlevelsup
= var
->varlevelsup
+ levelsup
;
3369 if (netlevelsup
>= list_length(context
->namespaces
))
3370 elog(ERROR
, "bogus varlevelsup: %d offset %d",
3371 var
->varlevelsup
, levelsup
);
3372 dpns
= (deparse_namespace
*) list_nth(context
->namespaces
,
3376 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3377 * likely that varno is OUTER or INNER, in which case we must dig down
3378 * into the subplans.
3380 if (var
->varno
>= 1 && var
->varno
<= list_length(dpns
->rtable
))
3382 rte
= rt_fetch(var
->varno
, dpns
->rtable
);
3383 attnum
= var
->varattno
;
3385 else if (var
->varno
== OUTER
&& dpns
->outer_plan
)
3391 tle
= get_tle_by_resno(dpns
->outer_plan
->targetlist
, var
->varattno
);
3393 elog(ERROR
, "bogus varattno for OUTER var: %d", var
->varattno
);
3395 Assert(netlevelsup
== 0);
3396 save_outer
= dpns
->outer_plan
;
3397 save_inner
= dpns
->inner_plan
;
3398 push_plan(dpns
, dpns
->outer_plan
);
3401 * Force parentheses because our caller probably assumed a Var is a
3402 * simple expression.
3404 if (!IsA(tle
->expr
, Var
))
3405 appendStringInfoChar(buf
, '(');
3406 get_rule_expr((Node
*) tle
->expr
, context
, true);
3407 if (!IsA(tle
->expr
, Var
))
3408 appendStringInfoChar(buf
, ')');
3410 dpns
->outer_plan
= save_outer
;
3411 dpns
->inner_plan
= save_inner
;
3414 else if (var
->varno
== INNER
&& dpns
->inner_plan
)
3420 tle
= get_tle_by_resno(dpns
->inner_plan
->targetlist
, var
->varattno
);
3422 elog(ERROR
, "bogus varattno for INNER var: %d", var
->varattno
);
3424 Assert(netlevelsup
== 0);
3425 save_outer
= dpns
->outer_plan
;
3426 save_inner
= dpns
->inner_plan
;
3427 push_plan(dpns
, dpns
->inner_plan
);
3430 * Force parentheses because our caller probably assumed a Var is a
3431 * simple expression.
3433 if (!IsA(tle
->expr
, Var
))
3434 appendStringInfoChar(buf
, '(');
3435 get_rule_expr((Node
*) tle
->expr
, context
, true);
3436 if (!IsA(tle
->expr
, Var
))
3437 appendStringInfoChar(buf
, ')');
3439 dpns
->outer_plan
= save_outer
;
3440 dpns
->inner_plan
= save_inner
;
3445 elog(ERROR
, "bogus varno: %d", var
->varno
);
3446 return NULL
; /* keep compiler quiet */
3449 /* Identify names to use */
3450 schemaname
= NULL
; /* default assumptions */
3451 refname
= rte
->eref
->aliasname
;
3453 /* Exceptions occur only if the RTE is alias-less */
3454 if (rte
->alias
== NULL
)
3456 if (rte
->rtekind
== RTE_RELATION
)
3459 * It's possible that use of the bare refname would find another
3460 * more-closely-nested RTE, or be ambiguous, in which case we need
3461 * to specify the schemaname to avoid these errors.
3463 if (find_rte_by_refname(rte
->eref
->aliasname
, context
) != rte
)
3464 schemaname
= get_namespace_name(get_rel_namespace(rte
->relid
));
3466 else if (rte
->rtekind
== RTE_JOIN
)
3469 * If it's an unnamed join, look at the expansion of the alias
3470 * variable. If it's a simple reference to one of the input vars
3471 * then recursively print the name of that var, instead. (This
3472 * allows correct decompiling of cases where there are identically
3473 * named columns on both sides of the join.) When it's not a
3474 * simple reference, we have to just print the unqualified
3475 * variable name (this can only happen with columns that were
3476 * merged by USING or NATURAL clauses).
3478 * This wouldn't work in decompiling plan trees, because we don't
3479 * store joinaliasvars lists after planning; but a plan tree
3480 * should never contain a join alias variable.
3482 if (rte
->joinaliasvars
== NIL
)
3483 elog(ERROR
, "cannot decompile join alias var in plan tree");
3488 aliasvar
= (Var
*) list_nth(rte
->joinaliasvars
, attnum
- 1);
3489 if (IsA(aliasvar
, Var
))
3491 return get_variable(aliasvar
, var
->varlevelsup
+ levelsup
,
3495 /* Unnamed join has neither schemaname nor refname */
3500 if (attnum
== InvalidAttrNumber
)
3503 attname
= get_rte_attribute_name(rte
, attnum
);
3505 if (refname
&& (context
->varprefix
|| attname
== NULL
))
3508 appendStringInfo(buf
, "%s.",
3509 quote_identifier(schemaname
));
3511 if (strcmp(refname
, "*NEW*") == 0)
3512 appendStringInfoString(buf
, "new");
3513 else if (strcmp(refname
, "*OLD*") == 0)
3514 appendStringInfoString(buf
, "old");
3516 appendStringInfoString(buf
, quote_identifier(refname
));
3518 if (attname
|| showstar
)
3519 appendStringInfoChar(buf
, '.');
3522 appendStringInfoString(buf
, quote_identifier(attname
));
3524 appendStringInfoChar(buf
, '*');
3531 * Get the name of a field of an expression of composite type.
3533 * This is fairly straightforward except for the case of a Var of type RECORD.
3534 * Since no actual table or view column is allowed to have type RECORD, such
3535 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3536 * drill down to find the ultimate defining expression and attempt to infer
3537 * the field name from it. We ereport if we can't determine the name.
3539 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3542 get_name_for_var_field(Var
*var
, int fieldno
,
3543 int levelsup
, deparse_context
*context
)
3548 deparse_namespace
*dpns
;
3549 TupleDesc tupleDesc
;
3553 * If it's a RowExpr that was expanded from a whole-row Var, use the
3554 * column names attached to it.
3556 if (IsA(var
, RowExpr
))
3558 RowExpr
*r
= (RowExpr
*) var
;
3560 if (fieldno
> 0 && fieldno
<= list_length(r
->colnames
))
3561 return strVal(list_nth(r
->colnames
, fieldno
- 1));
3565 * If it's a Var of type RECORD, we have to find what the Var refers to;
3566 * if not, we can use get_expr_result_type. If that fails, we try
3567 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3568 * an acceptable message.
3570 if (!IsA(var
, Var
) ||
3571 var
->vartype
!= RECORDOID
)
3573 if (get_expr_result_type((Node
*) var
, NULL
, &tupleDesc
) != TYPEFUNC_COMPOSITE
)
3574 tupleDesc
= lookup_rowtype_tupdesc_copy(exprType((Node
*) var
),
3575 exprTypmod((Node
*) var
));
3577 /* Got the tupdesc, so we can extract the field name */
3578 Assert(fieldno
>= 1 && fieldno
<= tupleDesc
->natts
);
3579 return NameStr(tupleDesc
->attrs
[fieldno
- 1]->attname
);
3582 /* Find appropriate nesting depth */
3583 netlevelsup
= var
->varlevelsup
+ levelsup
;
3584 if (netlevelsup
>= list_length(context
->namespaces
))
3585 elog(ERROR
, "bogus varlevelsup: %d offset %d",
3586 var
->varlevelsup
, levelsup
);
3587 dpns
= (deparse_namespace
*) list_nth(context
->namespaces
,
3591 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3592 * likely that varno is OUTER or INNER, in which case we must dig down
3593 * into the subplans.
3595 if (var
->varno
>= 1 && var
->varno
<= list_length(dpns
->rtable
))
3597 rte
= rt_fetch(var
->varno
, dpns
->rtable
);
3598 attnum
= var
->varattno
;
3600 else if (var
->varno
== OUTER
&& dpns
->outer_plan
)
3607 tle
= get_tle_by_resno(dpns
->outer_plan
->targetlist
, var
->varattno
);
3609 elog(ERROR
, "bogus varattno for OUTER var: %d", var
->varattno
);
3611 Assert(netlevelsup
== 0);
3612 save_outer
= dpns
->outer_plan
;
3613 save_inner
= dpns
->inner_plan
;
3614 push_plan(dpns
, dpns
->outer_plan
);
3616 result
= get_name_for_var_field((Var
*) tle
->expr
, fieldno
,
3619 dpns
->outer_plan
= save_outer
;
3620 dpns
->inner_plan
= save_inner
;
3623 else if (var
->varno
== INNER
&& dpns
->inner_plan
)
3630 tle
= get_tle_by_resno(dpns
->inner_plan
->targetlist
, var
->varattno
);
3632 elog(ERROR
, "bogus varattno for INNER var: %d", var
->varattno
);
3634 Assert(netlevelsup
== 0);
3635 save_outer
= dpns
->outer_plan
;
3636 save_inner
= dpns
->inner_plan
;
3637 push_plan(dpns
, dpns
->inner_plan
);
3639 result
= get_name_for_var_field((Var
*) tle
->expr
, fieldno
,
3642 dpns
->outer_plan
= save_outer
;
3643 dpns
->inner_plan
= save_inner
;
3648 elog(ERROR
, "bogus varno: %d", var
->varno
);
3649 return NULL
; /* keep compiler quiet */
3652 if (attnum
== InvalidAttrNumber
)
3654 /* Var is whole-row reference to RTE, so select the right field */
3655 return get_rte_attribute_name(rte
, fieldno
);
3659 * This part has essentially the same logic as the parser's
3660 * expandRecordVariable() function, but we are dealing with a different
3661 * representation of the input context, and we only need one field name
3662 * not a TupleDesc. Also, we need special cases for finding subquery
3663 * and CTE subplans when deparsing Plan trees.
3665 expr
= (Node
*) var
; /* default if we can't drill down */
3667 switch (rte
->rtekind
)
3674 * This case should not occur: a column of a table or values list
3675 * shouldn't have type RECORD. Fall through and fail (most
3676 * likely) at the bottom.
3680 /* Subselect-in-FROM: examine sub-select's output expr */
3684 TargetEntry
*ste
= get_tle_by_resno(rte
->subquery
->targetList
,
3687 if (ste
== NULL
|| ste
->resjunk
)
3688 elog(ERROR
, "subquery %s does not have attribute %d",
3689 rte
->eref
->aliasname
, attnum
);
3690 expr
= (Node
*) ste
->expr
;
3694 * Recurse into the sub-select to see what its Var
3695 * refers to. We have to build an additional level of
3696 * namespace to keep in step with varlevelsup in the
3699 deparse_namespace mydpns
;
3702 mydpns
.rtable
= rte
->subquery
->rtable
;
3703 mydpns
.ctes
= rte
->subquery
->cteList
;
3704 mydpns
.subplans
= NIL
;
3705 mydpns
.outer_plan
= mydpns
.inner_plan
= NULL
;
3707 context
->namespaces
= lcons(&mydpns
,
3708 context
->namespaces
);
3710 result
= get_name_for_var_field((Var
*) expr
, fieldno
,
3713 context
->namespaces
=
3714 list_delete_first(context
->namespaces
);
3718 /* else fall through to inspect the expression */
3723 * We're deparsing a Plan tree so we don't have complete
3724 * RTE entries (in particular, rte->subquery is NULL).
3725 * But the only place we'd see a Var directly referencing
3726 * a SUBQUERY RTE is in a SubqueryScan plan node, and we
3727 * can look into the child plan's tlist instead.
3734 if (!dpns
->inner_plan
)
3735 elog(ERROR
, "failed to find plan for subquery %s",
3736 rte
->eref
->aliasname
);
3737 tle
= get_tle_by_resno(dpns
->inner_plan
->targetlist
,
3740 elog(ERROR
, "bogus varattno for subquery var: %d",
3742 Assert(netlevelsup
== 0);
3743 save_outer
= dpns
->outer_plan
;
3744 save_inner
= dpns
->inner_plan
;
3745 push_plan(dpns
, dpns
->inner_plan
);
3747 result
= get_name_for_var_field((Var
*) tle
->expr
, fieldno
,
3750 dpns
->outer_plan
= save_outer
;
3751 dpns
->inner_plan
= save_inner
;
3757 /* Join RTE --- recursively inspect the alias variable */
3758 if (rte
->joinaliasvars
== NIL
)
3759 elog(ERROR
, "cannot decompile join alias var in plan tree");
3760 Assert(attnum
> 0 && attnum
<= list_length(rte
->joinaliasvars
));
3761 expr
= (Node
*) list_nth(rte
->joinaliasvars
, attnum
- 1);
3763 return get_name_for_var_field((Var
*) expr
, fieldno
,
3764 var
->varlevelsup
+ levelsup
,
3766 /* else fall through to inspect the expression */
3771 * We couldn't get here unless a function is declared with one of
3772 * its result columns as RECORD, which is not allowed.
3776 /* CTE reference: examine subquery's output expr */
3778 CommonTableExpr
*cte
= NULL
;
3783 * Try to find the referenced CTE using the namespace stack.
3785 ctelevelsup
= rte
->ctelevelsup
+ netlevelsup
;
3786 if (ctelevelsup
>= list_length(context
->namespaces
))
3790 deparse_namespace
*ctedpns
;
3792 ctedpns
= (deparse_namespace
*)
3793 list_nth(context
->namespaces
, ctelevelsup
);
3794 foreach(lc
, ctedpns
->ctes
)
3796 cte
= (CommonTableExpr
*) lfirst(lc
);
3797 if (strcmp(cte
->ctename
, rte
->ctename
) == 0)
3803 Query
*ctequery
= (Query
*) cte
->ctequery
;
3804 TargetEntry
*ste
= get_tle_by_resno(ctequery
->targetList
,
3807 if (ste
== NULL
|| ste
->resjunk
)
3808 elog(ERROR
, "subquery %s does not have attribute %d",
3809 rte
->eref
->aliasname
, attnum
);
3810 expr
= (Node
*) ste
->expr
;
3814 * Recurse into the CTE to see what its Var refers
3815 * to. We have to build an additional level of
3816 * namespace to keep in step with varlevelsup in the
3817 * CTE. Furthermore it could be an outer CTE, so
3818 * we may have to delete some levels of namespace.
3820 List
*save_nslist
= context
->namespaces
;
3822 deparse_namespace mydpns
;
3825 mydpns
.rtable
= ctequery
->rtable
;
3826 mydpns
.ctes
= ctequery
->cteList
;
3827 mydpns
.subplans
= NIL
;
3828 mydpns
.outer_plan
= mydpns
.inner_plan
= NULL
;
3830 new_nslist
= list_copy_tail(context
->namespaces
,
3832 context
->namespaces
= lcons(&mydpns
, new_nslist
);
3834 result
= get_name_for_var_field((Var
*) expr
, fieldno
,
3837 context
->namespaces
= save_nslist
;
3841 /* else fall through to inspect the expression */
3846 * We're deparsing a Plan tree so we don't have a CTE
3847 * list. But the only place we'd see a Var directly
3848 * referencing a CTE RTE is in a CteScan plan node, and
3849 * we can look into the subplan's tlist instead.
3856 if (!dpns
->inner_plan
)
3857 elog(ERROR
, "failed to find plan for CTE %s",
3858 rte
->eref
->aliasname
);
3859 tle
= get_tle_by_resno(dpns
->inner_plan
->targetlist
,
3862 elog(ERROR
, "bogus varattno for subquery var: %d",
3864 Assert(netlevelsup
== 0);
3865 save_outer
= dpns
->outer_plan
;
3866 save_inner
= dpns
->inner_plan
;
3867 push_plan(dpns
, dpns
->inner_plan
);
3869 result
= get_name_for_var_field((Var
*) tle
->expr
, fieldno
,
3872 dpns
->outer_plan
= save_outer
;
3873 dpns
->inner_plan
= save_inner
;
3881 * We now have an expression we can't expand any more, so see if
3882 * get_expr_result_type() can do anything with it. If not, pass to
3883 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3884 * appropriate error message while failing.
3886 if (get_expr_result_type(expr
, NULL
, &tupleDesc
) != TYPEFUNC_COMPOSITE
)
3887 tupleDesc
= lookup_rowtype_tupdesc_copy(exprType(expr
),
3890 /* Got the tupdesc, so we can extract the field name */
3891 Assert(fieldno
>= 1 && fieldno
<= tupleDesc
->natts
);
3892 return NameStr(tupleDesc
->attrs
[fieldno
- 1]->attname
);
3897 * find_rte_by_refname - look up an RTE by refname in a deparse context
3899 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3901 * NOTE: this code is not really correct since it does not take account of
3902 * the fact that not all the RTEs in a rangetable may be visible from the
3903 * point where a Var reference appears. For the purposes we need, however,
3904 * the only consequence of a false match is that we might stick a schema
3905 * qualifier on a Var that doesn't really need it. So it seems close
3908 static RangeTblEntry
*
3909 find_rte_by_refname(const char *refname
, deparse_context
*context
)
3911 RangeTblEntry
*result
= NULL
;
3914 foreach(nslist
, context
->namespaces
)
3916 deparse_namespace
*dpns
= (deparse_namespace
*) lfirst(nslist
);
3919 foreach(rtlist
, dpns
->rtable
)
3921 RangeTblEntry
*rte
= (RangeTblEntry
*) lfirst(rtlist
);
3923 if (strcmp(rte
->eref
->aliasname
, refname
) == 0)
3926 return NULL
; /* it's ambiguous */
3938 * get_simple_binary_op_name
3940 * helper function for isSimpleNode
3941 * will return single char binary operator name, or NULL if it's not
3944 get_simple_binary_op_name(OpExpr
*expr
)
3946 List
*args
= expr
->args
;
3948 if (list_length(args
) == 2)
3950 /* binary operator */
3951 Node
*arg1
= (Node
*) linitial(args
);
3952 Node
*arg2
= (Node
*) lsecond(args
);
3955 op
= generate_operator_name(expr
->opno
, exprType(arg1
), exprType(arg2
));
3956 if (strlen(op
) == 1)
3964 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3966 * true : simple in the context of parent node's type
3967 * false : not simple
3970 isSimpleNode(Node
*node
, Node
*parentNode
, int prettyFlags
)
3975 switch (nodeTag(node
))
3980 case T_CoerceToDomainValue
:
3981 case T_SetToDefault
:
3982 case T_CurrentOfExpr
:
3983 /* single words: always simple */
3989 case T_CoalesceExpr
:
3996 /* function-like: name(..) or name[..] */
3999 /* CASE keywords act as parentheses */
4006 * appears simple since . has top precedence, unless parent is
4007 * T_FieldSelect itself!
4009 return (IsA(parentNode
, FieldSelect
) ? false : true);
4014 * treat like FieldSelect (probably doesn't matter)
4016 return (IsA(parentNode
, FieldStore
) ? false : true);
4018 case T_CoerceToDomain
:
4019 /* maybe simple, check args */
4020 return isSimpleNode((Node
*) ((CoerceToDomain
*) node
)->arg
,
4023 return isSimpleNode((Node
*) ((RelabelType
*) node
)->arg
,
4026 return isSimpleNode((Node
*) ((CoerceViaIO
*) node
)->arg
,
4028 case T_ArrayCoerceExpr
:
4029 return isSimpleNode((Node
*) ((ArrayCoerceExpr
*) node
)->arg
,
4031 case T_ConvertRowtypeExpr
:
4032 return isSimpleNode((Node
*) ((ConvertRowtypeExpr
*) node
)->arg
,
4037 /* depends on parent node type; needs further checking */
4038 if (prettyFlags
& PRETTYFLAG_PAREN
&& IsA(parentNode
, OpExpr
))
4041 const char *parentOp
;
4044 bool is_lopriparent
;
4045 bool is_hipriparent
;
4047 op
= get_simple_binary_op_name((OpExpr
*) node
);
4051 /* We know only the basic operators + - and * / % */
4052 is_lopriop
= (strchr("+-", *op
) != NULL
);
4053 is_hipriop
= (strchr("*/%", *op
) != NULL
);
4054 if (!(is_lopriop
|| is_hipriop
))
4057 parentOp
= get_simple_binary_op_name((OpExpr
*) parentNode
);
4061 is_lopriparent
= (strchr("+-", *parentOp
) != NULL
);
4062 is_hipriparent
= (strchr("*/%", *parentOp
) != NULL
);
4063 if (!(is_lopriparent
|| is_hipriparent
))
4066 if (is_hipriop
&& is_lopriparent
)
4067 return true; /* op binds tighter than parent */
4069 if (is_lopriop
&& is_hipriparent
)
4073 * Operators are same priority --- can skip parens only if
4074 * we have (a - b) - c, not a - (b - c).
4076 if (node
== (Node
*) linitial(((OpExpr
*) parentNode
)->args
))
4081 /* else do the same stuff as for T_SubLink et al. */
4088 case T_DistinctExpr
:
4089 switch (nodeTag(parentNode
))
4093 /* special handling for casts */
4094 CoercionForm type
= ((FuncExpr
*) parentNode
)->funcformat
;
4096 if (type
== COERCE_EXPLICIT_CAST
||
4097 type
== COERCE_IMPLICIT_CAST
)
4099 return true; /* own parentheses */
4101 case T_BoolExpr
: /* lower precedence */
4102 case T_ArrayRef
: /* other separators */
4103 case T_ArrayExpr
: /* other separators */
4104 case T_RowExpr
: /* other separators */
4105 case T_CoalesceExpr
: /* own parentheses */
4106 case T_MinMaxExpr
: /* own parentheses */
4107 case T_XmlExpr
: /* own parentheses */
4108 case T_NullIfExpr
: /* other separators */
4109 case T_Aggref
: /* own parentheses */
4110 case T_WindowFunc
: /* own parentheses */
4111 case T_CaseExpr
: /* other separators */
4118 switch (nodeTag(parentNode
))
4121 if (prettyFlags
& PRETTYFLAG_PAREN
)
4124 BoolExprType parentType
;
4126 type
= ((BoolExpr
*) node
)->boolop
;
4127 parentType
= ((BoolExpr
*) parentNode
)->boolop
;
4132 if (parentType
== AND_EXPR
|| parentType
== OR_EXPR
)
4136 if (parentType
== OR_EXPR
)
4144 /* special handling for casts */
4145 CoercionForm type
= ((FuncExpr
*) parentNode
)->funcformat
;
4147 if (type
== COERCE_EXPLICIT_CAST
||
4148 type
== COERCE_IMPLICIT_CAST
)
4150 return true; /* own parentheses */
4152 case T_ArrayRef
: /* other separators */
4153 case T_ArrayExpr
: /* other separators */
4154 case T_RowExpr
: /* other separators */
4155 case T_CoalesceExpr
: /* own parentheses */
4156 case T_MinMaxExpr
: /* own parentheses */
4157 case T_XmlExpr
: /* own parentheses */
4158 case T_NullIfExpr
: /* other separators */
4159 case T_Aggref
: /* own parentheses */
4160 case T_WindowFunc
: /* own parentheses */
4161 case T_CaseExpr
: /* other separators */
4170 /* those we don't know: in dubio complexo */
4176 * appendStringInfoSpaces - append spaces to buffer
4179 appendStringInfoSpaces(StringInfo buf
, int count
)
4182 appendStringInfoChar(buf
, ' ');
4186 * appendContextKeyword - append a keyword to buffer
4188 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4189 * Otherwise, just append the keyword.
4192 appendContextKeyword(deparse_context
*context
, const char *str
,
4193 int indentBefore
, int indentAfter
, int indentPlus
)
4195 if (PRETTY_INDENT(context
))
4197 context
->indentLevel
+= indentBefore
;
4199 appendStringInfoChar(context
->buf
, '\n');
4200 appendStringInfoSpaces(context
->buf
,
4201 Max(context
->indentLevel
, 0) + indentPlus
);
4202 appendStringInfoString(context
->buf
, str
);
4204 context
->indentLevel
+= indentAfter
;
4205 if (context
->indentLevel
< 0)
4206 context
->indentLevel
= 0;
4209 appendStringInfoString(context
->buf
, str
);
4213 * get_rule_expr_paren - deparse expr using get_rule_expr,
4214 * embracing the string with parentheses if necessary for prettyPrint.
4216 * Never embrace if prettyFlags=0, because it's done in the calling node.
4218 * Any node that does *not* embrace its argument node by sql syntax (with
4219 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4220 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4224 get_rule_expr_paren(Node
*node
, deparse_context
*context
,
4225 bool showimplicit
, Node
*parentNode
)
4229 need_paren
= PRETTY_PAREN(context
) &&
4230 !isSimpleNode(node
, parentNode
, context
->prettyFlags
);
4233 appendStringInfoChar(context
->buf
, '(');
4235 get_rule_expr(node
, context
, showimplicit
);
4238 appendStringInfoChar(context
->buf
, ')');
4243 * get_rule_expr - Parse back an expression
4245 * Note: showimplicit determines whether we display any implicit cast that
4246 * is present at the top of the expression tree. It is a passed argument,
4247 * not a field of the context struct, because we change the value as we
4248 * recurse down into the expression. In general we suppress implicit casts
4249 * when the result type is known with certainty (eg, the arguments of an
4250 * OR must be boolean). We display implicit casts for arguments of functions
4251 * and operators, since this is needed to be certain that the same function
4252 * or operator will be chosen when the expression is re-parsed.
4256 get_rule_expr(Node
*node
, deparse_context
*context
,
4259 StringInfo buf
= context
->buf
;
4265 * Each level of get_rule_expr must emit an indivisible term
4266 * (parenthesized if necessary) to ensure result is reparsed into the same
4267 * expression tree. The only exception is that when the input is a List,
4268 * we emit the component items comma-separated with no surrounding
4269 * decoration; this is convenient for most callers.
4271 switch (nodeTag(node
))
4274 (void) get_variable((Var
*) node
, 0, true, context
);
4278 get_const_expr((Const
*) node
, context
, 0);
4282 appendStringInfo(buf
, "$%d", ((Param
*) node
)->paramid
);
4286 get_agg_expr((Aggref
*) node
, context
);
4290 get_windowfunc_expr((WindowFunc
*) node
, context
);
4295 ArrayRef
*aref
= (ArrayRef
*) node
;
4299 * Parenthesize the argument unless it's a simple Var or a
4300 * FieldSelect. (In particular, if it's another ArrayRef, we
4301 * *must* parenthesize to avoid confusion.)
4303 need_parens
= !IsA(aref
->refexpr
, Var
) &&
4304 !IsA(aref
->refexpr
, FieldSelect
);
4306 appendStringInfoChar(buf
, '(');
4307 get_rule_expr((Node
*) aref
->refexpr
, context
, showimplicit
);
4309 appendStringInfoChar(buf
, ')');
4310 printSubscripts(aref
, context
);
4313 * Array assignment nodes should have been handled in
4314 * processIndirection().
4316 if (aref
->refassgnexpr
)
4317 elog(ERROR
, "unexpected refassgnexpr");
4322 get_func_expr((FuncExpr
*) node
, context
, showimplicit
);
4326 get_oper_expr((OpExpr
*) node
, context
);
4329 case T_DistinctExpr
:
4331 DistinctExpr
*expr
= (DistinctExpr
*) node
;
4332 List
*args
= expr
->args
;
4333 Node
*arg1
= (Node
*) linitial(args
);
4334 Node
*arg2
= (Node
*) lsecond(args
);
4336 if (!PRETTY_PAREN(context
))
4337 appendStringInfoChar(buf
, '(');
4338 get_rule_expr_paren(arg1
, context
, true, node
);
4339 appendStringInfo(buf
, " IS DISTINCT FROM ");
4340 get_rule_expr_paren(arg2
, context
, true, node
);
4341 if (!PRETTY_PAREN(context
))
4342 appendStringInfoChar(buf
, ')');
4346 case T_ScalarArrayOpExpr
:
4348 ScalarArrayOpExpr
*expr
= (ScalarArrayOpExpr
*) node
;
4349 List
*args
= expr
->args
;
4350 Node
*arg1
= (Node
*) linitial(args
);
4351 Node
*arg2
= (Node
*) lsecond(args
);
4353 if (!PRETTY_PAREN(context
))
4354 appendStringInfoChar(buf
, '(');
4355 get_rule_expr_paren(arg1
, context
, true, node
);
4356 appendStringInfo(buf
, " %s %s (",
4357 generate_operator_name(expr
->opno
,
4359 get_element_type(exprType(arg2
))),
4360 expr
->useOr
? "ANY" : "ALL");
4361 get_rule_expr_paren(arg2
, context
, true, node
);
4362 appendStringInfoChar(buf
, ')');
4363 if (!PRETTY_PAREN(context
))
4364 appendStringInfoChar(buf
, ')');
4370 BoolExpr
*expr
= (BoolExpr
*) node
;
4371 Node
*first_arg
= linitial(expr
->args
);
4372 ListCell
*arg
= lnext(list_head(expr
->args
));
4374 switch (expr
->boolop
)
4377 if (!PRETTY_PAREN(context
))
4378 appendStringInfoChar(buf
, '(');
4379 get_rule_expr_paren(first_arg
, context
,
4383 appendStringInfo(buf
, " AND ");
4384 get_rule_expr_paren((Node
*) lfirst(arg
), context
,
4388 if (!PRETTY_PAREN(context
))
4389 appendStringInfoChar(buf
, ')');
4393 if (!PRETTY_PAREN(context
))
4394 appendStringInfoChar(buf
, '(');
4395 get_rule_expr_paren(first_arg
, context
,
4399 appendStringInfo(buf
, " OR ");
4400 get_rule_expr_paren((Node
*) lfirst(arg
), context
,
4404 if (!PRETTY_PAREN(context
))
4405 appendStringInfoChar(buf
, ')');
4409 if (!PRETTY_PAREN(context
))
4410 appendStringInfoChar(buf
, '(');
4411 appendStringInfo(buf
, "NOT ");
4412 get_rule_expr_paren(first_arg
, context
,
4414 if (!PRETTY_PAREN(context
))
4415 appendStringInfoChar(buf
, ')');
4419 elog(ERROR
, "unrecognized boolop: %d",
4420 (int) expr
->boolop
);
4426 get_sublink_expr((SubLink
*) node
, context
);
4431 SubPlan
*subplan
= (SubPlan
*) node
;
4434 * We cannot see an already-planned subplan in rule deparsing,
4435 * only while EXPLAINing a query plan. We don't try to
4436 * reconstruct the original SQL, just reference the subplan
4437 * that appears elsewhere in EXPLAIN's result.
4439 if (subplan
->useHashTable
)
4440 appendStringInfo(buf
, "(hashed %s)", subplan
->plan_name
);
4442 appendStringInfo(buf
, "(%s)", subplan
->plan_name
);
4446 case T_AlternativeSubPlan
:
4448 AlternativeSubPlan
*asplan
= (AlternativeSubPlan
*) node
;
4451 /* As above, this can only happen during EXPLAIN */
4452 appendStringInfo(buf
, "(alternatives: ");
4453 foreach(lc
, asplan
->subplans
)
4455 SubPlan
*splan
= (SubPlan
*) lfirst(lc
);
4457 Assert(IsA(splan
, SubPlan
));
4458 if (splan
->useHashTable
)
4459 appendStringInfo(buf
, "hashed %s", splan
->plan_name
);
4461 appendStringInfo(buf
, "%s", splan
->plan_name
);
4463 appendStringInfo(buf
, " or ");
4465 appendStringInfo(buf
, ")");
4471 FieldSelect
*fselect
= (FieldSelect
*) node
;
4472 Node
*arg
= (Node
*) fselect
->arg
;
4473 int fno
= fselect
->fieldnum
;
4474 const char *fieldname
;
4478 * Parenthesize the argument unless it's an ArrayRef or
4479 * another FieldSelect. Note in particular that it would be
4480 * WRONG to not parenthesize a Var argument; simplicity is not
4481 * the issue here, having the right number of names is.
4483 need_parens
= !IsA(arg
, ArrayRef
) &&!IsA(arg
, FieldSelect
);
4485 appendStringInfoChar(buf
, '(');
4486 get_rule_expr(arg
, context
, true);
4488 appendStringInfoChar(buf
, ')');
4491 * Get and print the field name.
4493 fieldname
= get_name_for_var_field((Var
*) arg
, fno
,
4495 appendStringInfo(buf
, ".%s", quote_identifier(fieldname
));
4502 * We shouldn't see FieldStore here; it should have been stripped
4503 * off by processIndirection().
4505 elog(ERROR
, "unexpected FieldStore");
4510 RelabelType
*relabel
= (RelabelType
*) node
;
4511 Node
*arg
= (Node
*) relabel
->arg
;
4513 if (relabel
->relabelformat
== COERCE_IMPLICIT_CAST
&&
4516 /* don't show the implicit cast */
4517 get_rule_expr_paren(arg
, context
, false, node
);
4521 get_coercion_expr(arg
, context
,
4522 relabel
->resulttype
,
4523 relabel
->resulttypmod
,
4531 CoerceViaIO
*iocoerce
= (CoerceViaIO
*) node
;
4532 Node
*arg
= (Node
*) iocoerce
->arg
;
4534 if (iocoerce
->coerceformat
== COERCE_IMPLICIT_CAST
&&
4537 /* don't show the implicit cast */
4538 get_rule_expr_paren(arg
, context
, false, node
);
4542 get_coercion_expr(arg
, context
,
4543 iocoerce
->resulttype
,
4550 case T_ArrayCoerceExpr
:
4552 ArrayCoerceExpr
*acoerce
= (ArrayCoerceExpr
*) node
;
4553 Node
*arg
= (Node
*) acoerce
->arg
;
4555 if (acoerce
->coerceformat
== COERCE_IMPLICIT_CAST
&&
4558 /* don't show the implicit cast */
4559 get_rule_expr_paren(arg
, context
, false, node
);
4563 get_coercion_expr(arg
, context
,
4564 acoerce
->resulttype
,
4565 acoerce
->resulttypmod
,
4571 case T_ConvertRowtypeExpr
:
4573 ConvertRowtypeExpr
*convert
= (ConvertRowtypeExpr
*) node
;
4574 Node
*arg
= (Node
*) convert
->arg
;
4576 if (convert
->convertformat
== COERCE_IMPLICIT_CAST
&&
4579 /* don't show the implicit cast */
4580 get_rule_expr_paren(arg
, context
, false, node
);
4584 get_coercion_expr(arg
, context
,
4585 convert
->resulttype
, -1,
4593 CaseExpr
*caseexpr
= (CaseExpr
*) node
;
4596 appendContextKeyword(context
, "CASE",
4597 0, PRETTYINDENT_VAR
, 0);
4600 appendStringInfoChar(buf
, ' ');
4601 get_rule_expr((Node
*) caseexpr
->arg
, context
, true);
4603 foreach(temp
, caseexpr
->args
)
4605 CaseWhen
*when
= (CaseWhen
*) lfirst(temp
);
4606 Node
*w
= (Node
*) when
->expr
;
4608 if (!PRETTY_INDENT(context
))
4609 appendStringInfoChar(buf
, ' ');
4610 appendContextKeyword(context
, "WHEN ",
4615 * The parser should have produced WHEN clauses of the
4616 * form "CaseTestExpr = RHS"; we want to show just the
4617 * RHS. If the user wrote something silly like "CASE
4618 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4619 * simplify_boolean_equality() may have reduced this
4620 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4621 * which we have to show "TRUE" or "FALSE". Also,
4622 * depending on context the original CaseTestExpr
4623 * might have been reduced to a Const (but we won't
4624 * see "WHEN Const"). We have also to consider the
4625 * possibility that an implicit coercion was inserted
4626 * between the CaseTestExpr and the operator.
4630 List
*args
= ((OpExpr
*) w
)->args
;
4634 Assert(list_length(args
) == 2);
4635 lhs
= strip_implicit_coercions(linitial(args
));
4636 Assert(IsA(lhs
, CaseTestExpr
) ||
4638 rhs
= (Node
*) lsecond(args
);
4639 get_rule_expr(rhs
, context
, false);
4641 else if (IsA(strip_implicit_coercions(w
),
4643 appendStringInfo(buf
, "TRUE");
4644 else if (not_clause(w
))
4646 Assert(IsA(strip_implicit_coercions((Node
*) get_notclausearg((Expr
*) w
)),
4648 appendStringInfo(buf
, "FALSE");
4651 elog(ERROR
, "unexpected CASE WHEN clause: %d",
4655 get_rule_expr(w
, context
, false);
4656 appendStringInfo(buf
, " THEN ");
4657 get_rule_expr((Node
*) when
->result
, context
, true);
4659 if (!PRETTY_INDENT(context
))
4660 appendStringInfoChar(buf
, ' ');
4661 appendContextKeyword(context
, "ELSE ",
4663 get_rule_expr((Node
*) caseexpr
->defresult
, context
, true);
4664 if (!PRETTY_INDENT(context
))
4665 appendStringInfoChar(buf
, ' ');
4666 appendContextKeyword(context
, "END",
4667 -PRETTYINDENT_VAR
, 0, 0);
4673 ArrayExpr
*arrayexpr
= (ArrayExpr
*) node
;
4675 appendStringInfo(buf
, "ARRAY[");
4676 get_rule_expr((Node
*) arrayexpr
->elements
, context
, true);
4677 appendStringInfoChar(buf
, ']');
4679 * If the array isn't empty, we assume its elements are
4680 * coerced to the desired type. If it's empty, though, we
4681 * need an explicit coercion to the array type.
4683 if (arrayexpr
->elements
== NIL
)
4684 appendStringInfo(buf
, "::%s",
4685 format_type_with_typemod(arrayexpr
->array_typeid
, -1));
4691 RowExpr
*rowexpr
= (RowExpr
*) node
;
4692 TupleDesc tupdesc
= NULL
;
4698 * If it's a named type and not RECORD, we may have to skip
4699 * dropped columns and/or claim there are NULLs for added
4702 if (rowexpr
->row_typeid
!= RECORDOID
)
4704 tupdesc
= lookup_rowtype_tupdesc(rowexpr
->row_typeid
, -1);
4705 Assert(list_length(rowexpr
->args
) <= tupdesc
->natts
);
4709 * SQL99 allows "ROW" to be omitted when there is more than
4710 * one column, but for simplicity we always print it.
4712 appendStringInfo(buf
, "ROW(");
4715 foreach(arg
, rowexpr
->args
)
4717 Node
*e
= (Node
*) lfirst(arg
);
4719 if (tupdesc
== NULL
||
4720 !tupdesc
->attrs
[i
]->attisdropped
)
4722 appendStringInfoString(buf
, sep
);
4723 get_rule_expr(e
, context
, true);
4728 if (tupdesc
!= NULL
)
4730 while (i
< tupdesc
->natts
)
4732 if (!tupdesc
->attrs
[i
]->attisdropped
)
4734 appendStringInfoString(buf
, sep
);
4735 appendStringInfo(buf
, "NULL");
4741 ReleaseTupleDesc(tupdesc
);
4743 appendStringInfo(buf
, ")");
4744 if (rowexpr
->row_format
== COERCE_EXPLICIT_CAST
)
4745 appendStringInfo(buf
, "::%s",
4746 format_type_with_typemod(rowexpr
->row_typeid
, -1));
4750 case T_RowCompareExpr
:
4752 RowCompareExpr
*rcexpr
= (RowCompareExpr
*) node
;
4757 * SQL99 allows "ROW" to be omitted when there is more than
4758 * one column, but for simplicity we always print it.
4760 appendStringInfo(buf
, "(ROW(");
4762 foreach(arg
, rcexpr
->largs
)
4764 Node
*e
= (Node
*) lfirst(arg
);
4766 appendStringInfoString(buf
, sep
);
4767 get_rule_expr(e
, context
, true);
4772 * We assume that the name of the first-column operator will
4773 * do for all the rest too. This is definitely open to
4774 * failure, eg if some but not all operators were renamed
4775 * since the construct was parsed, but there seems no way to
4778 appendStringInfo(buf
, ") %s ROW(",
4779 generate_operator_name(linitial_oid(rcexpr
->opnos
),
4780 exprType(linitial(rcexpr
->largs
)),
4781 exprType(linitial(rcexpr
->rargs
))));
4783 foreach(arg
, rcexpr
->rargs
)
4785 Node
*e
= (Node
*) lfirst(arg
);
4787 appendStringInfoString(buf
, sep
);
4788 get_rule_expr(e
, context
, true);
4791 appendStringInfo(buf
, "))");
4795 case T_CoalesceExpr
:
4797 CoalesceExpr
*coalesceexpr
= (CoalesceExpr
*) node
;
4799 appendStringInfo(buf
, "COALESCE(");
4800 get_rule_expr((Node
*) coalesceexpr
->args
, context
, true);
4801 appendStringInfoChar(buf
, ')');
4807 MinMaxExpr
*minmaxexpr
= (MinMaxExpr
*) node
;
4809 switch (minmaxexpr
->op
)
4812 appendStringInfo(buf
, "GREATEST(");
4815 appendStringInfo(buf
, "LEAST(");
4818 get_rule_expr((Node
*) minmaxexpr
->args
, context
, true);
4819 appendStringInfoChar(buf
, ')');
4825 XmlExpr
*xexpr
= (XmlExpr
*) node
;
4826 bool needcomma
= false;
4834 appendStringInfoString(buf
, "XMLCONCAT(");
4837 appendStringInfoString(buf
, "XMLELEMENT(");
4840 appendStringInfoString(buf
, "XMLFOREST(");
4843 appendStringInfoString(buf
, "XMLPARSE(");
4846 appendStringInfoString(buf
, "XMLPI(");
4849 appendStringInfoString(buf
, "XMLROOT(");
4851 case IS_XMLSERIALIZE
:
4852 appendStringInfoString(buf
, "XMLSERIALIZE(");
4857 if (xexpr
->op
== IS_XMLPARSE
|| xexpr
->op
== IS_XMLSERIALIZE
)
4859 if (xexpr
->xmloption
== XMLOPTION_DOCUMENT
)
4860 appendStringInfoString(buf
, "DOCUMENT ");
4862 appendStringInfoString(buf
, "CONTENT ");
4866 appendStringInfo(buf
, "NAME %s",
4867 quote_identifier(map_xml_name_to_sql_identifier(xexpr
->name
)));
4870 if (xexpr
->named_args
)
4872 if (xexpr
->op
!= IS_XMLFOREST
)
4875 appendStringInfoString(buf
, ", ");
4876 appendStringInfoString(buf
, "XMLATTRIBUTES(");
4879 forboth(arg
, xexpr
->named_args
, narg
, xexpr
->arg_names
)
4881 Node
*e
= (Node
*) lfirst(arg
);
4882 char *argname
= strVal(lfirst(narg
));
4885 appendStringInfoString(buf
, ", ");
4886 get_rule_expr((Node
*) e
, context
, true);
4887 appendStringInfo(buf
, " AS %s",
4888 quote_identifier(map_xml_name_to_sql_identifier(argname
)));
4891 if (xexpr
->op
!= IS_XMLFOREST
)
4892 appendStringInfoChar(buf
, ')');
4897 appendStringInfoString(buf
, ", ");
4904 case IS_XMLSERIALIZE
:
4905 /* no extra decoration needed */
4906 get_rule_expr((Node
*) xexpr
->args
, context
, true);
4909 Assert(list_length(xexpr
->args
) == 2);
4911 get_rule_expr((Node
*) linitial(xexpr
->args
),
4914 con
= (Const
*) lsecond(xexpr
->args
);
4915 Assert(IsA(con
, Const
));
4916 Assert(!con
->constisnull
);
4917 if (DatumGetBool(con
->constvalue
))
4918 appendStringInfoString(buf
,
4919 " PRESERVE WHITESPACE");
4921 appendStringInfoString(buf
,
4922 " STRIP WHITESPACE");
4925 Assert(list_length(xexpr
->args
) == 3);
4927 get_rule_expr((Node
*) linitial(xexpr
->args
),
4930 appendStringInfoString(buf
, ", VERSION ");
4931 con
= (Const
*) lsecond(xexpr
->args
);
4932 if (IsA(con
, Const
) &&
4934 appendStringInfoString(buf
, "NO VALUE");
4936 get_rule_expr((Node
*) con
, context
, false);
4938 con
= (Const
*) lthird(xexpr
->args
);
4939 Assert(IsA(con
, Const
));
4940 if (con
->constisnull
)
4941 /* suppress STANDALONE NO VALUE */ ;
4944 switch (DatumGetInt32(con
->constvalue
))
4946 case XML_STANDALONE_YES
:
4947 appendStringInfoString(buf
,
4948 ", STANDALONE YES");
4950 case XML_STANDALONE_NO
:
4951 appendStringInfoString(buf
,
4954 case XML_STANDALONE_NO_VALUE
:
4955 appendStringInfoString(buf
,
4956 ", STANDALONE NO VALUE");
4964 get_rule_expr_paren((Node
*) xexpr
->args
, context
, false, node
);
4969 if (xexpr
->op
== IS_XMLSERIALIZE
)
4970 appendStringInfo(buf
, " AS %s", format_type_with_typemod(xexpr
->type
,
4972 if (xexpr
->op
== IS_DOCUMENT
)
4973 appendStringInfoString(buf
, " IS DOCUMENT");
4975 appendStringInfoChar(buf
, ')');
4981 NullIfExpr
*nullifexpr
= (NullIfExpr
*) node
;
4983 appendStringInfo(buf
, "NULLIF(");
4984 get_rule_expr((Node
*) nullifexpr
->args
, context
, true);
4985 appendStringInfoChar(buf
, ')');
4991 NullTest
*ntest
= (NullTest
*) node
;
4993 if (!PRETTY_PAREN(context
))
4994 appendStringInfoChar(buf
, '(');
4995 get_rule_expr_paren((Node
*) ntest
->arg
, context
, true, node
);
4996 switch (ntest
->nulltesttype
)
4999 appendStringInfo(buf
, " IS NULL");
5002 appendStringInfo(buf
, " IS NOT NULL");
5005 elog(ERROR
, "unrecognized nulltesttype: %d",
5006 (int) ntest
->nulltesttype
);
5008 if (!PRETTY_PAREN(context
))
5009 appendStringInfoChar(buf
, ')');
5015 BooleanTest
*btest
= (BooleanTest
*) node
;
5017 if (!PRETTY_PAREN(context
))
5018 appendStringInfoChar(buf
, '(');
5019 get_rule_expr_paren((Node
*) btest
->arg
, context
, false, node
);
5020 switch (btest
->booltesttype
)
5023 appendStringInfo(buf
, " IS TRUE");
5026 appendStringInfo(buf
, " IS NOT TRUE");
5029 appendStringInfo(buf
, " IS FALSE");
5032 appendStringInfo(buf
, " IS NOT FALSE");
5035 appendStringInfo(buf
, " IS UNKNOWN");
5037 case IS_NOT_UNKNOWN
:
5038 appendStringInfo(buf
, " IS NOT UNKNOWN");
5041 elog(ERROR
, "unrecognized booltesttype: %d",
5042 (int) btest
->booltesttype
);
5044 if (!PRETTY_PAREN(context
))
5045 appendStringInfoChar(buf
, ')');
5049 case T_CoerceToDomain
:
5051 CoerceToDomain
*ctest
= (CoerceToDomain
*) node
;
5052 Node
*arg
= (Node
*) ctest
->arg
;
5054 if (ctest
->coercionformat
== COERCE_IMPLICIT_CAST
&&
5057 /* don't show the implicit cast */
5058 get_rule_expr(arg
, context
, false);
5062 get_coercion_expr(arg
, context
,
5064 ctest
->resulttypmod
,
5070 case T_CoerceToDomainValue
:
5071 appendStringInfo(buf
, "VALUE");
5074 case T_SetToDefault
:
5075 appendStringInfo(buf
, "DEFAULT");
5078 case T_CurrentOfExpr
:
5080 CurrentOfExpr
*cexpr
= (CurrentOfExpr
*) node
;
5082 if (cexpr
->cursor_name
)
5083 appendStringInfo(buf
, "CURRENT OF %s",
5084 quote_identifier(cexpr
->cursor_name
));
5086 appendStringInfo(buf
, "CURRENT OF $%d",
5087 cexpr
->cursor_param
);
5097 foreach(l
, (List
*) node
)
5099 appendStringInfoString(buf
, sep
);
5100 get_rule_expr((Node
*) lfirst(l
), context
, showimplicit
);
5107 elog(ERROR
, "unrecognized node type: %d", (int) nodeTag(node
));
5114 * get_oper_expr - Parse back an OpExpr node
5117 get_oper_expr(OpExpr
*expr
, deparse_context
*context
)
5119 StringInfo buf
= context
->buf
;
5120 Oid opno
= expr
->opno
;
5121 List
*args
= expr
->args
;
5123 if (!PRETTY_PAREN(context
))
5124 appendStringInfoChar(buf
, '(');
5125 if (list_length(args
) == 2)
5127 /* binary operator */
5128 Node
*arg1
= (Node
*) linitial(args
);
5129 Node
*arg2
= (Node
*) lsecond(args
);
5131 get_rule_expr_paren(arg1
, context
, true, (Node
*) expr
);
5132 appendStringInfo(buf
, " %s ",
5133 generate_operator_name(opno
,
5136 get_rule_expr_paren(arg2
, context
, true, (Node
*) expr
);
5140 /* unary operator --- but which side? */
5141 Node
*arg
= (Node
*) linitial(args
);
5143 Form_pg_operator optup
;
5145 tp
= SearchSysCache(OPEROID
,
5146 ObjectIdGetDatum(opno
),
5148 if (!HeapTupleIsValid(tp
))
5149 elog(ERROR
, "cache lookup failed for operator %u", opno
);
5150 optup
= (Form_pg_operator
) GETSTRUCT(tp
);
5151 switch (optup
->oprkind
)
5154 appendStringInfo(buf
, "%s ",
5155 generate_operator_name(opno
,
5158 get_rule_expr_paren(arg
, context
, true, (Node
*) expr
);
5161 get_rule_expr_paren(arg
, context
, true, (Node
*) expr
);
5162 appendStringInfo(buf
, " %s",
5163 generate_operator_name(opno
,
5168 elog(ERROR
, "bogus oprkind: %d", optup
->oprkind
);
5170 ReleaseSysCache(tp
);
5172 if (!PRETTY_PAREN(context
))
5173 appendStringInfoChar(buf
, ')');
5177 * get_func_expr - Parse back a FuncExpr node
5180 get_func_expr(FuncExpr
*expr
, deparse_context
*context
,
5183 StringInfo buf
= context
->buf
;
5184 Oid funcoid
= expr
->funcid
;
5185 Oid argtypes
[FUNC_MAX_ARGS
];
5191 * If the function call came from an implicit coercion, then just show the
5192 * first argument --- unless caller wants to see implicit coercions.
5194 if (expr
->funcformat
== COERCE_IMPLICIT_CAST
&& !showimplicit
)
5196 get_rule_expr_paren((Node
*) linitial(expr
->args
), context
,
5197 false, (Node
*) expr
);
5202 * If the function call came from a cast, then show the first argument
5203 * plus an explicit cast operation.
5205 if (expr
->funcformat
== COERCE_EXPLICIT_CAST
||
5206 expr
->funcformat
== COERCE_IMPLICIT_CAST
)
5208 Node
*arg
= linitial(expr
->args
);
5209 Oid rettype
= expr
->funcresulttype
;
5210 int32 coercedTypmod
;
5212 /* Get the typmod if this is a length-coercion function */
5213 (void) exprIsLengthCoercion((Node
*) expr
, &coercedTypmod
);
5215 get_coercion_expr(arg
, context
,
5216 rettype
, coercedTypmod
,
5223 * Normal function: display as proname(args). First we need to extract
5224 * the argument datatypes.
5226 if (list_length(expr
->args
) > FUNC_MAX_ARGS
)
5228 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
5229 errmsg("too many arguments")));
5231 foreach(l
, expr
->args
)
5233 argtypes
[nargs
] = exprType((Node
*) lfirst(l
));
5237 appendStringInfo(buf
, "%s(",
5238 generate_function_name(funcoid
, nargs
, argtypes
,
5241 foreach(l
, expr
->args
)
5244 appendStringInfoString(buf
, ", ");
5245 if (is_variadic
&& lnext(l
) == NULL
)
5246 appendStringInfoString(buf
, "VARIADIC ");
5247 get_rule_expr((Node
*) lfirst(l
), context
, true);
5249 appendStringInfoChar(buf
, ')');
5253 * get_agg_expr - Parse back an Aggref node
5256 get_agg_expr(Aggref
*aggref
, deparse_context
*context
)
5258 StringInfo buf
= context
->buf
;
5259 Oid argtypes
[FUNC_MAX_ARGS
];
5263 if (list_length(aggref
->args
) > FUNC_MAX_ARGS
)
5265 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
5266 errmsg("too many arguments")));
5268 foreach(l
, aggref
->args
)
5270 argtypes
[nargs
] = exprType((Node
*) lfirst(l
));
5274 appendStringInfo(buf
, "%s(%s",
5275 generate_function_name(aggref
->aggfnoid
,
5276 nargs
, argtypes
, NULL
),
5277 aggref
->aggdistinct
? "DISTINCT " : "");
5278 /* aggstar can be set only in zero-argument aggregates */
5279 if (aggref
->aggstar
)
5280 appendStringInfoChar(buf
, '*');
5282 get_rule_expr((Node
*) aggref
->args
, context
, true);
5283 appendStringInfoChar(buf
, ')');
5287 * get_windowfunc_expr - Parse back a WindowFunc node
5290 get_windowfunc_expr(WindowFunc
*wfunc
, deparse_context
*context
)
5292 StringInfo buf
= context
->buf
;
5293 Oid argtypes
[FUNC_MAX_ARGS
];
5297 if (list_length(wfunc
->args
) > FUNC_MAX_ARGS
)
5299 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
5300 errmsg("too many arguments")));
5302 foreach(l
, wfunc
->args
)
5304 argtypes
[nargs
] = exprType((Node
*) lfirst(l
));
5308 appendStringInfo(buf
, "%s(%s",
5309 generate_function_name(wfunc
->winfnoid
,
5310 nargs
, argtypes
, NULL
), "");
5311 /* winstar can be set only in zero-argument aggregates */
5313 appendStringInfoChar(buf
, '*');
5315 get_rule_expr((Node
*) wfunc
->args
, context
, true);
5316 appendStringInfoString(buf
, ") OVER ");
5318 foreach(l
, context
->windowClause
)
5320 WindowClause
*wc
= (WindowClause
*) lfirst(l
);
5322 if (wc
->winref
== wfunc
->winref
)
5325 appendStringInfoString(buf
, quote_identifier(wc
->name
));
5327 get_rule_windowspec(wc
, context
->windowTList
, context
);
5333 if (context
->windowClause
)
5334 elog(ERROR
, "could not find window clause for winref %u",
5337 * In EXPLAIN, we don't have window context information available,
5338 * so we have to settle for this:
5340 appendStringInfoString(buf
, "(?)");
5347 * Make a string representation of a value coerced to a specific type
5351 get_coercion_expr(Node
*arg
, deparse_context
*context
,
5352 Oid resulttype
, int32 resulttypmod
,
5355 StringInfo buf
= context
->buf
;
5358 * Since parse_coerce.c doesn't immediately collapse application of
5359 * length-coercion functions to constants, what we'll typically see in
5360 * such cases is a Const with typmod -1 and a length-coercion function
5361 * right above it. Avoid generating redundant output. However, beware of
5362 * suppressing casts when the user actually wrote something like
5363 * 'foo'::text::char(3).
5365 if (arg
&& IsA(arg
, Const
) &&
5366 ((Const
*) arg
)->consttype
== resulttype
&&
5367 ((Const
*) arg
)->consttypmod
== -1)
5369 /* Show the constant without normal ::typename decoration */
5370 get_const_expr((Const
*) arg
, context
, -1);
5374 if (!PRETTY_PAREN(context
))
5375 appendStringInfoChar(buf
, '(');
5376 get_rule_expr_paren(arg
, context
, false, parentNode
);
5377 if (!PRETTY_PAREN(context
))
5378 appendStringInfoChar(buf
, ')');
5380 appendStringInfo(buf
, "::%s",
5381 format_type_with_typemod(resulttype
, resulttypmod
));
5387 * Make a string representation of a Const
5389 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5390 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5391 * the right type by default.
5395 get_const_expr(Const
*constval
, deparse_context
*context
, int showtype
)
5397 StringInfo buf
= context
->buf
;
5401 bool isfloat
= false;
5404 if (constval
->constisnull
)
5407 * Always label the type of a NULL constant to prevent misdecisions
5408 * about type when reparsing.
5410 appendStringInfo(buf
, "NULL");
5412 appendStringInfo(buf
, "::%s",
5413 format_type_with_typemod(constval
->consttype
,
5414 constval
->consttypmod
));
5418 getTypeOutputInfo(constval
->consttype
,
5419 &typoutput
, &typIsVarlena
);
5421 extval
= OidOutputFunctionCall(typoutput
, constval
->constvalue
);
5423 switch (constval
->consttype
)
5434 * These types are printed without quotes unless they contain
5435 * values that aren't accepted by the scanner unquoted (e.g.,
5436 * 'NaN'). Note that strtod() and friends might accept NaN,
5437 * so we can't use that to test.
5439 * In reality we only need to defend against infinity and NaN,
5440 * so we need not get too crazy about pattern matching here.
5442 * There is a special-case gotcha: if the constant is signed,
5443 * we need to parenthesize it, else the parser might see a
5444 * leading plus/minus as binding less tightly than adjacent
5445 * operators --- particularly, the cast that we might attach
5448 if (strspn(extval
, "0123456789+-eE.") == strlen(extval
))
5450 if (extval
[0] == '+' || extval
[0] == '-')
5451 appendStringInfo(buf
, "(%s)", extval
);
5453 appendStringInfoString(buf
, extval
);
5454 if (strcspn(extval
, "eE.") != strlen(extval
))
5455 isfloat
= true; /* it looks like a float */
5458 appendStringInfo(buf
, "'%s'", extval
);
5464 appendStringInfo(buf
, "B'%s'", extval
);
5468 if (strcmp(extval
, "t") == 0)
5469 appendStringInfo(buf
, "true");
5471 appendStringInfo(buf
, "false");
5475 simple_quote_literal(buf
, extval
);
5485 * For showtype == 0, append ::typename unless the constant will be
5486 * implicitly typed as the right type when it is read in.
5488 * XXX this code has to be kept in sync with the behavior of the parser,
5489 * especially make_const.
5491 switch (constval
->consttype
)
5496 /* These types can be left unlabeled */
5502 * Float-looking constants will be typed as numeric, but if
5503 * there's a specific typmod we need to show it.
5505 needlabel
= !isfloat
|| (constval
->consttypmod
>= 0);
5511 if (needlabel
|| showtype
> 0)
5512 appendStringInfo(buf
, "::%s",
5513 format_type_with_typemod(constval
->consttype
,
5514 constval
->consttypmod
));
5518 * simple_quote_literal - Format a string as a SQL literal, append to buf
5521 simple_quote_literal(StringInfo buf
, const char *val
)
5526 * We form the string literal according to the prevailing setting
5527 * of standard_conforming_strings; we never use E''. User is
5528 * responsible for making sure result is used correctly.
5530 appendStringInfoChar(buf
, '\'');
5531 for (valptr
= val
; *valptr
; valptr
++)
5535 if (SQL_STR_DOUBLE(ch
, !standard_conforming_strings
))
5536 appendStringInfoChar(buf
, ch
);
5537 appendStringInfoChar(buf
, ch
);
5539 appendStringInfoChar(buf
, '\'');
5544 * get_sublink_expr - Parse back a sublink
5548 get_sublink_expr(SubLink
*sublink
, deparse_context
*context
)
5550 StringInfo buf
= context
->buf
;
5551 Query
*query
= (Query
*) (sublink
->subselect
);
5552 char *opname
= NULL
;
5555 if (sublink
->subLinkType
== ARRAY_SUBLINK
)
5556 appendStringInfo(buf
, "ARRAY(");
5558 appendStringInfoChar(buf
, '(');
5561 * Note that we print the name of only the first operator, when there are
5562 * multiple combining operators. This is an approximation that could go
5563 * wrong in various scenarios (operators in different schemas, renamed
5564 * operators, etc) but there is not a whole lot we can do about it, since
5565 * the syntax allows only one operator to be shown.
5567 if (sublink
->testexpr
)
5569 if (IsA(sublink
->testexpr
, OpExpr
))
5571 /* single combining operator */
5572 OpExpr
*opexpr
= (OpExpr
*) sublink
->testexpr
;
5574 get_rule_expr(linitial(opexpr
->args
), context
, true);
5575 opname
= generate_operator_name(opexpr
->opno
,
5576 exprType(linitial(opexpr
->args
)),
5577 exprType(lsecond(opexpr
->args
)));
5579 else if (IsA(sublink
->testexpr
, BoolExpr
))
5581 /* multiple combining operators, = or <> cases */
5585 appendStringInfoChar(buf
, '(');
5587 foreach(l
, ((BoolExpr
*) sublink
->testexpr
)->args
)
5589 OpExpr
*opexpr
= (OpExpr
*) lfirst(l
);
5591 Assert(IsA(opexpr
, OpExpr
));
5592 appendStringInfoString(buf
, sep
);
5593 get_rule_expr(linitial(opexpr
->args
), context
, true);
5595 opname
= generate_operator_name(opexpr
->opno
,
5596 exprType(linitial(opexpr
->args
)),
5597 exprType(lsecond(opexpr
->args
)));
5600 appendStringInfoChar(buf
, ')');
5602 else if (IsA(sublink
->testexpr
, RowCompareExpr
))
5604 /* multiple combining operators, < <= > >= cases */
5605 RowCompareExpr
*rcexpr
= (RowCompareExpr
*) sublink
->testexpr
;
5607 appendStringInfoChar(buf
, '(');
5608 get_rule_expr((Node
*) rcexpr
->largs
, context
, true);
5609 opname
= generate_operator_name(linitial_oid(rcexpr
->opnos
),
5610 exprType(linitial(rcexpr
->largs
)),
5611 exprType(linitial(rcexpr
->rargs
)));
5612 appendStringInfoChar(buf
, ')');
5615 elog(ERROR
, "unrecognized testexpr type: %d",
5616 (int) nodeTag(sublink
->testexpr
));
5621 switch (sublink
->subLinkType
)
5623 case EXISTS_SUBLINK
:
5624 appendStringInfo(buf
, "EXISTS ");
5628 if (strcmp(opname
, "=") == 0) /* Represent = ANY as IN */
5629 appendStringInfo(buf
, " IN ");
5631 appendStringInfo(buf
, " %s ANY ", opname
);
5635 appendStringInfo(buf
, " %s ALL ", opname
);
5638 case ROWCOMPARE_SUBLINK
:
5639 appendStringInfo(buf
, " %s ", opname
);
5647 case CTE_SUBLINK
: /* shouldn't occur in a SubLink */
5649 elog(ERROR
, "unrecognized sublink type: %d",
5650 (int) sublink
->subLinkType
);
5655 appendStringInfoChar(buf
, '(');
5657 get_query_def(query
, buf
, context
->namespaces
, NULL
,
5658 context
->prettyFlags
, context
->indentLevel
);
5661 appendStringInfo(buf
, "))");
5663 appendStringInfoChar(buf
, ')');
5668 * get_from_clause - Parse back a FROM clause
5670 * "prefix" is the keyword that denotes the start of the list of FROM
5671 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5672 * is USING when parsing back DELETE.
5676 get_from_clause(Query
*query
, const char *prefix
, deparse_context
*context
)
5678 StringInfo buf
= context
->buf
;
5683 * We use the query's jointree as a guide to what to print. However, we
5684 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5685 * only appear at the top level of the jointree, so it's sufficient to
5686 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5689 foreach(l
, query
->jointree
->fromlist
)
5691 Node
*jtnode
= (Node
*) lfirst(l
);
5693 if (IsA(jtnode
, RangeTblRef
))
5695 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
5696 RangeTblEntry
*rte
= rt_fetch(varno
, query
->rtable
);
5704 appendContextKeyword(context
, prefix
,
5705 -PRETTYINDENT_STD
, PRETTYINDENT_STD
, 2);
5709 appendStringInfoString(buf
, ", ");
5711 get_from_clause_item(jtnode
, query
, context
);
5716 get_from_clause_item(Node
*jtnode
, Query
*query
, deparse_context
*context
)
5718 StringInfo buf
= context
->buf
;
5720 if (IsA(jtnode
, RangeTblRef
))
5722 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
5723 RangeTblEntry
*rte
= rt_fetch(varno
, query
->rtable
);
5724 bool gavealias
= false;
5726 switch (rte
->rtekind
)
5729 /* Normal relation RTE */
5730 appendStringInfo(buf
, "%s%s",
5732 generate_relation_name(rte
->relid
,
5733 context
->namespaces
));
5737 appendStringInfoChar(buf
, '(');
5738 get_query_def(rte
->subquery
, buf
, context
->namespaces
, NULL
,
5739 context
->prettyFlags
, context
->indentLevel
);
5740 appendStringInfoChar(buf
, ')');
5744 get_rule_expr(rte
->funcexpr
, context
, true);
5747 /* Values list RTE */
5748 get_values_def(rte
->values_lists
, context
);
5751 appendStringInfoString(buf
, quote_identifier(rte
->ctename
));
5754 elog(ERROR
, "unrecognized RTE kind: %d", (int) rte
->rtekind
);
5758 if (rte
->alias
!= NULL
)
5760 appendStringInfo(buf
, " %s",
5761 quote_identifier(rte
->alias
->aliasname
));
5764 else if (rte
->rtekind
== RTE_RELATION
&&
5765 strcmp(rte
->eref
->aliasname
, get_rel_name(rte
->relid
)) != 0)
5768 * Apparently the rel has been renamed since the rule was made.
5769 * Emit a fake alias clause so that variable references will still
5770 * work. This is not a 100% solution but should work in most
5771 * reasonable situations.
5773 appendStringInfo(buf
, " %s",
5774 quote_identifier(rte
->eref
->aliasname
));
5777 else if (rte
->rtekind
== RTE_FUNCTION
)
5780 * For a function RTE, always give an alias. This covers possible
5781 * renaming of the function and/or instability of the
5782 * FigureColname rules for things that aren't simple functions.
5784 appendStringInfo(buf
, " %s",
5785 quote_identifier(rte
->eref
->aliasname
));
5789 if (rte
->rtekind
== RTE_FUNCTION
)
5791 if (rte
->funccoltypes
!= NIL
)
5793 /* Function returning RECORD, reconstruct the columndefs */
5795 appendStringInfo(buf
, " AS ");
5796 get_from_clause_coldeflist(rte
->eref
->colnames
,
5798 rte
->funccoltypmods
,
5804 * For a function RTE, always emit a complete column alias
5805 * list; this is to protect against possible instability of
5806 * the default column names (eg, from altering parameter
5809 get_from_clause_alias(rte
->eref
, rte
, context
);
5815 * For non-function RTEs, just report whatever the user originally
5816 * gave as column aliases.
5818 get_from_clause_alias(rte
->alias
, rte
, context
);
5821 else if (IsA(jtnode
, JoinExpr
))
5823 JoinExpr
*j
= (JoinExpr
*) jtnode
;
5824 bool need_paren_on_right
;
5826 need_paren_on_right
= PRETTY_PAREN(context
) &&
5827 !IsA(j
->rarg
, RangeTblRef
) &&
5828 !(IsA(j
->rarg
, JoinExpr
) &&((JoinExpr
*) j
->rarg
)->alias
!= NULL
);
5830 if (!PRETTY_PAREN(context
) || j
->alias
!= NULL
)
5831 appendStringInfoChar(buf
, '(');
5833 get_from_clause_item(j
->larg
, query
, context
);
5837 if (!PRETTY_INDENT(context
))
5838 appendStringInfoChar(buf
, ' ');
5839 switch (j
->jointype
)
5842 appendContextKeyword(context
, "NATURAL JOIN ",
5844 PRETTYINDENT_JOIN
, 0);
5847 appendContextKeyword(context
, "NATURAL LEFT JOIN ",
5849 PRETTYINDENT_JOIN
, 0);
5852 appendContextKeyword(context
, "NATURAL FULL JOIN ",
5854 PRETTYINDENT_JOIN
, 0);
5857 appendContextKeyword(context
, "NATURAL RIGHT JOIN ",
5859 PRETTYINDENT_JOIN
, 0);
5862 elog(ERROR
, "unrecognized join type: %d",
5868 switch (j
->jointype
)
5872 appendContextKeyword(context
, " JOIN ",
5874 PRETTYINDENT_JOIN
, 2);
5876 appendContextKeyword(context
, " CROSS JOIN ",
5878 PRETTYINDENT_JOIN
, 1);
5881 appendContextKeyword(context
, " LEFT JOIN ",
5883 PRETTYINDENT_JOIN
, 2);
5886 appendContextKeyword(context
, " FULL JOIN ",
5888 PRETTYINDENT_JOIN
, 2);
5891 appendContextKeyword(context
, " RIGHT JOIN ",
5893 PRETTYINDENT_JOIN
, 2);
5896 elog(ERROR
, "unrecognized join type: %d",
5901 if (need_paren_on_right
)
5902 appendStringInfoChar(buf
, '(');
5903 get_from_clause_item(j
->rarg
, query
, context
);
5904 if (need_paren_on_right
)
5905 appendStringInfoChar(buf
, ')');
5907 context
->indentLevel
-= PRETTYINDENT_JOIN_ON
;
5915 appendStringInfo(buf
, " USING (");
5916 foreach(col
, j
->using)
5918 if (col
!= list_head(j
->using))
5919 appendStringInfo(buf
, ", ");
5920 appendStringInfoString(buf
,
5921 quote_identifier(strVal(lfirst(col
))));
5923 appendStringInfoChar(buf
, ')');
5927 appendStringInfo(buf
, " ON ");
5928 if (!PRETTY_PAREN(context
))
5929 appendStringInfoChar(buf
, '(');
5930 get_rule_expr(j
->quals
, context
, false);
5931 if (!PRETTY_PAREN(context
))
5932 appendStringInfoChar(buf
, ')');
5935 if (!PRETTY_PAREN(context
) || j
->alias
!= NULL
)
5936 appendStringInfoChar(buf
, ')');
5938 /* Yes, it's correct to put alias after the right paren ... */
5939 if (j
->alias
!= NULL
)
5941 appendStringInfo(buf
, " %s",
5942 quote_identifier(j
->alias
->aliasname
));
5943 get_from_clause_alias(j
->alias
,
5944 rt_fetch(j
->rtindex
, query
->rtable
),
5949 elog(ERROR
, "unrecognized node type: %d",
5950 (int) nodeTag(jtnode
));
5954 * get_from_clause_alias - reproduce column alias list
5956 * This is tricky because we must ignore dropped columns.
5959 get_from_clause_alias(Alias
*alias
, RangeTblEntry
*rte
,
5960 deparse_context
*context
)
5962 StringInfo buf
= context
->buf
;
5967 if (alias
== NULL
|| alias
->colnames
== NIL
)
5968 return; /* definitely nothing to do */
5971 foreach(col
, alias
->colnames
)
5974 if (get_rte_attribute_is_dropped(rte
, attnum
))
5978 appendStringInfoChar(buf
, '(');
5982 appendStringInfo(buf
, ", ");
5983 appendStringInfoString(buf
,
5984 quote_identifier(strVal(lfirst(col
))));
5987 appendStringInfoChar(buf
, ')');
5991 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5993 * The coldeflist is appended immediately (no space) to buf. Caller is
5994 * responsible for ensuring that an alias or AS is present before it.
5997 get_from_clause_coldeflist(List
*names
, List
*types
, List
*typmods
,
5998 deparse_context
*context
)
6000 StringInfo buf
= context
->buf
;
6006 appendStringInfoChar(buf
, '(');
6008 l2
= list_head(types
);
6009 l3
= list_head(typmods
);
6012 char *attname
= strVal(lfirst(l1
));
6016 atttypid
= lfirst_oid(l2
);
6018 atttypmod
= lfirst_int(l3
);
6022 appendStringInfo(buf
, ", ");
6023 appendStringInfo(buf
, "%s %s",
6024 quote_identifier(attname
),
6025 format_type_with_typemod(atttypid
, atttypmod
));
6029 appendStringInfoChar(buf
, ')');
6033 * get_opclass_name - fetch name of an index operator class
6035 * The opclass name is appended (after a space) to buf.
6037 * Output is suppressed if the opclass is the default for the given
6038 * actual_datatype. (If you don't want this behavior, just pass
6039 * InvalidOid for actual_datatype.)
6042 get_opclass_name(Oid opclass
, Oid actual_datatype
,
6046 Form_pg_opclass opcrec
;
6050 ht_opc
= SearchSysCache(CLAOID
,
6051 ObjectIdGetDatum(opclass
),
6053 if (!HeapTupleIsValid(ht_opc
))
6054 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
6055 opcrec
= (Form_pg_opclass
) GETSTRUCT(ht_opc
);
6057 if (!OidIsValid(actual_datatype
) ||
6058 GetDefaultOpClass(actual_datatype
, opcrec
->opcmethod
) != opclass
)
6060 /* Okay, we need the opclass name. Do we need to qualify it? */
6061 opcname
= NameStr(opcrec
->opcname
);
6062 if (OpclassIsVisible(opclass
))
6063 appendStringInfo(buf
, " %s", quote_identifier(opcname
));
6066 nspname
= get_namespace_name(opcrec
->opcnamespace
);
6067 appendStringInfo(buf
, " %s.%s",
6068 quote_identifier(nspname
),
6069 quote_identifier(opcname
));
6072 ReleaseSysCache(ht_opc
);
6076 * processIndirection - take care of array and subfield assignment
6078 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6079 * appear in the input, and return the subexpression that's to be assigned.
6080 * If printit is true, we also print out the appropriate decoration for the
6081 * base column name (that the caller just printed).
6084 processIndirection(Node
*node
, deparse_context
*context
, bool printit
)
6086 StringInfo buf
= context
->buf
;
6092 if (IsA(node
, FieldStore
))
6094 FieldStore
*fstore
= (FieldStore
*) node
;
6098 /* lookup tuple type */
6099 typrelid
= get_typ_typrelid(fstore
->resulttype
);
6100 if (!OidIsValid(typrelid
))
6101 elog(ERROR
, "argument type %s of FieldStore is not a tuple type",
6102 format_type_be(fstore
->resulttype
));
6105 * Print the field name. Note we assume here that there's only
6106 * one field being assigned to. This is okay in stored rules but
6107 * could be wrong in executable target lists. Presently no
6108 * problem since explain.c doesn't print plan targetlists, but
6109 * someday may have to think of something ...
6111 fieldname
= get_relid_attribute_name(typrelid
,
6112 linitial_int(fstore
->fieldnums
));
6114 appendStringInfo(buf
, ".%s", quote_identifier(fieldname
));
6117 * We ignore arg since it should be an uninteresting reference to
6118 * the target column or subcolumn.
6120 node
= (Node
*) linitial(fstore
->newvals
);
6122 else if (IsA(node
, ArrayRef
))
6124 ArrayRef
*aref
= (ArrayRef
*) node
;
6126 if (aref
->refassgnexpr
== NULL
)
6129 printSubscripts(aref
, context
);
6132 * We ignore refexpr since it should be an uninteresting reference
6133 * to the target column or subcolumn.
6135 node
= (Node
*) aref
->refassgnexpr
;
6145 printSubscripts(ArrayRef
*aref
, deparse_context
*context
)
6147 StringInfo buf
= context
->buf
;
6148 ListCell
*lowlist_item
;
6149 ListCell
*uplist_item
;
6151 lowlist_item
= list_head(aref
->reflowerindexpr
); /* could be NULL */
6152 foreach(uplist_item
, aref
->refupperindexpr
)
6154 appendStringInfoChar(buf
, '[');
6157 get_rule_expr((Node
*) lfirst(lowlist_item
), context
, false);
6158 appendStringInfoChar(buf
, ':');
6159 lowlist_item
= lnext(lowlist_item
);
6161 get_rule_expr((Node
*) lfirst(uplist_item
), context
, false);
6162 appendStringInfoChar(buf
, ']');
6167 * quote_identifier - Quote an identifier only if needed
6169 * When quotes are needed, we palloc the required space; slightly
6170 * space-wasteful but well worth it for notational simplicity.
6173 quote_identifier(const char *ident
)
6176 * Can avoid quoting if ident starts with a lowercase letter or underscore
6177 * and contains only lowercase letters, digits, and underscores, *and* is
6178 * not any SQL keyword. Otherwise, supply quotes.
6187 * would like to use <ctype.h> macros here, but they might yield unwanted
6188 * locale-specific results...
6190 safe
= ((ident
[0] >= 'a' && ident
[0] <= 'z') || ident
[0] == '_');
6192 for (ptr
= ident
; *ptr
; ptr
++)
6196 if ((ch
>= 'a' && ch
<= 'z') ||
6197 (ch
>= '0' && ch
<= '9') ||
6213 * Check for keyword. We quote keywords except for unreserved ones.
6214 * (In some cases we could avoid quoting a col_name or type_func_name
6215 * keyword, but it seems much harder than it's worth to tell that.)
6217 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6218 * that's fine, since we already know we have all-lower-case.
6220 const ScanKeyword
*keyword
= ScanKeywordLookup(ident
);
6222 if (keyword
!= NULL
&& keyword
->category
!= UNRESERVED_KEYWORD
)
6227 return ident
; /* no change needed */
6229 result
= (char *) palloc(strlen(ident
) + nquotes
+ 2 + 1);
6233 for (ptr
= ident
; *ptr
; ptr
++)
6248 * quote_qualified_identifier - Quote a possibly-qualified identifier
6250 * Return a name of the form namespace.ident, or just ident if namespace
6251 * is NULL, quoting each component if necessary. The result is palloc'd.
6254 quote_qualified_identifier(const char *namespace,
6259 initStringInfo(&buf
);
6261 appendStringInfo(&buf
, "%s.", quote_identifier(namespace));
6262 appendStringInfoString(&buf
, quote_identifier(ident
));
6267 * generate_relation_name
6268 * Compute the name to display for a relation specified by OID
6270 * The result includes all necessary quoting and schema-prefixing.
6272 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6273 * We will forcibly qualify the relation name if it equals any CTE name
6274 * visible in the namespace list.
6277 generate_relation_name(Oid relid
, List
*namespaces
)
6280 Form_pg_class reltup
;
6287 tp
= SearchSysCache(RELOID
,
6288 ObjectIdGetDatum(relid
),
6290 if (!HeapTupleIsValid(tp
))
6291 elog(ERROR
, "cache lookup failed for relation %u", relid
);
6292 reltup
= (Form_pg_class
) GETSTRUCT(tp
);
6293 relname
= NameStr(reltup
->relname
);
6295 /* Check for conflicting CTE name */
6297 foreach(nslist
, namespaces
)
6299 deparse_namespace
*dpns
= (deparse_namespace
*) lfirst(nslist
);
6302 foreach(ctlist
, dpns
->ctes
)
6304 CommonTableExpr
*cte
= (CommonTableExpr
*) lfirst(ctlist
);
6306 if (strcmp(cte
->ctename
, relname
) == 0)
6316 /* Otherwise, qualify the name if not visible in search path */
6318 need_qual
= !RelationIsVisible(relid
);
6321 nspname
= get_namespace_name(reltup
->relnamespace
);
6325 result
= quote_qualified_identifier(nspname
, relname
);
6327 ReleaseSysCache(tp
);
6333 * generate_function_name
6334 * Compute the name to display for a function specified by OID,
6335 * given that it is being called with the specified actual arg types.
6336 * (Arg types matter because of ambiguous-function resolution rules.)
6338 * The result includes all necessary quoting and schema-prefixing. We can
6339 * also pass back an indication of whether the function is variadic.
6342 generate_function_name(Oid funcid
, int nargs
, Oid
*argtypes
,
6346 Form_pg_proc procform
;
6350 FuncDetailCode p_result
;
6355 Oid
*p_true_typeids
;
6357 proctup
= SearchSysCache(PROCOID
,
6358 ObjectIdGetDatum(funcid
),
6360 if (!HeapTupleIsValid(proctup
))
6361 elog(ERROR
, "cache lookup failed for function %u", funcid
);
6362 procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
6363 proname
= NameStr(procform
->proname
);
6366 * The idea here is to schema-qualify only if the parser would fail to
6367 * resolve the correct function given the unqualified func name with the
6368 * specified argtypes.
6370 p_result
= func_get_detail(list_make1(makeString(proname
)),
6371 NIL
, nargs
, argtypes
, false, true,
6372 &p_funcid
, &p_rettype
,
6373 &p_retset
, &p_nvargs
, &p_true_typeids
, NULL
);
6374 if ((p_result
== FUNCDETAIL_NORMAL
||
6375 p_result
== FUNCDETAIL_AGGREGATE
||
6376 p_result
== FUNCDETAIL_WINDOWFUNC
) &&
6380 nspname
= get_namespace_name(procform
->pronamespace
);
6382 result
= quote_qualified_identifier(nspname
, proname
);
6384 /* Check variadic-ness if caller cares */
6387 /* "any" variadics are not treated as variadics for listing */
6388 if (OidIsValid(procform
->provariadic
) &&
6389 procform
->provariadic
!= ANYOID
)
6390 *is_variadic
= true;
6392 *is_variadic
= false;
6395 ReleaseSysCache(proctup
);
6401 * generate_operator_name
6402 * Compute the name to display for an operator specified by OID,
6403 * given that it is being called with the specified actual arg types.
6404 * (Arg types matter because of ambiguous-operator resolution rules.
6405 * Pass InvalidOid for unused arg of a unary operator.)
6407 * The result includes all necessary quoting and schema-prefixing,
6408 * plus the OPERATOR() decoration needed to use a qualified operator name
6412 generate_operator_name(Oid operid
, Oid arg1
, Oid arg2
)
6416 Form_pg_operator operform
;
6421 initStringInfo(&buf
);
6423 opertup
= SearchSysCache(OPEROID
,
6424 ObjectIdGetDatum(operid
),
6426 if (!HeapTupleIsValid(opertup
))
6427 elog(ERROR
, "cache lookup failed for operator %u", operid
);
6428 operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
6429 oprname
= NameStr(operform
->oprname
);
6432 * The idea here is to schema-qualify only if the parser would fail to
6433 * resolve the correct operator given the unqualified op name with the
6434 * specified argtypes.
6436 switch (operform
->oprkind
)
6439 p_result
= oper(NULL
, list_make1(makeString(oprname
)), arg1
, arg2
,
6443 p_result
= left_oper(NULL
, list_make1(makeString(oprname
)), arg2
,
6447 p_result
= right_oper(NULL
, list_make1(makeString(oprname
)), arg1
,
6451 elog(ERROR
, "unrecognized oprkind: %d", operform
->oprkind
);
6452 p_result
= NULL
; /* keep compiler quiet */
6456 if (p_result
!= NULL
&& oprid(p_result
) == operid
)
6460 nspname
= get_namespace_name(operform
->oprnamespace
);
6461 appendStringInfo(&buf
, "OPERATOR(%s.", quote_identifier(nspname
));
6464 appendStringInfoString(&buf
, oprname
);
6467 appendStringInfoChar(&buf
, ')');
6469 if (p_result
!= NULL
)
6470 ReleaseSysCache(p_result
);
6472 ReleaseSysCache(opertup
);
6478 * Given a C string, produce a TEXT datum.
6480 * We assume that the input was palloc'd and may be freed.
6483 string_to_text(char *str
)
6487 result
= cstring_to_text(str
);
6493 * Generate a C string representing a relation's reloptions, or NULL if none.
6496 flatten_reloptions(Oid relid
)
6498 char *result
= NULL
;
6503 tuple
= SearchSysCache(RELOID
,
6504 ObjectIdGetDatum(relid
),
6506 if (!HeapTupleIsValid(tuple
))
6507 elog(ERROR
, "cache lookup failed for relation %u", relid
);
6509 reloptions
= SysCacheGetAttr(RELOID
, tuple
,
6510 Anum_pg_class_reloptions
, &isnull
);
6517 * We want to use array_to_text(reloptions, ', ') --- but
6518 * DirectFunctionCall2(array_to_text) does not work, because
6519 * array_to_text() relies on flinfo to be valid. So use
6522 sep
= CStringGetTextDatum(", ");
6523 txt
= OidFunctionCall2(F_ARRAY_TO_TEXT
, reloptions
, sep
);
6524 result
= TextDatumGetCString(txt
);
6527 ReleaseSysCache(tuple
);