Commit 2f582f76 authored by Andrew Dunstan's avatar Andrew Dunstan

Improve pretty printing of viewdefs.

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.
parent 84ff5b5d
......@@ -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>
......
......@@ -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);
}
}
......
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201202141
#define CATALOG_VERSION_NO 201202191
#endif
......@@ -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_ ));
......
......@@ -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);
......
......@@ -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;
......
......@@ -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)
......@@ -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)
......
......@@ -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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment