Limit overall indentation in rule/view dumps.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Apr 2014 16:48:15 +0000 (12:48 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Apr 2014 16:48:15 +0000 (12:48 -0400)
Continuing to indent no matter how deeply nested we get doesn't really
do anything for readability; what's worse, it results in O(N^2) total
whitespace, which can become a performance and memory-consumption issue.

To address this, once we get past 40 characters of indentation, reduce
the indentation step distance 4x, and also limit the maximum indentation
by reducing it modulo 40.  This latter choice is a bit weird at first
glance, but it seems to preserve readability better than a simple cap
would do.

Back-patch to 9.3, because since commit 62e666400d the performance issue
is a hazard for pg_dump.

Greg Stark and Tom Lane

src/backend/utils/adt/ruleutils.c
src/test/regress/expected/rules.out

index 3fea8132f89e6107b2792aa7dad13cc8f5f09e20..491ffc6e8b1693f3e374b34f477909238eb921d4 100644 (file)
@@ -69,6 +69,8 @@
 #define PRETTYINDENT_JOIN      4
 #define PRETTYINDENT_VAR       4
 
+#define PRETTYINDENT_LIMIT     40      /* wrap limit */
+
 /* Pretty flags */
 #define PRETTYFLAG_PAREN       1
 #define PRETTYFLAG_INDENT      2
@@ -6258,14 +6260,36 @@ appendContextKeyword(deparse_context *context, const char *str,
 
    if (PRETTY_INDENT(context))
    {
+       int         indentAmount;
+
        context->indentLevel += indentBefore;
 
        /* remove any trailing spaces currently in the buffer ... */
        removeStringInfoSpaces(buf);
        /* ... then add a newline and some spaces */
        appendStringInfoChar(buf, '\n');
-       appendStringInfoSpaces(buf,
-                              Max(context->indentLevel, 0) + indentPlus);
+
+       if (context->indentLevel < PRETTYINDENT_LIMIT)
+           indentAmount = Max(context->indentLevel, 0) + indentPlus;
+       else
+       {
+           /*
+            * If we're indented more than PRETTYINDENT_LIMIT characters, try
+            * to conserve horizontal space by reducing the per-level
+            * indentation.  For best results the scale factor here should
+            * divide all the indent amounts that get added to indentLevel
+            * (PRETTYINDENT_STD, etc).  It's important that the indentation
+            * not grow unboundedly, else deeply-nested trees use O(N^2)
+            * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
+            */
+           indentAmount = PRETTYINDENT_LIMIT +
+               (context->indentLevel - PRETTYINDENT_LIMIT) /
+               (PRETTYINDENT_STD / 2);
+           indentAmount %= PRETTYINDENT_LIMIT;
+           /* scale/wrap logic affects indentLevel, but not indentPlus */
+           indentAmount += indentPlus;
+       }
+       appendStringInfoSpaces(buf, indentAmount);
 
        appendStringInfoString(buf, str);
 
index 1cd19a664aff9b4368c41aa16efdca8022fa6ac0..34abec383c2b8ffe14ac607f2900f9a8f2b3a386 100644 (file)
@@ -1391,121 +1391,121 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
                                  |      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))                                                                                                                                                  +
                                  |   WHERE (r.rulename <> '_RETURN'::name);
  pg_seclabels                    |         (        (        (        (        (        (        (        (        (         SELECT l.objoid,                                                                                                    +
-                                 |                                                                                     l.classoid,                                                                                                               +
-                                 |                                                                                     l.objsubid,                                                                                                               +
-                                 |                                                                                         CASE                                                                                                                  +
-                                 |                                                                                             WHEN (rel.relkind = 'r'::"char") THEN 'table'::text                                                               +
-                                 |                                                                                             WHEN (rel.relkind = 'v'::"char") THEN 'view'::text                                                                +
-                                 |                                                                                             WHEN (rel.relkind = 'm'::"char") THEN 'materialized view'::text                                                   +
-                                 |                                                                                             WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text                                                            +
-                                 |                                                                                             WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text                                                       +
-                                 |                                                                                             ELSE NULL::text                                                                                                   +
-                                 |                                                                                         END AS objtype,                                                                                                       +
-                                 |                                                                                     rel.relnamespace AS objnamespace,                                                                                         +
-                                 |                                                                                         CASE                                                                                                                  +
-                                 |                                                                                             WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text)                                           +
-                                 |                                                                                             ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text))                        +
-                                 |                                                                                         END AS objname,                                                                                                       +
-                                 |                                                                                     l.provider,                                                                                                               +
-                                 |                                                                                     l.label                                                                                                                   +
-                                 |                                                                                    FROM ((pg_seclabel l                                                                                                       +
-                                 |                                                                                      JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid))))                                           +
-                                 |                                                                                      JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid)))                                                                 +
-                                 |                                                                                   WHERE (l.objsubid = 0)                                                                                                      +
-                                 |                                                                         UNION ALL                                                                                                                             +
-                                 |                                                                                  SELECT l.objoid,                                                                                                             +
-                                 |                                                                                     l.classoid,                                                                                                               +
-                                 |                                                                                     l.objsubid,                                                                                                               +
-                                 |                                                                                     'column'::text AS objtype,                                                                                                +
-                                 |                                                                                     rel.relnamespace AS objnamespace,                                                                                         +
-                                 |                                                                                     ((                                                                                                                        +
-                                 |                                                                                         CASE                                                                                                                  +
-                                 |                                                                                             WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text)                                           +
-                                 |                                                                                             ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text))                        +
-                                 |                                                                                         END || '.'::text) || (att.attname)::text) AS objname,                                                                 +
-                                 |                                                                                     l.provider,                                                                                                               +
-                                 |                                                                                     l.label                                                                                                                   +
-                                 |                                                                                    FROM (((pg_seclabel l                                                                                                      +
-                                 |                                                                                      JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid))))                                           +
-                                 |                                                                                      JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum))))                                     +
-                                 |                                                                                      JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid)))                                                                 +
-                                 |                                                                                   WHERE (l.objsubid <> 0))                                                                                                    +
-                                 |                                                                 UNION ALL                                                                                                                                     +
-                                 |                                                                          SELECT l.objoid,                                                                                                                     +
-                                 |                                                                             l.classoid,                                                                                                                       +
-                                 |                                                                             l.objsubid,                                                                                                                       +
-                                 |                                                                                 CASE                                                                                                                          +
-                                 |                                                                                     WHEN (pro.proisagg = true) THEN 'aggregate'::text                                                                         +
-                                 |                                                                                     WHEN (pro.proisagg = false) THEN 'function'::text                                                                         +
-                                 |                                                                                     ELSE NULL::text                                                                                                           +
-                                 |                                                                                 END AS objtype,                                                                                                               +
-                                 |                                                                             pro.pronamespace AS objnamespace,                                                                                                 +
-                                 |                                                                             (((                                                                                                                               +
-                                 |                                                                                 CASE                                                                                                                          +
-                                 |                                                                                     WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text)                                                +
-                                 |                                                                                     ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text))                                +
-                                 |                                                                                 END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname,                                            +
-                                 |                                                                             l.provider,                                                                                                                       +
-                                 |                                                                             l.label                                                                                                                           +
-                                 |                                                                            FROM ((pg_seclabel l                                                                                                               +
-                                 |                                                                              JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid))))                                                    +
-                                 |                                                                              JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid)))                                                                         +
-                                 |                                                                           WHERE (l.objsubid = 0))                                                                                                             +
-                                 |                                                         UNION ALL                                                                                                                                             +
-                                 |                                                                  SELECT l.objoid,                                                                                                                             +
-                                 |                                                                     l.classoid,                                                                                                                               +
-                                 |                                                                     l.objsubid,                                                                                                                               +
-                                 |                                                                         CASE                                                                                                                                  +
-                                 |                                                                             WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text                                                                              +
-                                 |                                                                             ELSE 'type'::text                                                                                                                 +
-                                 |                                                                         END AS objtype,                                                                                                                       +
-                                 |                                                                     typ.typnamespace AS objnamespace,                                                                                                         +
-                                 |                                                                         CASE                                                                                                                                  +
-                                 |                                                                             WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text)                                                            +
-                                 |                                                                             ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text))                                        +
-                                 |                                                                         END AS objname,                                                                                                                       +
-                                 |                                                                     l.provider,                                                                                                                               +
-                                 |                                                                     l.label                                                                                                                                   +
-                                 |                                                                    FROM ((pg_seclabel l                                                                                                                       +
-                                 |                                                                      JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid))))                                                            +
-                                 |                                                                      JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid)))                                                                                 +
-                                 |                                                                   WHERE (l.objsubid = 0))                                                                                                                     +
-                                 |                                                 UNION ALL                                                                                                                                                     +
-                                 |                                                          SELECT l.objoid,                                                                                                                                     +
-                                 |                                                             l.classoid,                                                                                                                                       +
-                                 |                                                             l.objsubid,                                                                                                                                       +
-                                 |                                                             'large object'::text AS objtype,                                                                                                                  +
-                                 |                                                             NULL::oid AS objnamespace,                                                                                                                        +
-                                 |                                                             (l.objoid)::text AS objname,                                                                                                                      +
-                                 |                                                             l.provider,                                                                                                                                       +
-                                 |                                                             l.label                                                                                                                                           +
-                                 |                                                            FROM (pg_seclabel l                                                                                                                                +
-                                 |                                                              JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid)))                                                                                      +
-                                 |                                                           WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0)))                                                                      +
-                                 |                                         UNION ALL                                                                                                                                                             +
-                                 |                                                  SELECT l.objoid,                                                                                                                                             +
-                                 |                                                     l.classoid,                                                                                                                                               +
-                                 |                                                     l.objsubid,                                                                                                                                               +
-                                 |                                                     'language'::text AS objtype,                                                                                                                              +
-                                 |                                                     NULL::oid AS objnamespace,                                                                                                                                +
-                                 |                                                     quote_ident((lan.lanname)::text) AS objname,                                                                                                              +
-                                 |                                                     l.provider,                                                                                                                                               +
-                                 |                                                     l.label                                                                                                                                                   +
-                                 |                                                    FROM (pg_seclabel l                                                                                                                                        +
-                                 |                                                      JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid))))                                                                        +
-                                 |                                                   WHERE (l.objsubid = 0))                                                                                                                                     +
+                                 |               l.classoid,                                                                                                                                                                                     +
+                                 |               l.objsubid,                                                                                                                                                                                     +
+                                 |             CASE                                                                                                                                                                                              +
+                                 |              WHEN (rel.relkind = 'r'::"char") THEN 'table'::text                                                                                                                                              +
+                                 |              WHEN (rel.relkind = 'v'::"char") THEN 'view'::text                                                                                                                                               +
+                                 |              WHEN (rel.relkind = 'm'::"char") THEN 'materialized view'::text                                                                                                                                  +
+                                 |              WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text                                                                                                                                           +
+                                 |              WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text                                                                                                                                      +
+                                 |              ELSE NULL::text                                                                                                                                                                                  +
+                                 |             END AS objtype,                                                                                                                                                                                   +
+                                 |               rel.relnamespace AS objnamespace,                                                                                                                                                               +
+                                 |             CASE                                                                                                                                                                                              +
+                                 |              WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text)                                                                                                                          +
+                                 |              ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text))                                                                                                       +
+                                 |             END AS objname,                                                                                                                                                                                   +
+                                 |               l.provider,                                                                                                                                                                                     +
+                                 |               l.label                                                                                                                                                                                         +
+                                 |              FROM ((pg_seclabel l                                                                                                                                                                             +
+                                 |                JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid))))                                                                                                                 +
+                                 |                JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid)))                                                                                                                                       +
+                                 |             WHERE (l.objsubid = 0)                                                                                                                                                                            +
+                                 |         UNION ALL                                                                                                                                                                                             +
+                                 |            SELECT l.objoid,                                                                                                                                                                                   +
+                                 |               l.classoid,                                                                                                                                                                                     +
+                                 |               l.objsubid,                                                                                                                                                                                     +
+                                 |               'column'::text AS objtype,                                                                                                                                                                      +
+                                 |               rel.relnamespace AS objnamespace,                                                                                                                                                               +
+                                 |               ((                                                                                                                                                                                              +
+                                 |             CASE                                                                                                                                                                                              +
+                                 |              WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text)                                                                                                                          +
+                                 |              ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text))                                                                                                       +
+                                 |             END || '.'::text) || (att.attname)::text) AS objname,                                                                                                                                             +
+                                 |               l.provider,                                                                                                                                                                                     +
+                                 |               l.label                                                                                                                                                                                         +
+                                 |              FROM (((pg_seclabel l                                                                                                                                                                            +
+                                 |                JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid))))                                                                                                                 +
+                                 |                JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum))))                                                                                                           +
+                                 |                JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid)))                                                                                                                                       +
+                                 |             WHERE (l.objsubid <> 0))                                                                                                                                                                          +
+                                 |       UNION ALL                                                                                                                                                                                               +
+                                 |          SELECT l.objoid,                                                                                                                                                                                     +
+                                 |             l.classoid,                                                                                                                                                                                       +
+                                 |             l.objsubid,                                                                                                                                                                                       +
+                                 |           CASE                                                                                                                                                                                                +
+                                 |            WHEN (pro.proisagg = true) THEN 'aggregate'::text                                                                                                                                                  +
+                                 |            WHEN (pro.proisagg = false) THEN 'function'::text                                                                                                                                                  +
+                                 |            ELSE NULL::text                                                                                                                                                                                    +
+                                 |           END AS objtype,                                                                                                                                                                                     +
+                                 |             pro.pronamespace AS objnamespace,                                                                                                                                                                 +
+                                 |             (((                                                                                                                                                                                               +
+                                 |           CASE                                                                                                                                                                                                +
+                                 |            WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text)                                                                                                                         +
+                                 |            ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text))                                                                                                         +
+                                 |           END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname,                                                                                                                  +
+                                 |             l.provider,                                                                                                                                                                                       +
+                                 |             l.label                                                                                                                                                                                           +
+                                 |            FROM ((pg_seclabel l                                                                                                                                                                               +
+                                 |              JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid))))                                                                                                                    +
+                                 |              JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid)))                                                                                                                                         +
+                                 |           WHERE (l.objsubid = 0))                                                                                                                                                                             +
+                                 |     UNION ALL                                                                                                                                                                                                 +
+                                 |        SELECT l.objoid,                                                                                                                                                                                       +
+                                 |           l.classoid,                                                                                                                                                                                         +
+                                 |           l.objsubid,                                                                                                                                                                                         +
+                                 |         CASE                                                                                                                                                                                                  +
+                                 |          WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text                                                                                                                                                 +
+                                 |          ELSE 'type'::text                                                                                                                                                                                    +
+                                 |         END AS objtype,                                                                                                                                                                                       +
+                                 |           typ.typnamespace AS objnamespace,                                                                                                                                                                   +
+                                 |         CASE                                                                                                                                                                                                  +
+                                 |          WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text)                                                                                                                               +
+                                 |          ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text))                                                                                                           +
+                                 |         END AS objname,                                                                                                                                                                                       +
+                                 |           l.provider,                                                                                                                                                                                         +
+                                 |           l.label                                                                                                                                                                                             +
+                                 |          FROM ((pg_seclabel l                                                                                                                                                                                 +
+                                 |            JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid))))                                                                                                                      +
+                                 |            JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid)))                                                                                                                                           +
+                                 |         WHERE (l.objsubid = 0))                                                                                                                                                                               +
+                                 |   UNION ALL                                                                                                                                                                                                   +
+                                 |      SELECT l.objoid,                                                                                                                                                                                         +
+                                 |         l.classoid,                                                                                                                                                                                           +
+                                 |         l.objsubid,                                                                                                                                                                                           +
+                                 |         'large object'::text AS objtype,                                                                                                                                                                      +
+                                 |         NULL::oid AS objnamespace,                                                                                                                                                                            +
+                                 |         (l.objoid)::text AS objname,                                                                                                                                                                          +
+                                 |         l.provider,                                                                                                                                                                                           +
+                                 |         l.label                                                                                                                                                                                               +
+                                 |        FROM (pg_seclabel l                                                                                                                                                                                    +
+                                 |          JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid)))                                                                                                                                          +
+                                 |       WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0)))                                                                                                                          +
+                                 | UNION ALL                                                                                                                                                                                                     +
+                                 |    SELECT l.objoid,                                                                                                                                                                                           +
+                                 |       l.classoid,                                                                                                                                                                                             +
+                                 |       l.objsubid,                                                                                                                                                                                             +
+                                 |       'language'::text AS objtype,                                                                                                                                                                            +
+                                 |       NULL::oid AS objnamespace,                                                                                                                                                                              +
+                                 |       quote_ident((lan.lanname)::text) AS objname,                                                                                                                                                            +
+                                 |       l.provider,                                                                                                                                                                                             +
+                                 |       l.label                                                                                                                                                                                                 +
+                                 |      FROM (pg_seclabel l                                                                                                                                                                                      +
+                                 |        JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid))))                                                                                                                      +
+                                 |     WHERE (l.objsubid = 0))                                                                                                                                                                                   +
                                  |                                 UNION ALL                                                                                                                                                                     +
-                                 |                                          SELECT l.objoid,                                                                                                                                                     +
-                                 |                                             l.classoid,                                                                                                                                                       +
-                                 |                                             l.objsubid,                                                                                                                                                       +
-                                 |                                             'schema'::text AS objtype,                                                                                                                                        +
-                                 |                                             nsp.oid AS objnamespace,                                                                                                                                          +
-                                 |                                             quote_ident((nsp.nspname)::text) AS objname,                                                                                                                      +
-                                 |                                             l.provider,                                                                                                                                                       +
-                                 |                                             l.label                                                                                                                                                           +
-                                 |                                            FROM (pg_seclabel l                                                                                                                                                +
-                                 |                                              JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid))))                                                                               +
-                                 |                                           WHERE (l.objsubid = 0))                                                                                                                                             +
+                                 |  SELECT l.objoid,                                                                                                                                                                                             +
+                                 |     l.classoid,                                                                                                                                                                                               +
+                                 |     l.objsubid,                                                                                                                                                                                               +
+                                 |     'schema'::text AS objtype,                                                                                                                                                                                +
+                                 |     nsp.oid AS objnamespace,                                                                                                                                                                                  +
+                                 |     quote_ident((nsp.nspname)::text) AS objname,                                                                                                                                                              +
+                                 |     l.provider,                                                                                                                                                                                               +
+                                 |     l.label                                                                                                                                                                                                   +
+                                 |    FROM (pg_seclabel l                                                                                                                                                                                        +
+                                 |      JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid))))                                                                                                                       +
+                                 |   WHERE (l.objsubid = 0))                                                                                                                                                                                     +
                                  |                         UNION ALL                                                                                                                                                                             +
                                  |                                  SELECT l.objoid,                                                                                                                                                             +
                                  |                                     l.classoid,                                                                                                                                                               +