Skip to content

Commit 53dd197

Browse files
committed
Add formatting of MERGE requests. Thanks to Ole Peder Brandtzaeg for the report.
1 parent eefdb07 commit 53dd197

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

lib/pgFormatter/Beautify.pm

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,7 @@ sub beautify {
893893
$self->{'_is_in_block'} = -1;
894894
$self->{'_is_in_work'} = 0;
895895
$self->{'_is_in_function'} = 0;
896+
$self->{'_is_in_merge'} = 0;
896897
$self->{'_current_function'} = '';
897898
$self->{'_is_in_statistics'} = 0;
898899
$self->{'_is_in_cast'} = 0;
@@ -1343,6 +1344,7 @@ sub beautify {
13431344
{
13441345
if ( $self->{'_current_sql_stmt'} !~ /^(GRANT|REVOKE)$/i
13451346
and !$self->{'_is_in_trigger'}
1347+
and !$self->{'_is_in_merge'}
13461348
and !$self->{'_is_in_operator'}
13471349
and !$self->{'_is_in_alter'} )
13481350
{
@@ -1354,7 +1356,7 @@ sub beautify {
13541356
}
13551357
}
13561358
}
1357-
if ( $self->{'_current_sql_stmt'} =~ /^(INSERT|DELETE|UPDATE|SELECT)$/i ) {
1359+
if ( $self->{'_current_sql_stmt'} =~ /^(INSERT|DELETE|UPDATE|SELECT|MERGE)$/i ) {
13581360
$self->{'_current_full_sql_stmt'} = "$self->{'_current_sql_stmt'} ";
13591361
for (my $i = 0; $i <= $#{ $self->{'_tokens'} }; $i++) {
13601362
last if ($self->{'_tokens'}[$i] eq ';');
@@ -1485,6 +1487,13 @@ sub beautify {
14851487
$self->{'_is_in_create_schema'}++;
14861488
}
14871489
}
1490+
elsif ( $token =~ /^MERGE$/i
1491+
and defined $self->_next_token
1492+
&& $self->_next_token =~ /^INTO/i )
1493+
{
1494+
$self->{'_is_in_merge'} = 1;
1495+
$self->{'_current_sql_stmt'} = 'MERGE';
1496+
}
14881497

14891498
if ( $self->{'_is_in_using'}
14901499
and defined $self->_next_token
@@ -2366,6 +2375,7 @@ sub beautify {
23662375
and !$self->{'_is_in_over'}
23672376
and !$self->{'_is_in_cast'}
23682377
and !$self->{'_is_in_domain'}
2378+
and !$self->{'_is_in_merge'}
23692379
);
23702380
}
23712381
}
@@ -2471,10 +2481,11 @@ sub beautify {
24712481
if ( defined $self->_next_token
24722482
and $self->_next_token =~ /KEYWCONST/ and $#{$self->{'_tokens'}} >= 1
24732483
and $self->{'_tokens'}[1] =~ /^(LANGUAGE|STRICT)$/i );
2474-
$add_newline = 1 if ( $self->{'_is_in_truncate'} );
2484+
$add_newline = 1 if ( $self->{'_is_in_truncate'});
24752485
if (
24762486
$add_newline
24772487
and $self->{'comma'} eq 'end'
2488+
and !$self->{'_is_in_merge'}
24782489
and ( $self->{'comma_break'}
24792490
|| ($self->{'_current_sql_stmt'} ne 'INSERT'
24802491
&& ($self->{'_current_sql_stmt'} ne 'DO UPDATE'
@@ -2523,6 +2534,7 @@ sub beautify {
25232534
$self->{'_is_in_create'} = 0;
25242535
$self->{'_is_in_create_schema'} = 0;
25252536
$self->{'_is_in_alter'} = 0;
2537+
$self->{'_is_in_merge'} = 0;
25262538
$self->{'_is_in_rule'} = 0;
25272539
$self->{'_is_in_publication'} = 0;
25282540
$self->{'_is_in_call'} = 0;
@@ -2767,7 +2779,7 @@ sub beautify {
27672779
$self->{'_is_in_index'} = 0;
27682780
$self->{'_is_in_from'} = 0;
27692781
$self->_add_token($token);
2770-
$self->_new_line( $token, $last );
2782+
$self->_new_line( $token, $last ) if (!$self->{'_is_in_merge'});
27712783
$self->_over( $token, $last );
27722784
$last = $self->_set_last( $token, $last );
27732785
next;
@@ -2800,8 +2812,8 @@ sub beautify {
28002812
$self->_over( $token, $last );
28012813
}
28022814
$self->_new_line( $token, $last )
2803-
if (
2804-
!$self->{'_is_in_rule'}
2815+
if ( !$self->{'_is_in_rule'}
2816+
and !$self->{'_is_in_merge'}
28052817
and
28062818
( $last !~ /^DEFAULT$/i or $self->_next_token() ne ';' )
28072819
);
@@ -2836,6 +2848,7 @@ sub beautify {
28362848
$token =~ /^VALUES$/i
28372849
and !$self->{'_is_in_rule'}
28382850
and !$self->{'comma_break'}
2851+
and !$self->{'_is_in_merge'}
28392852
and ( $self->{'_current_sql_stmt'} eq 'INSERT' or $last eq '(' )
28402853
)
28412854
{
@@ -2849,7 +2862,7 @@ sub beautify {
28492862
}
28502863
}
28512864

2852-
if ( $token =~ /^VALUES$/i and $last eq '(' ) {
2865+
if ( !$self->{'_is_in_merge'} and $token =~ /^VALUES$/i and $last eq '(' ) {
28532866
$self->{'_is_in_value'} = 1;
28542867
}
28552868

@@ -2913,6 +2926,12 @@ sub beautify {
29132926
$self->_over( $token, $last );
29142927
}
29152928

2929+
if ( $token =~ /^(UPDATE|DELETE|INSERT)$/i
2930+
&& $self->{'_is_in_merge'} )
2931+
{
2932+
$self->_over( $token, $last ) if ($self->{'_level_stack'}[-1]+1 != $self->{'_level'});
2933+
}
2934+
29162935
# case of ON DELETE/UPDATE clause in create table statements
29172936
if ( $token =~ /^(UPDATE|DELETE)$/i && $self->{'_is_in_create'} ) {
29182937
$self->_add_token($token);
@@ -2945,7 +2964,7 @@ sub beautify {
29452964
$self->_new_line( $token, $last );
29462965
}
29472966
$self->_add_token($token);
2948-
if ( $self->{'_is_in_policy'} > 1 ) {
2967+
if ( $self->{'_is_in_policy'} > 1) {
29492968
$self->_new_line( $token, $last );
29502969
$self->_over( $token, $last );
29512970
}
@@ -3057,7 +3076,7 @@ sub beautify {
30573076
if ( defined $last && $last =~ /^(?:GROUP|ORDER)/i );
30583077
if ( !$self->{'_has_order_by'} and !$self->{'_is_in_over'} ) {
30593078
$self->_new_line( $token, $last )
3060-
if ( !$self->{'wrap_after'} and !$self->{'_is_in_function'} );
3079+
if ( !$self->{'wrap_after'} and !$self->{'_is_in_function'} and !$self->{'_is_in_merge'} );
30613080
$self->_over( $token, $last );
30623081
}
30633082
}
@@ -3085,8 +3104,15 @@ sub beautify {
30853104
elsif ($token =~ /^(?:WHEN)$/i
30863105
&& $self->_is_keyword( $token, $self->_next_token(), $last ) )
30873106
{
3107+
if ($self->{'_is_in_merge'})
3108+
{
3109+
$self->_set_level( $self->{'_level_stack'}[-1], $token, $last );
3110+
$self->_push_level( $self->{'_level'}, $token, $last ) if ($self->{'_is_in_merge'} == 1);
3111+
$self->{'_is_in_merge'}++;
3112+
}
30883113
if ( !$self->{'_first_when_in_case'}
30893114
and !$self->{'_is_in_trigger'}
3115+
and !$self->{'_is_in_merge'}
30903116
and defined $last
30913117
and uc($last) ne 'CASE' )
30923118
{
@@ -3097,7 +3123,6 @@ sub beautify {
30973123
}
30983124
elsif ( $#{ $self->{'_begin_level'} } >= 0 ) {
30993125

3100-
#$self->_set_level($self->{ '_begin_level' }[-1]+1, $token, $last);
31013126
$self->_set_level( $self->{'_begin_level'}[-1] + 1,
31023127
$token, $last );
31033128
}
@@ -3106,7 +3131,8 @@ sub beautify {
31063131
if ( not defined $last or $last !~ /^(CASE|,|\()$/i );
31073132
$self->_add_token($token);
31083133
if ( $#{ $self->{'_is_in_case'} } < 0
3109-
&& !$self->{'_is_in_trigger'} )
3134+
and !$self->{'_is_in_merge'}
3135+
and !$self->{'_is_in_trigger'} )
31103136
{
31113137
$self->_over( $token, $last );
31123138
}
@@ -3365,6 +3391,7 @@ sub beautify {
33653391
$self->{'_is_in_join'} = 0;
33663392
if ( !$self->{'_is_in_if'}
33673393
and !$self->{'_is_in_index'}
3394+
and !$self->{'_is_in_merge'}
33683395
and ( not defined $last or $last !~ /^(?:CREATE)$/i )
33693396
and ( $self->{'_is_in_create'} <= 2 )
33703397
and !$self->{'_is_in_trigger'} )
@@ -3387,8 +3414,9 @@ sub beautify {
33873414
$self->_over( $token, $last );
33883415
}
33893416
}
3417+
$self->_over( $token, $last ) if ($self->{'_is_in_merge'});
33903418
$self->_add_token($token);
3391-
$self->{'_and_level'}++;
3419+
$self->{'_and_level'}++ if (!$self->{'_is_in_merge'});
33923420
}
33933421

33943422
elsif ( $token =~ /^\/\*.*\*\/$/s ) {
@@ -3415,9 +3443,18 @@ sub beautify {
34153443
}
34163444
}
34173445

3446+
elsif ($self->{'_is_in_merge'} && $token =~ /^(WHEN|USING)$/i)
3447+
{
3448+
$self->_over( $token, $last ) if ($token =~ /^USING$/i);
3449+
$self->_new_line( $token, $last );
3450+
$self->_add_token($token);
3451+
next;
3452+
}
3453+
34183454
elsif (
34193455
(
34203456
$token =~ /^USING$/i
3457+
and !$self->{'_is_in_merge'}
34213458
and !$self->{'_is_in_order_by'}
34223459
and !$self->{'_is_in_exception'}
34233460
and ( $self->{'_current_sql_stmt'} ne 'DELETE'
@@ -3693,6 +3730,12 @@ sub beautify {
36933730
$self->_new_line( $token, $last );
36943731
}
36953732

3733+
if ( $token =~ /^(UPDATE|DELETE|INSERT)$/i
3734+
&& $self->{'_is_in_merge'} )
3735+
{
3736+
$self->_over( $token, $last ) if ($self->{'_level_stack'}[-1]+1 != $self->{'_level'});
3737+
}
3738+
36963739
# Finally add the token without further condition
36973740
$self->_add_token( $token, $last );
36983741

t/02_regress.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use Test::Simple tests => 80;
1+
use Test::Simple tests => 81;
22
use File::Temp qw/ tempfile /;
33

44
my $pg_format = $ENV{PG_FORMAT} // './pg_format'; # set to the full path to 'pg_format' to test installed binary in /usr/bin

t/test-files/ex79.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
MERGE INTO wines w
2+
USING new_wine_list s
3+
ON s.winename = w.winename
4+
WHEN NOT MATCHED BY TARGET THEN
5+
INSERT VALUES(s.winename, s.stock)
6+
WHEN MATCHED AND w.stock != s.stock THEN
7+
UPDATE SET stock = s.stock
8+
WHEN NOT MATCHED BY SOURCE THEN
9+
DELETE;
10+
11+
MERGE INTO rw_view14 AS t
12+
USING (VALUES (2, 'Merged row 2'), (3, 'Merged row 3')) AS v(a,b) ON t.a = v.a
13+
WHEN MATCHED THEN UPDATE SET b = v.b
14+
WHEN NOT MATCHED THEN INSERT (a,b) VALUES (v.a, v.b);

t/test-files/expected/ex79.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
MERGE INTO wines w
2+
USING new_wine_list s ON s.winename = w.winename
3+
WHEN NOT MATCHED BY TARGET THEN
4+
INSERT VALUES (s.winename, s.stock)
5+
WHEN MATCHED AND w.stock != s.stock THEN
6+
UPDATE SET stock = s.stock
7+
WHEN NOT MATCHED BY SOURCE THEN
8+
DELETE;
9+
10+
MERGE INTO rw_view14 AS t
11+
USING ( VALUES (2, 'Merged row 2'), (3, 'Merged row 3')) AS v (a, b) ON t.a = v.a
12+
WHEN MATCHED THEN
13+
UPDATE SET b = v.b
14+
WHEN NOT MATCHED THEN
15+
INSERT (a, b) VALUES (v.a, v.b);
16+

0 commit comments

Comments
 (0)