Skip to content

Commit

Permalink
Fix formatting of column name corresponding to keywords in INSERT and…
Browse files Browse the repository at this point in the history
… UPDATE statement. Thanks to Zoe Roux for the report.
  • Loading branch information
darold committed Nov 6, 2024
1 parent a7205ed commit 5c7463d
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 43 deletions.
26 changes: 18 additions & 8 deletions lib/pgFormatter/Beautify.pm
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ sub tokenize_sql
{
if ($query[$i] =~ /^[\d\.]+$/ && $query[$i-1] =~ /^[\+\-]$/
and ($query[$i-2] =~ /$math_operators/ or $query[$i-2] =~ /^(?:,|\(|\[)$/
or $self->_is_keyword( $query[$i-2]))
or $self->_is_keyword($query[$i-2]))
)
{
$query[$i] = $query[$i-1] . $query[$i];
Expand Down Expand Up @@ -761,8 +761,6 @@ sub _push_level
push(@{ $self->{ '_level_stack' } }, (($position >= 0) ? $position : 0));
}



sub _set_last
{
my ($self, $token, $last_token) = @_;
Expand Down Expand Up @@ -1607,7 +1605,7 @@ sub beautify
$self->_process_rule( $rule, $token );
}

elsif ($token =~ /^(LANGUAGE|SECURITY|COST)$/i && !$self->{ '_is_in_alter' } && !$self->{ '_is_in_drop' } )
elsif ($token =~ /^(LANGUAGE|SECURITY|COST)$/i && !$self->{ '_is_in_alter' } && !$self->{ '_is_in_drop' } && $last ne ',')
{
@{ $self->{ '_begin_level' } } = ();
$self->_new_line($token,$last) if (uc($token) ne 'SECURITY' or (defined $last and uc($last) ne 'LEVEL'));
Expand Down Expand Up @@ -2304,6 +2302,9 @@ sub beautify
if ($token =~ /^UPDATE$/i and $last =~ /^(FOR|KEY|DO)$/i)
{
$self->_add_token( $token );
if (uc($last) eq 'DO' && uc($self->_next_token) eq 'SET') {
$self->{ '_current_sql_stmt' } = 'UPDATE';
}
}
elsif (!$self->{ '_is_in_policy' } && $token !~ /^(DELETE|UPDATE)$/i && (!defined $self->_next_token || $self->_next_token !~ /^DISTINCT$/i))
{
Expand Down Expand Up @@ -2432,7 +2433,7 @@ sub beautify
push(@{ $self->{ '_is_in_case' } }, $self->{ '_level' });
}

elsif ( $token =~ /^(?:WHEN)$/i)
elsif ( $token =~ /^(?:WHEN)$/i && $self->_is_keyword($token, $self->_next_token(), $last))
{
if (!$self->{ '_first_when_in_case' } and !$self->{'_is_in_trigger'}
and defined $last and uc($last) ne 'CASE'
Expand Down Expand Up @@ -2497,7 +2498,6 @@ sub beautify

elsif ( $token =~ /^(?:ELSE|ELSIF)$/i )
{
# ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
if ($#{ $self->{ '_is_in_case' } } < 0) {
$self->_back($token, $last);
} else {
Expand Down Expand Up @@ -2882,6 +2882,7 @@ sub beautify

# Finally add the token without further condition
$self->_add_token( $token, $last );

if ($last eq "'" and $token =~ /^(BEGIN|DECLARE)$/i)
{
$last = $self->_set_last($token, $last);
Expand All @@ -2895,7 +2896,7 @@ sub beautify
{
$self->{ '_is_in_create' } = 0;
}
if (defined $last && uc($last) eq 'LANGUAGE' && (!defined $self->_next_token || $self->_next_token ne ';'))
if (defined $last && uc($last) eq 'LANGUAGE' && $self->_is_keyword( $last, $token ) && (!defined $self->_next_token || $self->_next_token ne ';'))
{
$self->_new_line($token,$last);
}
Expand Down Expand Up @@ -3367,16 +3368,25 @@ sub _is_keyword
{
my ( $self, $token, $next_token, $last_token ) = @_;

if ($DEBUG)
{
my ($package, $filename, $line) = caller;
print STDERR "DEBUG_KEYWORD: line: $line => last=", ($last_token||''), ", token=$token\n";
}

return 0 if (!$token);

# Remove cast if any
$token =~ s/::[^:]+$//;

$next_token //= '';

# Fix some false positive
if (defined $next_token)
{
return 0 if (uc($token) eq 'LEVEL' and uc($next_token) ne 'SECURITY');
return 0 if (uc($token) eq 'EVENT' and uc($next_token) ne 'TRIGGER');
return 0 if ($self->{ '_current_sql_stmt' } =~ /(INSERT|UPDATE)/ and $next_token =~ /^[,\)=]$/ and (not defined $last_token or $last_token =~ /^[,\(]$/) and $token !~ /^(TRUE|FALSE|DEFAULT|NULL|CURRENT_.*|LEXIZE|END)$/i);
}
return 0 if ($token =~ /^(LOGIN|RULE)$/i and !$self->{ '_is_in_create' } and !$self->{ '_is_in_alter' } and !$self->{ '_is_in_drop' } and !$self->{ '_is_in_rule' });
return 0 if (uc($token) eq 'COMMENT' and (not defined $next_token or $next_token) !~ /^ON|IS$/i);
Expand Down Expand Up @@ -3918,7 +3928,7 @@ sub set_dicts
FIRST FOLLOWING FOR FOREIGN FORWARD FREEZE FROM FULL FUNCTION GENERATED GRANT GROUP GROUPING HAVING HASHES HASH
IDENTITY IF ILIKE IMMUTABLE IN INCLUDING INCREMENT INDEX INHERITS INITIALLY INNER INOUT INSERT INSTEAD
INTERSECT INTO INVOKER IS ISNULL ISOLATION JOIN KEY LANGUAGE LAST LATERAL LC_COLLATE LC_CTYPE LEADING
LEAKPROOF LEFT LEFTARG LEVEL LIKE LIMIT LIST LISTEN LOAD LOCALTIME LOCALTIMESTAMP LOCK LOCKED LOGGED LOGIN
LEAKPROOF LEFT LEFTARG LEVEL LEXIZE LIKE LIMIT LIST LISTEN LOAD LOCALTIME LOCALTIMESTAMP LOCK LOCKED LOGGED LOGIN
LOOP MAPPING MATCH MAXVALUE MERGES MINVALUE MODULUS MOVE NATURAL NEXT NOTHING NOTICE ORDINALITY
NO NOCREATEDB NOCREATEROLE NOSUPERUSER NOT NOTIFY NOTNULL NOWAIT NULL OFF OF OIDS ON ONLY OPEN OPERATOR OR ORDER
OUTER OVER OVERLAPS OWNER PARTITION PASSWORD PERFORM PLACING POLICY PRECEDING PREPARE PRIMARY PROCEDURE RANGE
Expand Down
6 changes: 3 additions & 3 deletions t/pg-test-files/expected/alter_generic.sql
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,11 @@ ORDER BY
-- Text Search Template
--
CREATE TEXT SEARCH TEMPLATE alt_ts_temp1 (
lexize = dsimple_lexize
LEXIZE = dsimple_lexize
);

CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (
lexize = dsimple_lexize
LEXIZE = dsimple_lexize
);

ALTER TEXT SEARCH TEMPLATE alt_ts_temp1 RENAME TO alt_ts_temp2;
Expand All @@ -708,7 +708,7 @@ ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2;

-- OK
CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (
lexize = dsimple_lexize
LEXIZE = dsimple_lexize
);

ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2;
Expand Down
2 changes: 1 addition & 1 deletion t/pg-test-files/expected/alter_table.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3813,7 +3813,7 @@ CREATE text search configuration alter1.cfg (

CREATE text search TEMPLATE alter1.tmpl (
init = dsimple_init,
lexize = dsimple_lexize
LEXIZE = dsimple_lexize
);

CREATE text search dictionary alter1.dict (
Expand Down
13 changes: 9 additions & 4 deletions t/pg-test-files/expected/arrays.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1154,17 +1154,22 @@ INSERT INTO arr_pk_tbl
VALUES (1, '{3,4,5}')
ON CONFLICT (pk)
DO UPDATE SET
f1[1] = excluded.f1[1], f1[3] = excluded.f1[3]
f1[1] = excluded.f1[1],
f1[3] = excluded.f1[3]
RETURNING
pk, f1;
pk,
f1;

INSERT INTO arr_pk_tbl (pk, f1[1:2])
VALUES (1, '{6,7,8}')
ON CONFLICT (pk)
DO UPDATE SET
f1[1] = excluded.f1[1], f1[2] = excluded.f1[2], f1[3] = excluded.f1[3]
f1[1] = excluded.f1[1],
f1[2] = excluded.f1[2],
f1[3] = excluded.f1[3]
RETURNING
pk, f1;
pk,
f1;

-- note: if above selects don't produce the expected tuple order,
-- then you didn't get an indexscan plan, and something is busted.
Expand Down
34 changes: 25 additions & 9 deletions t/pg-test-files/expected/insert_conflict.sql
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ INSERT INTO insertconflicttest
(2, 'Orange')
ON CONFLICT (key)
DO UPDATE SET
(fruit, key) = (excluded.fruit, excluded.key);
(fruit,
key) = (excluded.fruit,
excluded.key);

-- Give good diagnostic message when EXCLUDED.* spuriously referenced from
-- RETURNING:
Expand Down Expand Up @@ -831,7 +833,8 @@ INSERT INTO cities
VALUES ('Las Vegas', 5.83E + 5, 2001)
ON CONFLICT (name)
DO UPDATE SET
population = excluded.population, altitude = excluded.altitude;
population = excluded.population,
altitude = excluded.altitude;

SELECT
tableoid::regclass,
Expand Down Expand Up @@ -864,7 +867,8 @@ INSERT INTO cities
VALUES ('Las Vegas', 5.86E + 5, 2223)
ON CONFLICT (name)
DO UPDATE SET
population = excluded.population, altitude = excluded.altitude;
population = excluded.population,
altitude = excluded.altitude;

SELECT
tableoid::regclass,
Expand Down Expand Up @@ -942,7 +946,10 @@ INSERT INTO dropcol (key, drop1, keep1, drop2, keep2)
VALUES (1, 2, '2', '2', 2)
ON CONFLICT (key)
DO UPDATE SET
drop1 = excluded.drop1, keep1 = excluded.keep1, drop2 = excluded.drop2, keep2 = excluded.keep2
drop1 = excluded.drop1,
keep1 = excluded.keep1,
drop2 = excluded.drop2,
keep2 = excluded.keep2
WHERE
excluded.drop1 IS NOT NULL
AND excluded.keep1 IS NOT NULL
Expand All @@ -962,7 +969,10 @@ INSERT INTO dropcol (key, drop1, keep1, drop2, keep2)
VALUES (1, 3, '3', '3', 3)
ON CONFLICT (key)
DO UPDATE SET
drop1 = dropcol.drop1, keep1 = dropcol.keep1, drop2 = dropcol.drop2, keep2 = dropcol.keep2
drop1 = dropcol.drop1,
keep1 = dropcol.keep1,
drop2 = dropcol.drop2,
keep2 = dropcol.keep2
RETURNING
*;

Expand All @@ -977,7 +987,8 @@ INSERT INTO dropcol (key, keep1, keep2)
VALUES (1, '4', 4)
ON CONFLICT (key)
DO UPDATE SET
keep1 = excluded.keep1, keep2 = excluded.keep2
keep1 = excluded.keep1,
keep2 = excluded.keep2
WHERE
excluded.keep1 IS NOT NULL
AND excluded.keep2 IS NOT NULL
Expand All @@ -993,7 +1004,8 @@ INSERT INTO dropcol (key, keep1, keep2)
VALUES (1, '5', 5)
ON CONFLICT (key)
DO UPDATE SET
keep1 = dropcol.keep1, keep2 = dropcol.keep2
keep1 = dropcol.keep1,
keep2 = dropcol.keep2
RETURNING
*;

Expand Down Expand Up @@ -1383,10 +1395,14 @@ INSERT INTO parted_conflict
VALUES (50, 'cincuenta', 2)
ON CONFLICT (a, b)
DO UPDATE SET
(a, b, c) = ROW (excluded.*)
(a,
b,
c) = ROW (excluded.*)
WHERE
parted_conflict = (50, text 'cincuenta', 1)
AND excluded = (50, text 'cincuenta', 2);
AND excluded = (50,
text 'cincuenta',
2);

-- should see (50, 'cincuenta', 2)
SELECT
Expand Down
2 changes: 1 addition & 1 deletion t/pg-test-files/expected/object_address.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ CREATE TEXT SEARCH CONFIGURATION addr_ts_conf (
);

CREATE TEXT SEARCH TEMPLATE addr_ts_temp (
lexize = dsimple_lexize
LEXIZE = dsimple_lexize
);

CREATE TEXT SEARCH PARSER addr_ts_prs (
Expand Down
3 changes: 2 additions & 1 deletion t/pg-test-files/expected/rules.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2585,7 +2585,8 @@ CREATE RULE hat_upsert AS ON INSERT TO hats
INSERT INTO hat_data VALUES (NEW.hat_name, NEW.hat_color)
ON CONFLICT (hat_name)
DO UPDATE SET
hat_name = hat_data.hat_name, hat_color = excluded.hat_color WHERE
hat_name = hat_data.hat_name,
hat_color = excluded.hat_color WHERE
excluded.hat_color <> 'forbidden'
AND hat_data.* != excluded.* RETURNING
*;
Expand Down
3 changes: 1 addition & 2 deletions t/pg-test-files/expected/subselect.sql
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,7 @@ CREATE RULE shipped_view_insert AS ON INSERT TO shipped_view
DO INSTEAD
INSERT INTO shipped VALUES ('wt', NEW.ordnum, NEW.partnum, NEW.value);

INSERT INTO parts (partnum,
COST)
INSERT INTO parts (partnum, cost)
VALUES (1, 1234.56);

INSERT INTO shipped_view (ordnum, partnum, value)
Expand Down
9 changes: 6 additions & 3 deletions t/pg-test-files/expected/update.sql
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ INSERT INTO upsert_test
VALUES (1, 'Bar')
ON CONFLICT (a)
DO UPDATE SET
(b, a) = (
(b,
a) = (
SELECT
b,
a
Expand All @@ -335,7 +336,8 @@ INSERT INTO upsert_test
VALUES (1, 'Baz')
ON CONFLICT (a)
DO UPDATE SET
(b, a) = (
(b,
a) = (
SELECT
b || ', Correlated',
a
Expand All @@ -351,7 +353,8 @@ INSERT INTO upsert_test
VALUES (1, 'Bat')
ON CONFLICT (a)
DO UPDATE SET
(b, a) = (
(b,
a) = (
SELECT
b || ', Excluded',
a
Expand Down
23 changes: 15 additions & 8 deletions t/pg-test-files/expected/with.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2163,7 +2163,9 @@ INSERT INTO withz
*
)
SELECT
* FROM t
*
FROM
t
JOIN y ON t.k = y.a
ORDER BY
a,
Expand All @@ -2179,11 +2181,12 @@ INSERT INTO withz
WHERE
withz.k != EXCLUDED.k
RETURNING
*)
SELECT
*
FROM
aa;
)
SELECT
*
FROM
aa;

-- New query/snapshot demonstrates side-effects of previous query.
SELECT
Expand Down Expand Up @@ -2283,7 +2286,9 @@ ON CONFLICT (k)
DO UPDATE SET
v = (
SELECT
b || ' update' FROM aa
b || ' update'
FROM
aa
WHERE
a = 1
LIMIT 1);
Expand All @@ -2301,7 +2306,8 @@ INSERT INTO withz
VALUES (2, 'Blue')
ON CONFLICT (k)
DO UPDATE SET
(k, v) = (
(k,
v) = (
SELECT
k,
v
Expand All @@ -2316,7 +2322,8 @@ INSERT INTO withz
VALUES (2, 'Red')
ON CONFLICT (k)
DO UPDATE SET
(k, v) = (
(k,
v) = (
SELECT
k,
v
Expand Down
14 changes: 14 additions & 0 deletions t/test-files/ex9.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,17 @@ WITH a1 AS (
SELECT * FROM test1
)
SELECT ROUND(AVG(t1)) avg_da, ROUND(AVG(t2)) FROM a1;

insert into videos(sha, idx, title, language, codec, mime_codec, width, height, is_default, bitrate)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
on conflict (sha, idx) do update set
sha = excluded.sha,
idx = excluded.idx,
title = excluded.title,
language = excluded.language,
codec = excluded.codec,
mime_codec = excluded.mime_codec,
width = excluded.width,
height = excluded.height,
is_default = excluded.is_default,
bitrate = excluded.bitrate;
Loading

0 comments on commit 5c7463d

Please sign in to comment.