From 0beffd127b4ef5e9caffd74b1efff87e40fb0799 Mon Sep 17 00:00:00 2001 From: Gilles Darold Date: Sat, 28 Mar 2020 19:19:35 +0100 Subject: [PATCH] Better indentation of subqueries inside a "WITH" clause. Thanks to Cyril Chaboisseau for the report. --- lib/pgFormatter/Beautify.pm | 20 ++- t/pg-test-files/expected/subselect.sql | 50 +++--- t/pg-test-files/expected/with.sql | 202 ++++++++++++------------- 3 files changed, 141 insertions(+), 131 deletions(-) diff --git a/lib/pgFormatter/Beautify.pm b/lib/pgFormatter/Beautify.pm index c3ce596..bd324bb 100755 --- a/lib/pgFormatter/Beautify.pm +++ b/lib/pgFormatter/Beautify.pm @@ -660,6 +660,7 @@ sub beautify $self->{ '_has_limit' } = 0; $self->{ '_not_a_type' } = 0; $self->{ 'stmt_number' } = 1; + $self->{ '_is_subquery' } = 0; my $last = ''; $self->tokenize_sql(); @@ -767,7 +768,7 @@ sub beautify # Control case where we have to add a newline, go back and # reset indentation after the last ) in the WITH statement #### - if ($token =~ /^WITH$/i && (!defined $last || $last ne ')') + if ($token =~ /^WITH$/i && (!defined $last or $last ne ')') && !$self->{ '_is_in_partition' } && !$self->{ '_is_in_publication' } && !$self->{ '_is_in_policy' } && uc($self->_next_token) ne 'TIME') { @@ -1292,6 +1293,7 @@ sub beautify $self->{ '_is_in_create' }++ if ($self->{ '_is_in_create' }); $self->{ '_is_in_constraint' }++ if ($self->{ '_is_in_constraint' }); $self->_add_token( $token, $last ); + $self->{ '_is_subquery' }++ if (defined $self->_next_token and uc($self->_next_token) eq 'SELECT'); if (defined $self->_next_token and $self->_next_token eq ')' and !$self->{ '_is_in_create' }) { $last = $self->_set_last($token, $last); next; @@ -1388,7 +1390,6 @@ sub beautify } if (defined $self->_next_token && $self->_next_token !~ /FILTER/i) { - my $add_nl = 0; $add_nl = 1 if ($self->{ '_is_in_create' } > 1 and defined $last and $last ne '(' @@ -1438,9 +1439,17 @@ sub beautify } # When closing CTE statement go back again - if ($self->_next_token =~ /^(?:SELECT|INSERT|UPDATE|DELETE)$/i && !$self->{ '_is_in_policy' }) { - $self->_back($token, $last) if ($self->{ '_current_sql_stmt' } ne 'INSERT'); - } + if ( ($self->_next_token =~ /^(?:SELECT|INSERT|UPDATE|DELETE)$/i and !$self->{ '_is_in_policy' }) + or ($self->{ '_is_in_with' } and $self->{ '_is_subquery' } + and $self->{ '_is_subquery' } % 2 == 0) ) { + $self->_back($token, $last) if ($self->{ '_current_sql_stmt' } ne 'INSERT' + and (!$self->{ '_parenthesis_level' } or !defined $self->_next_token + or uc($self->_next_token) eq 'AS' + or ($#{$self->{ '_tokens' }} >= 1 and $self->{ '_tokens' }->[ 1 ] eq ','))); + } + $self->{ '_is_subquery' }-- if ($self->{ '_is_subquery' } + and defined $self->_next_token and $#{$self->{ '_tokens' }} >= 1 + and (uc($self->_next_token) eq 'AS' or $self->{ '_tokens' }->[ 1 ] eq ',')); if ($self->{ '_is_in_create' } <= 1) { my $next_tok = quotemeta($self->_next_token); $self->_new_line($token,$last) @@ -1585,6 +1594,7 @@ sub beautify $self->{ '_is_in_returns_table' } = 0; $self->{ '_has_limit' } = 0; $self->{ '_not_a_type' } = 0; + $self->{ '_is_subquery' } = 0; if ( $self->{ '_insert_values' } ) { diff --git a/t/pg-test-files/expected/subselect.sql b/t/pg-test-files/expected/subselect.sql index 6895175..c8bb333 100644 --- a/t/pg-test-files/expected/subselect.sql +++ b/t/pg-test-files/expected/subselect.sql @@ -1821,13 +1821,13 @@ AS (( FROM x ) - SELECT - z.a || z1.a AS a - FROM - z - CROSS JOIN z AS z1 - WHERE - length(z.a || z1.a) < 5)) + SELECT + z.a || z1.a AS a + FROM + z + CROSS JOIN z AS z1 + WHERE + length(z.a || z1.a) < 5)) SELECT * FROM @@ -1872,12 +1872,12 @@ AS (( FROM x ) - SELECT - z.a || z.a AS a - FROM - z - WHERE - length(z.a || z.a) < 5)) + SELECT + z.a || z.a AS a + FROM + z + WHERE + length(z.a || z.a) < 5)) SELECT * FROM @@ -1926,10 +1926,10 @@ FROM ( WITH y AS ( FROM x ) - SELECT - * - FROM - y) ss; + SELECT + * + FROM + y) ss; EXPLAIN ( VERBOSE, @@ -1948,10 +1948,10 @@ FROM ( WITH y AS ( FROM x ) - SELECT - * - FROM - y) ss; + SELECT + * + FROM + y) ss; -- Ensure that we inline the currect CTE when there are -- multiple CTEs with the same name @@ -1969,10 +1969,10 @@ FROM ( WITH x AS ( SELECT 2 AS y ) - SELECT - * - FROM - x) ss; + SELECT + * + FROM + x) ss; -- Row marks are not pushed into CTEs EXPLAIN ( diff --git a/t/pg-test-files/expected/with.sql b/t/pg-test-files/expected/with.sql index 0b90bf2..656da6e 100644 --- a/t/pg-test-files/expected/with.sql +++ b/t/pg-test-files/expected/with.sql @@ -27,15 +27,15 @@ FROM ( WITH q1 ( random() FROM generate_series(1, 5)) - SELECT - * - FROM - q1 - UNION - SELECT - * - FROM - q1) ss; + SELECT + * + FROM + q1 + UNION + SELECT + * + FROM + q1) ss; -- WITH RECURSIVE -- sum of 1..100 @@ -382,10 +382,10 @@ FROM ( WITH RECURSIVE t ( WHERE n < 500 ) - SELECT - * - FROM - t) AS t + SELECT + * + FROM + t) AS t WHERE n < ( SELECT @@ -403,14 +403,14 @@ WHERE WHERE n < 100 ) - SELECT - * - FROM - t + SELECT + * + FROM + t + WHERE + n < 50000) AS t WHERE - n < 50000) AS t - WHERE - n < 100); + n < 100); -- use same CTE twice at different subquery levels WITH q1 ( @@ -507,10 +507,10 @@ WITH RECURSIVE q AS ( FROM q ) - SELECT - * - FROM - x)) + SELECT + * + FROM + x)) SELECT * FROM @@ -537,10 +537,10 @@ WITH RECURSIVE q AS ( * FROM x)) - SELECT - * - FROM - x)) + SELECT + * + FROM + x)) SELECT * FROM @@ -1560,14 +1560,14 @@ SELECT foo ) AS ( VALUES (f1)) - SELECT - ( - SELECT - foo - FROM - cte)) - FROM - int4_tbl; + SELECT + ( + SELECT + foo + FROM + cte)) + FROM + int4_tbl; SELECT ( WITH cte ( @@ -1600,23 +1600,23 @@ WITH RECURSIVE t ( s WHERE i < 10 +) + SELECT + i + FROM + s + UNION ALL + SELECT + j + 1 + FROM + t + WHERE + j < 10 ) SELECT - i - FROM - s - UNION ALL - SELECT - j + 1 + * FROM - t - WHERE - j < 10 -) -SELECT - * -FROM - t; + t; -- -- test WITH attached to intermediate-level set operation @@ -1631,13 +1631,13 @@ WITH outermost ( SELECT 2 ) - SELECT - * - FROM - innermost - UNION - SELECT - 3)) + SELECT + * + FROM + innermost + UNION + SELECT + 3)) SELECT * FROM @@ -1654,15 +1654,15 @@ WITH outermost ( SELECT 2 ) - SELECT - * - FROM - outermost -- fail - UNION - SELECT - * - FROM - innermost)) + SELECT + * + FROM + outermost -- fail + UNION + SELECT + * + FROM + innermost)) SELECT * FROM @@ -1679,15 +1679,15 @@ WITH RECURSIVE outermost ( SELECT 2 ) - SELECT - * - FROM - outermost - UNION - SELECT - * - FROM - innermost)) + SELECT + * + FROM + outermost + UNION + SELECT + * + FROM + innermost)) SELECT * FROM @@ -1734,15 +1734,15 @@ WITH A AS ( ( SELECT q1) AS x - FROM - int8_tbl + FROM + int8_tbl ), B AS ( SELECT id, row_number() OVER (PARTITION BY id) AS r - FROM - A +FROM + A ), C AS ( SELECT @@ -1809,15 +1809,15 @@ iter ( WHERE e.row_type = 'false' ) - SELECT - * - FROM - first_remaining - UNION ALL - SELECT - * - FROM - effect)) + SELECT + * + FROM + first_remaining + UNION ALL + SELECT + * + FROM + effect)) SELECT * FROM @@ -1866,15 +1866,15 @@ iter ( WHERE e.row_type = 'false' ) - SELECT - * - FROM - first_remaining - UNION ALL - SELECT - * - FROM - effect)) + SELECT + * + FROM + first_remaining + UNION ALL + SELECT + * + FROM + effect)) SELECT * FROM @@ -2621,10 +2621,10 @@ FROM ( WITH t AS ( RETURNING * ) - SELECT - * - FROM - t) ss; + SELECT + * + FROM + t) ss; -- most variants of rules aren't allowed CREATE RULE y_rule AS ON INSERT TO y WHERE