Add public ruleutils.c entry point to deparse a Query.

This has no in-core callers but will be wanted by extensions.
It's just a thin wrapper around get_query_def, so it adds little code.

Also, fix get_from_clause_item() to force insertion of an alias
for a SUBQUERY RTE item.  This is irrelevant to existing uses because
RTE_SUBQUERY items made by the parser always have aliases already.
However, if one tried to use pg_get_querydef() to inspect a post-rewrite
Query, it could be an issue.  In any case, get_from_clause_item already
contained logic to force alias insertion for VALUES items, so the lack
of the same for SUBQUERY is a pretty clear oversight.

In passing, replace duplicated code for selection of pretty-print
options with a common macro.

Julien Rouhaud, reviewed by Pavel Stehule, Gilles Darold, and myself

Discussion: https://postgr.es/m/20210627041138.zklczwmu3ms4ufnk@nol
This commit is contained in:
Tom Lane 2022-03-28 11:19:29 -04:00
parent 386ca0abf4
commit d22646922d
2 changed files with 43 additions and 12 deletions

View File

@ -90,6 +90,11 @@
#define PRETTYFLAG_INDENT 0x0002
#define PRETTYFLAG_SCHEMA 0x0004
/* Standard conversion of a "bool pretty" option to detailed flags */
#define GET_PRETTY_FLAGS(pretty) \
((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
: PRETTYFLAG_INDENT)
/* Default line length for pretty-print wrapping: 0 means wrap always */
#define WRAP_COLUMN_DEFAULT 0
@ -532,7 +537,7 @@ pg_get_ruledef_ext(PG_FUNCTION_ARGS)
int prettyFlags;
char *res;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
res = pg_get_ruledef_worker(ruleoid, prettyFlags);
@ -653,7 +658,7 @@ pg_get_viewdef_ext(PG_FUNCTION_ARGS)
int prettyFlags;
char *res;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
@ -673,7 +678,7 @@ pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
char *res;
/* calling this implies we want pretty printing */
prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA;
prettyFlags = GET_PRETTY_FLAGS(true);
res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
@ -719,7 +724,7 @@ pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
Oid viewoid;
char *res;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
/* Look up view name. Can't lock it - we might not have privileges. */
viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
@ -1062,7 +1067,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
context.windowClause = NIL;
context.windowTList = NIL;
context.varprefix = true;
context.prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
context.prettyFlags = GET_PRETTY_FLAGS(pretty);
context.wrapColumn = WRAP_COLUMN_DEFAULT;
context.indentLevel = PRETTYINDENT_STD;
context.special_exprkind = EXPR_KIND_NONE;
@ -1152,7 +1157,7 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS)
int prettyFlags;
char *res;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
res = pg_get_indexdef_worker(indexrelid, colno, NULL,
colno != 0, false,
@ -1185,7 +1190,7 @@ pg_get_indexdef_columns(Oid indexrelid, bool pretty)
{
int prettyFlags;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
return pg_get_indexdef_worker(indexrelid, 0, NULL,
true, true,
@ -1516,6 +1521,30 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
return buf.data;
}
/* ----------
* pg_get_querydef
*
* Public entry point to deparse one query parsetree.
* The pretty flags are determined by GET_PRETTY_FLAGS(pretty).
*
* The result is a palloc'd C string.
* ----------
*/
char *
pg_get_querydef(Query *query, bool pretty)
{
StringInfoData buf;
int prettyFlags;
prettyFlags = GET_PRETTY_FLAGS(pretty);
initStringInfo(&buf);
get_query_def(query, &buf, NIL, NULL, prettyFlags, WRAP_COLUMN_DEFAULT, 0);
return buf.data;
}
/*
* pg_get_statisticsobjdef
* Get the definition of an extended statistics object
@ -1848,7 +1877,7 @@ pg_get_partkeydef_columns(Oid relid, bool pretty)
{
int prettyFlags;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
}
@ -2095,7 +2124,7 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
int prettyFlags;
char *res;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
@ -2625,7 +2654,7 @@ pg_get_expr_ext(PG_FUNCTION_ARGS)
int prettyFlags;
char *relname;
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT;
prettyFlags = GET_PRETTY_FLAGS(pretty);
if (OidIsValid(relid))
{
@ -11210,9 +11239,10 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
*/
printalias = true;
}
else if (rte->rtekind == RTE_VALUES)
else if (rte->rtekind == RTE_SUBQUERY ||
rte->rtekind == RTE_VALUES)
{
/* Alias is syntactically required for VALUES */
/* Alias is syntactically required for SUBQUERY and VALUES */
printalias = true;
}
else if (rte->rtekind == RTE_CTE)

View File

@ -23,6 +23,7 @@ struct PlannedStmt;
extern char *pg_get_indexdef_string(Oid indexrelid);
extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
extern char *pg_get_querydef(Query *query, bool pretty);
extern char *pg_get_partkeydef_columns(Oid relid, bool pretty);
extern char *pg_get_partconstrdef_string(Oid partitionId, char *aliasname);