Add public ruleutils.c entry point to deparse a Query.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Mar 2022 15:19:29 +0000 (11:19 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Mar 2022 15:19:37 +0000 (11:19 -0400)
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

src/backend/utils/adt/ruleutils.c
src/include/utils/ruleutils.h

index 82dc849a3016a9456ac25a8525dd282e9feb8a88..38da26951978b7757a7275133697fd004f832252 100644 (file)
 #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)
index e8090c96d7380339e32f29bb77d7f6e82450b90b..7d489718a3572a1b389bb1b04468de8100e28988 100644 (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);