On 12/22/2011 06:14 PM, Andrew Dunstan wrote:


On 12/22/2011 06:11 PM, Andrew Dunstan wrote:


On 12/22/2011 02:17 PM, Andrew Dunstan wrote:


On 12/22/2011 01:05 PM, Tom Lane wrote:
Maybe, though I fear it might complicate the ruleutils code a bit.
You'd probably have to build the output for a column first and then
see how long it is before deciding whether to insert a newline.

In short, I don't mind trying to make this work better, but I think it
will take more work than a two-line patch.



OK. Let me whip something up. I had already come to the conclusion you did about how best to do this.



Here's a WIP patch. At least it's fairly localized, but as expected it's rather more than 2 lines :-). Sample output:

regression=# \pset format unaligned
Output format is unaligned.
regression=# select pg_get_viewdef('shoelace',true);
pg_get_viewdef
 SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit,
    s.sl_len * u.un_fact AS sl_len_cm
   FROM shoelace_data s, unit u
  WHERE s.sl_unit = u.un_name;
(1 row)
regression=#


I just had an idea. We could invent a flavor of pg_get_viewdef() that took an int as the second param, that would be the wrap width. For the boolean case as above, 80 would be implied. 0 would mean always wrap. psql could be made to default to the window width, or maybe window width - 1, but we could provide a psql setting that would override it.



This time with patch.




Updated, with docs and tests. Since the docs mark the versions of pg_get_viewdef() that take text as the first param as deprecated, I removed that variant of the new flavor. I left adding extra psql support to another day - I think this already does a good job of cleaning it up without any extra adjustments.

I'll add this to the upcoming commitfest.

cheers

andrew
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 2e06346..0418591 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -13758,7 +13758,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>
@@ -13768,7 +13769,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>
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 29df748..5b774f0 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -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;
@@ -381,6 +384,23 @@ pg_get_viewdef_ext(PG_FUNCTION_ARGS)
 }
 
 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)
 {
 	/* By qualified name */
@@ -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 */
@@ -3030,6 +3055,15 @@ get_target_list(List *targetList, deparse_context *context,
 		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
 		 * "foo.*", which is the preferred notation in most contexts, but at
@@ -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);
 	}
 }
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c893c3a..83f65b8 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3715,6 +3715,8 @@ DATA(insert OID = 2505 (  pg_get_viewdef	   PGNSP PGUID 12 1 0 0 0 f f f t f s 2
 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 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 = 3145 (  pg_get_viewdef	   PGNSP PGUID 12 1 0 0 0 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 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 t f s 2 0 25 "26 16" _null_ _null_ _null_ _null_	pg_get_constraintdef_ext _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index aa36db6..49e7d3b 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -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);
diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out
index cb3d756..1e87953 100644
--- a/src/test/regress/expected/polymorphism.out
+++ b/src/test/regress/expected/polymorphism.out
@@ -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;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 454e1f9..019ca5c 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1568,3 +1568,35 @@ 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)
+
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index c4b0456..d34492e 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -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)
 
diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql
index 16dc106..ea665a3 100644
--- a/src/test/regress/sql/rules.sql
+++ b/src/test/regress/sql/rules.sql
@@ -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;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to