mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Fix ruleutils pretty-printing to not generate trailing whitespace.
The pretty-printing logic in ruleutils.c operates by inserting a newline and some indentation whitespace into strings that are already valid SQL. This naturally results in leaving some trailing whitespace before the newline in many cases; which can be annoying when processing the output with other tools, as complained of by Joe Abbate. We can fix that in a pretty localized fashion by deleting any trailing whitespace before we append a pretty-printing newline. In addition, we have to modify the code inserted by commit 2f582f76b1945929ff07116cd4639747ce9bb8a1 so that we also delete trailing whitespace when transposing items from temporary buffers into the main result string, when a temporary item starts with a newline. This results in rather voluminous changes to the regression test results, but it's easily verified that they are only removal of trailing whitespace. Back-patch to 9.3, because the aforementioned commit resulted in many more cases of trailing whitespace than had occurred in earlier branches.
This commit is contained in:
parent
04e6ee4020
commit
fbbd150a25
@ -366,6 +366,7 @@ static const char *get_simple_binary_op_name(OpExpr *expr);
|
||||
static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
|
||||
static void appendContextKeyword(deparse_context *context, const char *str,
|
||||
int indentBefore, int indentAfter, int indentPlus);
|
||||
static void removeStringInfoSpaces(StringInfo str);
|
||||
static void get_rule_expr(Node *node, deparse_context *context,
|
||||
bool showimplicit);
|
||||
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
||||
@ -4494,42 +4495,42 @@ get_target_list(List *targetList, deparse_context *context,
|
||||
/* Consider line-wrapping if enabled */
|
||||
if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
|
||||
{
|
||||
int leading_nl_pos = -1;
|
||||
char *trailing_nl;
|
||||
int pos;
|
||||
int leading_nl_pos;
|
||||
|
||||
/* 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 output buffer */
|
||||
trailing_nl = strrchr(buf->data, '\n');
|
||||
if (trailing_nl == NULL)
|
||||
trailing_nl = buf->data;
|
||||
/* Does the new field start with a new line? */
|
||||
if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
|
||||
leading_nl_pos = 0;
|
||||
else
|
||||
trailing_nl++;
|
||||
leading_nl_pos = -1;
|
||||
|
||||
/*
|
||||
* If the field we're adding is the first in the list, or it
|
||||
* already has a leading newline, 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 &&
|
||||
((strlen(trailing_nl) + strlen(targetbuf.data) > context->wrapColumn) ||
|
||||
last_was_multiline))
|
||||
appendContextKeyword(context, "", -PRETTYINDENT_STD,
|
||||
PRETTYINDENT_STD, PRETTYINDENT_VAR);
|
||||
/* If so, we shouldn't add anything */
|
||||
if (leading_nl_pos >= 0)
|
||||
{
|
||||
/* instead, remove any trailing spaces currently in buf */
|
||||
removeStringInfoSpaces(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *trailing_nl;
|
||||
|
||||
/* Locate the start of the current line in the output 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 the new field is
|
||||
* not the first and either the new field would cause an
|
||||
* overflow or the last field used more than one line.
|
||||
*/
|
||||
if (colno > 1 &&
|
||||
((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
|
||||
last_was_multiline))
|
||||
appendContextKeyword(context, "", -PRETTYINDENT_STD,
|
||||
PRETTYINDENT_STD, PRETTYINDENT_VAR);
|
||||
}
|
||||
|
||||
/* Remember this field's multiline status for next iteration */
|
||||
last_was_multiline =
|
||||
@ -6251,23 +6252,42 @@ static void
|
||||
appendContextKeyword(deparse_context *context, const char *str,
|
||||
int indentBefore, int indentAfter, int indentPlus)
|
||||
{
|
||||
StringInfo buf = context->buf;
|
||||
|
||||
if (PRETTY_INDENT(context))
|
||||
{
|
||||
context->indentLevel += indentBefore;
|
||||
|
||||
appendStringInfoChar(context->buf, '\n');
|
||||
appendStringInfoSpaces(context->buf,
|
||||
/* 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);
|
||||
appendStringInfoString(context->buf, str);
|
||||
|
||||
appendStringInfoString(buf, str);
|
||||
|
||||
context->indentLevel += indentAfter;
|
||||
if (context->indentLevel < 0)
|
||||
context->indentLevel = 0;
|
||||
}
|
||||
else
|
||||
appendStringInfoString(context->buf, str);
|
||||
appendStringInfoString(buf, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* removeStringInfoSpaces - delete trailing spaces from a buffer.
|
||||
*
|
||||
* Possibly this should move to stringinfo.c at some point.
|
||||
*/
|
||||
static void
|
||||
removeStringInfoSpaces(StringInfo str)
|
||||
{
|
||||
while (str->len > 0 && str->data[str->len - 1] == ' ')
|
||||
str->data[--(str->len)] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_rule_expr_paren - deparse expr using get_rule_expr,
|
||||
* embracing the string with parentheses if necessary for prettyPrint.
|
||||
@ -7929,22 +7949,33 @@ get_from_clause(Query *query, const char *prefix, deparse_context *context)
|
||||
/* Consider line-wrapping if enabled */
|
||||
if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
|
||||
{
|
||||
char *trailing_nl;
|
||||
|
||||
/* Locate the start of the current line in the buffer */
|
||||
trailing_nl = strrchr(buf->data, '\n');
|
||||
if (trailing_nl == NULL)
|
||||
trailing_nl = buf->data;
|
||||
/* Does the new item start with a new line? */
|
||||
if (itembuf.len > 0 && itembuf.data[0] == '\n')
|
||||
{
|
||||
/* If so, we shouldn't add anything */
|
||||
/* instead, remove any trailing spaces currently in buf */
|
||||
removeStringInfoSpaces(buf);
|
||||
}
|
||||
else
|
||||
trailing_nl++;
|
||||
{
|
||||
char *trailing_nl;
|
||||
|
||||
/*
|
||||
* Add a newline, plus some indentation, if the new item would
|
||||
* cause an overflow.
|
||||
*/
|
||||
if (strlen(trailing_nl) + strlen(itembuf.data) > context->wrapColumn)
|
||||
appendContextKeyword(context, "", -PRETTYINDENT_STD,
|
||||
PRETTYINDENT_STD, PRETTYINDENT_VAR);
|
||||
/* 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 the new item
|
||||
* would cause an overflow.
|
||||
*/
|
||||
if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
|
||||
appendContextKeyword(context, "", -PRETTYINDENT_STD,
|
||||
PRETTYINDENT_STD,
|
||||
PRETTYINDENT_VAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the new item */
|
||||
|
@ -960,10 +960,10 @@ select * from agg_view1;
|
||||
(1 row)
|
||||
|
||||
select pg_get_viewdef('agg_view1'::regclass);
|
||||
pg_get_viewdef
|
||||
----------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), +
|
||||
pg_get_viewdef
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
|
||||
generate_series(1, 3) i(i);
|
||||
(1 row)
|
||||
|
||||
@ -978,10 +978,10 @@ select * from agg_view1;
|
||||
(1 row)
|
||||
|
||||
select pg_get_viewdef('agg_view1'::regclass);
|
||||
pg_get_viewdef
|
||||
----------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.b) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), +
|
||||
pg_get_viewdef
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.b) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
|
||||
generate_series(1, 3) i(i);
|
||||
(1 row)
|
||||
|
||||
@ -1044,10 +1044,10 @@ select * from agg_view1;
|
||||
(1 row)
|
||||
|
||||
select pg_get_viewdef('agg_view1'::regclass);
|
||||
pg_get_viewdef
|
||||
----------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.a, v.c USING ~<~ NULLS LAST, v.b) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), +
|
||||
pg_get_viewdef
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.a, v.c USING ~<~ NULLS LAST, v.b) AS aggfns +
|
||||
FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
|
||||
generate_series(1, 2) i(i);
|
||||
(1 row)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user