diff --git a/lib/pgFormatter/Beautify.pm b/lib/pgFormatter/Beautify.pm index d5f5a6b..3929c9b 100755 --- a/lib/pgFormatter/Beautify.pm +++ b/lib/pgFormatter/Beautify.pm @@ -3940,10 +3940,15 @@ sub beautify { } $self->{'no_break'} = 0; if ( defined $self->_next_token - and $self->_next_token !~ /^(EXISTS|;)$/i ) + and ( $self->_next_token !~ /^(EXISTS|;)$/i + or ( uc($self->_next_token) eq 'EXISTS' + and defined $self->{'_tokens'}->[1] + and $self->{'_tokens'}->[1] eq '(' ) ) ) { if ( uc( $self->_next_token ) ne 'NOT' - || uc( $self->{'_tokens'}->[1] ) ne 'EXISTS' ) + || uc( $self->{'_tokens'}->[1] ) ne 'EXISTS' + || ( defined $self->{'_tokens'}->[2] + and $self->{'_tokens'}->[2] eq '(' ) ) { $self->_new_line( $token, $last ) if ( $token =~ /^LOOP$/i ); @@ -4179,7 +4184,9 @@ sub beautify { $self->{'_has_over_in_join'} = 1; } $self->{'_is_in_join'} = 0; - if ( !$self->{'_is_in_if'} + # Keep query predicates multiline inside procedural conditions. + if ( ( !$self->{'_is_in_if'} + or ( $self->{'_is_subquery'} and $self->{'_parenthesis_level'} ) ) and !$self->{'_is_in_index'} and !$self->{'_is_in_merge'} and ( not defined $last or $last !~ /^(?:CREATE)$/i ) diff --git a/t/pg-test-files/expected/opr_sanity.sql b/t/pg-test-files/expected/opr_sanity.sql index fe62725..ddde41a 100644 --- a/t/pg-test-files/expected/opr_sanity.sql +++ b/t/pg-test-files/expected/opr_sanity.sql @@ -38,8 +38,8 @@ BEGIN AND casttarget = $2 AND castmethod = 'b' AND castcontext = 'i') THEN - RETURN TRUE; -END IF; + RETURN TRUE; + END IF; IF $2 = 'pg_catalog.any'::pg_catalog.regtype THEN RETURN TRUE; END IF; @@ -53,9 +53,9 @@ END IF; oid = $1 AND typelem != 0 AND typlen = -1) THEN - RETURN TRUE; + RETURN TRUE; + END IF; END IF; -END IF; IF $2 = 'pg_catalog.anyrange'::pg_catalog.regtype THEN IF ( SELECT @@ -93,8 +93,8 @@ BEGIN castsource = $1 AND casttarget = $2 AND castmethod = 'b') THEN - RETURN TRUE; -END IF; + RETURN TRUE; + END IF; IF $2 = 'pg_catalog.any'::pg_catalog.regtype THEN RETURN TRUE; END IF; @@ -108,9 +108,9 @@ END IF; oid = $1 AND typelem != 0 AND typlen = -1) THEN - RETURN TRUE; + RETURN TRUE; + END IF; END IF; -END IF; IF $2 = 'pg_catalog.anyrange'::pg_catalog.regtype THEN IF ( SELECT diff --git a/t/test-files/ex85.sql b/t/test-files/ex85.sql index dc1be03..5c591d9 100644 --- a/t/test-files/ex85.sql +++ b/t/test-files/ex85.sql @@ -1,3 +1,21 @@ +-- Procedural existence checks must open an indentation level, unlike DDL guards. +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM widgets WHERE id = 1 AND enabled) THEN + IF EXISTS (SELECT 1 FROM other_widgets WHERE id = 1 OR id = 2) AND true THEN + EXECUTE $sql$SELECT 1;$sql$; + ELSE + RAISE NOTICE 'missing'; + END IF; + ELSE + PERFORM 2; + END IF; + PERFORM 3; +END +$$; + +CREATE TABLE IF NOT EXISTS widgets (id integer, enabled boolean); +DROP TABLE IF EXISTS widgets; SELECT 'a' 'b' AS lit FROM t; diff --git a/t/test-files/expected/ex85.sql b/t/test-files/expected/ex85.sql index 556c4e2..e62b61c 100644 --- a/t/test-files/expected/ex85.sql +++ b/t/test-files/expected/ex85.sql @@ -1,3 +1,41 @@ +-- Procedural existence checks must open an indentation level, unlike DDL guards. +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT + 1 + FROM + widgets + WHERE + id = 1 + AND enabled) THEN + IF EXISTS ( + SELECT + 1 + FROM + other_widgets + WHERE + id = 1 + OR id = 2) AND TRUE THEN + EXECUTE $sql$SELECT 1;$sql$; + ELSE + RAISE NOTICE 'missing'; + END IF; + ELSE + PERFORM + 2; + END IF; + PERFORM + 3; +END +$$; + +CREATE TABLE IF NOT EXISTS widgets ( + id integer, + enabled boolean +); + +DROP TABLE IF EXISTS widgets; SELECT 'a' 'b' AS lit