]> granicus.if.org Git - postgresql/commitdiff
Improve pretty printing of viewdefs.
authorAndrew Dunstan <andrew@dunslane.net>
Sun, 19 Feb 2012 16:43:46 +0000 (11:43 -0500)
committerAndrew Dunstan <andrew@dunslane.net>
Sun, 19 Feb 2012 16:43:46 +0000 (11:43 -0500)
Some line feeds are added to target lists and from lists to make
them more readable. By default they wrap at 80 columns if possible,
but the wrap column is also selectable - if 0 it wraps after every
item.

Andrew Dunstan, reviewed by Hitoshi Harada.

doc/src/sgml/func.sgml
src/backend/utils/adt/ruleutils.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h
src/test/regress/expected/polymorphism.out
src/test/regress/expected/rules.out
src/test/regress/expected/with.out
src/test/regress/sql/rules.sql

index 236a60a688e7b7737cf869d168bd2a0db26c4879..e8e637bf31bbd87c3294392f360e2ab91822106b 100644 (file)
@@ -13828,7 +13828,8 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
       <row>
        <entry><literal><function>pg_get_viewdef(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</function></literal></entry>
        <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry>
+       <entry>get underlying <command>SELECT</command> command for view, 
+              lines with fields are wrapped to 80 columns if pretty_bool is true (<emphasis>deprecated</emphasis>)</entry>
       </row>
       <row>
        <entry><literal><function>pg_get_viewdef(<parameter>view_oid</parameter>)</function></literal></entry>
@@ -13838,7 +13839,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
       <row>
        <entry><literal><function>pg_get_viewdef(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</function></literal></entry>
        <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view</entry>
+       <entry>get underlying <command>SELECT</command> command for view, 
+              lines with fields are wrapped to 80 columns if pretty_bool is true</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_get_viewdef(<parameter>view_oid</parameter>, <parameter>wrap_int</>)</function></literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get underlying <command>SELECT</command> command for view, 
+              wrapping lines with fields as specified, pretty printing is implied</entry>
       </row>
       <row>
        <entry><literal><function>pg_options_to_table(<parameter>reloptions</parameter>)</function></literal></entry>
index 9ad54c5decbcb1debb4f0bec4edd27f589efca83..64ba8ec8917d3b3da588eb3a319cb39e1c8ec1d7 100644 (file)
@@ -73,6 +73,8 @@
 #define PRETTYFLAG_PAREN               1
 #define PRETTYFLAG_INDENT              2
 
+#define PRETTY_WRAP_DEFAULT     79
+
 /* macro to test if pretty action needed */
 #define PRETTY_PAREN(context)  ((context)->prettyFlags & PRETTYFLAG_PAREN)
 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
@@ -136,6 +138,7 @@ static SPIPlanPtr plan_getrulebyoid = NULL;
 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
 static SPIPlanPtr plan_getviewrule = NULL;
 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
+static int pretty_wrap = PRETTY_WRAP_DEFAULT;
 
 /* GUC parameters */
 bool           quote_all_identifiers = false;
@@ -380,6 +383,23 @@ pg_get_viewdef_ext(PG_FUNCTION_ARGS)
        PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
 }
 
+Datum
+pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
+{
+       /* By OID */
+       Oid                     viewoid = PG_GETARG_OID(0);
+       int                 wrap = PG_GETARG_INT32(1);
+       int                     prettyFlags;
+       char       *result;
+
+       /* calling this implies we want pretty printing */
+       prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT;
+       pretty_wrap = wrap;
+       result = pg_get_viewdef_worker(viewoid, prettyFlags);
+       pretty_wrap = PRETTY_WRAP_DEFAULT;
+       PG_RETURN_TEXT_P(string_to_text(result));
+}
+
 Datum
 pg_get_viewdef_name(PG_FUNCTION_ARGS)
 {
@@ -3013,6 +3033,7 @@ get_target_list(List *targetList, deparse_context *context,
        char       *sep;
        int                     colno;
        ListCell   *l;
+       bool        last_was_multiline = false;
 
        sep = " ";
        colno = 0;
@@ -3021,6 +3042,10 @@ get_target_list(List *targetList, deparse_context *context,
                TargetEntry *tle = (TargetEntry *) lfirst(l);
                char       *colname;
                char       *attname;
+               StringInfoData targetbuf;
+               int         leading_nl_pos =  -1;
+               char       *trailing_nl;
+               int         pos;
 
                if (tle->resjunk)
                        continue;                       /* ignore junk entries */
@@ -3029,6 +3054,15 @@ get_target_list(List *targetList, deparse_context *context,
                sep = ", ";
                colno++;
 
+               /*
+                * Put the new field spec into targetbuf so we can
+                * decide after we've got it whether or not it needs
+                * to go on a new line.
+                */
+
+               initStringInfo(&targetbuf);
+               context->buf = &targetbuf;
+
                /*
                 * We special-case Var nodes rather than using get_rule_expr. This is
                 * needed because get_rule_expr will display a whole-row Var as
@@ -3063,8 +3097,66 @@ get_target_list(List *targetList, deparse_context *context,
                if (colname)                    /* resname could be NULL */
                {
                        if (attname == NULL || strcmp(attname, colname) != 0)
-                               appendStringInfo(buf, " AS %s", quote_identifier(colname));
+                               appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
+               }
+
+               /* Restore context buffer */
+
+               context->buf = buf;
+
+               /* Does the new field start with whitespace plus a new line? */
+
+               for (pos=0; pos < targetbuf.len; pos++)
+               {
+                       if (targetbuf.data[pos] == '\n')
+                       {
+                               leading_nl_pos = pos;
+                               break;
+                       }
+                       if (targetbuf.data[pos] > ' ')
+                               break;
+               }
+
+               /* Locate the start of the current  line in the buffer */
+
+               trailing_nl = (strrchr(buf->data,'\n'));
+               if (trailing_nl == NULL)
+                       trailing_nl = buf->data;
+               else 
+                       trailing_nl++;
+
+               /*
+                * If the field we're adding is the first in the list, or it already 
+                * has a leading newline, or wrap mode is disabled (pretty_wrap < 0), 
+                * don't add anything.
+                * Otherwise, add a newline, plus some  indentation, if either the 
+                * new field would cause an overflow or the last field used more than
+                * one line.
+                */
+
+               if (colno > 1 &&
+                       leading_nl_pos == -1 && 
+                       pretty_wrap >= 0 &&
+                       ((strlen(trailing_nl) + strlen(targetbuf.data) > pretty_wrap) ||
+                        last_was_multiline))
+               {
+                       appendContextKeyword(context, "", -PRETTYINDENT_STD, 
+                                                                PRETTYINDENT_STD, PRETTYINDENT_VAR);
                }
+
+               /* Add the new field */
+
+               appendStringInfoString(buf, targetbuf.data);
+
+
+               /* Keep track of this field's status for next iteration */
+
+               last_was_multiline = 
+                       (strchr(targetbuf.data + leading_nl_pos + 1,'\n') != NULL);
+
+               /* cleanup */
+
+               pfree (targetbuf.data);
        }
 }
 
@@ -6445,11 +6537,52 @@ get_from_clause(Query *query, const char *prefix, deparse_context *context)
                        appendContextKeyword(context, prefix,
                                                                 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
                        first = false;
+
+                       get_from_clause_item(jtnode, query, context);
                }
                else
+               {
+                       StringInfoData targetbuf;
+                       char          *trailing_nl;
+
                        appendStringInfoString(buf, ", ");
+                       
+                       initStringInfo(&targetbuf);
+                       context->buf = &targetbuf;
+
+                       get_from_clause_item(jtnode, query, context);
+
+                       context->buf = buf;
+
+                       /* Locate the start of the current  line in the buffer */
+
+                       trailing_nl = (strrchr(buf->data,'\n'));
+                       if (trailing_nl == NULL)
+                               trailing_nl = buf->data;
+                       else 
+                               trailing_nl++;
+                       
+                       /*
+                        * Add a newline, plus some  indentation, if pretty_wrap is on and the 
+                        * new from-clause item would cause an overflow.
+                        */
+                       
+                       if (pretty_wrap >= 0 &&
+                               (strlen(trailing_nl) + strlen(targetbuf.data) > pretty_wrap))
+                       {
+                               appendContextKeyword(context, "", -PRETTYINDENT_STD, 
+                                                                        PRETTYINDENT_STD, PRETTYINDENT_VAR);
+                       }
+
+                       /* Add the new item */
+
+                       appendStringInfoString(buf, targetbuf.data);
+                       
+                       /* cleanup */
+
+                       pfree (targetbuf.data);
+               }
 
-               get_from_clause_item(jtnode, query, context);
        }
 }
 
index 7a54a74757e75940a238578634d183e5d303d893..6100472d94a918c2e461013605d54164282dd506 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201202141
+#define CATALOG_VERSION_NO     201202191
 
 #endif
index fb2923f94db06cd528d588fa52ca3294e025f9f6..8700d0d958a26161d626fae1ae2e58f0c3154250 100644 (file)
@@ -3743,6 +3743,8 @@ DATA(insert OID = 2505 (  pg_get_viewdef     PGNSP PGUID 12 1 0 0 0 f f f f t f s
 DESCR("select statement of a view with pretty-print option");
 DATA(insert OID = 2506 (  pg_get_viewdef          PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 25 "26 16" _null_ _null_ _null_ _null_      pg_get_viewdef_ext _null_ _null_ _null_ ));
 DESCR("select statement of a view with pretty-print option");
+DATA(insert OID = 3159 (  pg_get_viewdef          PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 25 "26 23" _null_ _null_ _null_ _null_      pg_get_viewdef_wrap _null_ _null_ _null_ ));
+DESCR("select statement of a view with pretty-printing and specified line wrapping");
 DATA(insert OID = 2507 (  pg_get_indexdef         PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 25 "26 23 16" _null_ _null_ _null_ _null_   pg_get_indexdef_ext _null_ _null_ _null_ ));
 DESCR("index description (full create statement or single expression) with pretty-print option");
 DATA(insert OID = 2508 (  pg_get_constraintdef PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 25 "26 16" _null_ _null_ _null_ _null_ pg_get_constraintdef_ext _null_ _null_ _null_ ));
index 2c331ce5eb9b2dc2a0f5db63be57f8af0db74ad5..fe253bcc7cdf8d08f4fdcf365480dac939ffa207 100644 (file)
@@ -624,6 +624,7 @@ extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
 extern Datum pg_get_ruledef_ext(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef_ext(PG_FUNCTION_ARGS);
+extern Datum pg_get_viewdef_wrap(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef_name_ext(PG_FUNCTION_ARGS);
 extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
index cb3d756290cf1157141c29d2657876a05a5014d4..1e879532f870c58a090cfec00df686b4bbe1981d 100644 (file)
@@ -1381,7 +1381,9 @@ select * from dfview;
  c3     | bigint |           | plain   | 
  c4     | bigint |           | plain   | 
 View definition:
- SELECT int8_tbl.q1, int8_tbl.q2, dfunc(int8_tbl.q1, int8_tbl.q2, flag := int8_tbl.q1 > int8_tbl.q2) AS c3, dfunc(int8_tbl.q1, flag := int8_tbl.q1 < int8_tbl.q2, b := int8_tbl.q2) AS c4
+ SELECT int8_tbl.q1, int8_tbl.q2, 
+    dfunc(int8_tbl.q1, int8_tbl.q2, flag := int8_tbl.q1 > int8_tbl.q2) AS c3, 
+    dfunc(int8_tbl.q1, flag := int8_tbl.q1 < int8_tbl.q2, b := int8_tbl.q2) AS c4
    FROM int8_tbl;
 
 drop view dfview;
index f67b8dc3f43e988ffddab241153b66514cd4b13d..0275a0e120e40e91e6cdf70531f7ed8ccd371fc3 100644 (file)
@@ -1568,3 +1568,36 @@ select * from only t1_2;
  19
 (10 rows)
 
+-- test various flavors of pg_get_viewdef()
+select pg_get_viewdef('shoe'::regclass) as unpretty;
+                                                                                                             unpretty                                                                                                              
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, (sh.slminlen * un.un_fact) AS slminlen_cm, sh.slmaxlen, (sh.slmaxlen * un.un_fact) AS slmaxlen_cm, sh.slunit FROM shoe_data sh, unit un WHERE (sh.slunit = un.un_name);
+(1 row)
+
+select pg_get_viewdef('shoe'::regclass,true) as pretty;
+                           pretty                            
+-------------------------------------------------------------
+  SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, +
+     sh.slminlen * un.un_fact AS slminlen_cm, sh.slmaxlen,  +
+     sh.slmaxlen * un.un_fact AS slmaxlen_cm, sh.slunit     +
+    FROM shoe_data sh, unit un                              +
+   WHERE sh.slunit = un.un_name;
+(1 row)
+
+select pg_get_viewdef('shoe'::regclass,0) as prettier;
+                   prettier                    
+-----------------------------------------------
+  SELECT sh.shoename,                         +
+     sh.sh_avail,                             +
+     sh.slcolor,                              +
+     sh.slminlen,                             +
+     sh.slminlen * un.un_fact AS slminlen_cm, +
+     sh.slmaxlen,                             +
+     sh.slmaxlen * un.un_fact AS slmaxlen_cm, +
+     sh.slunit                                +
+    FROM shoe_data sh,                        +
+     unit un                                  +
+   WHERE sh.slunit = un.un_name;
+(1 row)
+
index a58739b68ef5921d6fbf310d2aafa251cfdd504f..fae92cd37bf3535a2dc44635496c0f953926e6e8 100644 (file)
@@ -277,18 +277,19 @@ SELECT pg_get_viewdef('vsubdepartment'::regclass);
 (1 row)
 
 SELECT pg_get_viewdef('vsubdepartment'::regclass, true);
-                                    pg_get_viewdef                                    
---------------------------------------------------------------------------------------
-  WITH RECURSIVE subdepartment AS (                                                  +
-                  SELECT department.id, department.parent_department, department.name+
-                    FROM department                                                  +
-                   WHERE department.name = 'A'::text                                 +
-         UNION ALL                                                                   +
-                  SELECT d.id, d.parent_department, d.name                           +
-                    FROM department d, subdepartment sd                              +
-                   WHERE d.parent_department = sd.id                                 +
-         )                                                                           +
-  SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name       +
+                                pg_get_viewdef                                 
+-------------------------------------------------------------------------------
+  WITH RECURSIVE subdepartment AS (                                           +
+                  SELECT department.id, department.parent_department,         +
+                     department.name                                          +
+                    FROM department                                           +
+                   WHERE department.name = 'A'::text                          +
+         UNION ALL                                                            +
+                  SELECT d.id, d.parent_department, d.name                    +
+                    FROM department d, subdepartment sd                       +
+                   WHERE d.parent_department = sd.id                          +
+         )                                                                    +
+  SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name+
     FROM subdepartment;
 (1 row)
 
index 16dc106ab0767d091ce9347094093aacce42b33c..ea665a3c8bb801aa6b96bb5747be093618115f63 100644 (file)
@@ -927,3 +927,9 @@ update t1 set a = 4 where a = 5;
 select * from only t1;
 select * from only t1_1;
 select * from only t1_2;
+
+-- test various flavors of pg_get_viewdef()
+
+select pg_get_viewdef('shoe'::regclass) as unpretty;
+select pg_get_viewdef('shoe'::regclass,true) as pretty;
+select pg_get_viewdef('shoe'::regclass,0) as prettier;