diff --git a/lib/pgFormatter/Beautify.pm b/lib/pgFormatter/Beautify.pm index 61e8aaf..1b89eb8 100755 --- a/lib/pgFormatter/Beautify.pm +++ b/lib/pgFormatter/Beautify.pm @@ -1863,7 +1863,10 @@ sub beautify { and ( !defined $last or - ( $last ne ')' and $self->_next_token !~ /^(TIME|FUNCTION)/i ) + ( ( $last ne ')' + or ( $self->{'_current_sql_stmt'} eq 'INSERT' + and !$self->{'_parenthesis_level'} ) ) + and $self->_next_token !~ /^(TIME|FUNCTION)/i ) ) ) { @@ -1890,6 +1893,11 @@ sub beautify { $self->{'no_break'} = 1 if ( uc( $self->_next_token ) eq 'ORDINALITY' ); } + # Sibling CTEs and the final query inherit the enclosing block's level. + if ( $self->{'_is_in_with'} == 1 and !$self->{'_parenthesis_level'} ) { + $self->{_cte_base_level} = $self->{'_level'}; + $self->{_cte_base_stack} = [ @{ $self->{'_level_stack'} } ]; + } $self->{'_is_in_materialized'} = 0; } elsif ( $token =~ /^WITH$/i @@ -2013,15 +2021,12 @@ sub beautify { $self->{'_level'} = $self->{'_with_base_level'} if ( $self->{'_with_base_level'} ); } - $self->_add_token($token); - if ( !$self->{'_is_in_operator'} ) { - $self->_reset_level( $token, $last ); - # Same rationale for the continuation of the WITH clause - # (the next CTE after a comma, or the final query): resume - # at the WITH level, not at column 0. - $self->{'_level'} = $self->{'_with_base_level'} - if ( $self->{'_with_base_level'} ); + if ( !$self->{'_is_in_operator'} and defined $self->{_cte_base_level} ) { + $self->_set_level( $self->{_cte_base_level}, $token, $last ); + @{ $self->{'_level_stack'} } = @{ $self->{_cte_base_stack} }; + $self->{'content'} .= $self->_indent if ( $self->{'_new_line'} ); } + $self->_add_token($token); if ( $self->{'_is_in_with'} ) { if ( defined $self->_next_token && $self->_next_token eq ',' ) diff --git a/t/test-files/cte_indentation.sql b/t/test-files/cte_indentation.sql new file mode 100644 index 0000000..196b139 --- /dev/null +++ b/t/test-files/cte_indentation.sql @@ -0,0 +1,29 @@ +INSERT INTO results (id) +WITH first_cte AS (SELECT 1 AS id), +second_cte AS (SELECT id FROM first_cte) +SELECT id FROM second_cte; + +DO $$ +BEGIN +IF TRUE THEN +INSERT INTO results (id) +WITH first_cte AS (SELECT 1 AS id), +second_cte AS (SELECT id FROM first_cte) +SELECT id FROM second_cte; +ELSE +PERFORM 0; +END IF; +END +$$; + +DO $$ +BEGIN +IF TRUE THEN +WITH first_cte AS (SELECT 1 AS id), +second_cte AS (SELECT id FROM first_cte) +SELECT id FROM second_cte; +ELSE +PERFORM 0; +END IF; +END +$$; diff --git a/t/test-files/expected/cte_indentation.sql b/t/test-files/expected/cte_indentation.sql new file mode 100644 index 0000000..a80144e --- /dev/null +++ b/t/test-files/expected/cte_indentation.sql @@ -0,0 +1,65 @@ +INSERT INTO results (id) +WITH first_cte AS ( + SELECT + 1 AS id +), +second_cte AS ( + SELECT + id + FROM + first_cte +) +SELECT + id +FROM + second_cte; + +DO $$ +BEGIN + IF TRUE THEN + INSERT INTO results (id) + WITH first_cte AS ( + SELECT + 1 AS id + ), + second_cte AS ( + SELECT + id + FROM + first_cte + ) + SELECT + id + FROM + second_cte; + ELSE + PERFORM + 0; + END IF; +END +$$; + +DO $$ +BEGIN + IF TRUE THEN + WITH first_cte AS ( + SELECT + 1 AS id + ), + second_cte AS ( + SELECT + id + FROM + first_cte + ) + SELECT + id + FROM + second_cte; + ELSE + PERFORM + 0; + END IF; +END +$$; +