Skip to content

Commit

Permalink
fix: character and bit columns with fixed length not inserting/updati…
Browse files Browse the repository at this point in the history
…ng properly

Fixes the error "value too long for type character(1)" when the char length of the column was bigger than one.
  • Loading branch information
laurenceisla authored Jul 21, 2023
1 parent 28d5278 commit 630e0a1
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2840, Fix `Prefer: missing=default` with DOMAIN default values - @steve-chavez
- #2849, Fix HEAD unnecessarily executing aggregates - @steve-chavez
- #2594, Fix unused index on jsonb/jsonb arrow filter and order (``/bets?data->>contractId=eq.1`` and ``/bets?order=data->>contractId``) - @steve-chavez
- #2861, Fix character and bit columns with fixed length not inserting/updating properly - @laurenceisla
+ Fixes the error "value too long for type character(1)" when the char length of the column was bigger than one.

## [11.1.0] - 2023-06-07

Expand Down
26 changes: 13 additions & 13 deletions src/PostgREST/SchemaCache.hs
Original file line number Diff line number Diff line change
Expand Up @@ -573,19 +573,19 @@ tablesSqlQuery pgVer =
d.description AS description,
|] <> columnDefault <> [q| AS column_default,
not (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS is_nullable,
CASE
WHEN t.typtype = 'd' THEN
CASE
WHEN nbt.nspname = 'pg_catalog'::name THEN format_type(t.typbasetype, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
ELSE
CASE
WHEN t.typtype = 'd' THEN
CASE
WHEN nbt.nspname = 'pg_catalog'::name THEN format_type(t.typbasetype, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
ELSE
CASE
WHEN nt.nspname = 'pg_catalog'::name THEN format_type(a.atttypid, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
END::text AS data_type,
t.oid AS data_type_id,
WHEN nt.nspname = 'pg_catalog'::name THEN format_type(a.atttypid, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
END::text AS data_type,
format_type(a.atttypid, a.atttypmod)::text AS nominal_data_type,
information_schema._pg_char_max_length(
information_schema._pg_truetypid(a.*, t.*),
information_schema._pg_truetypmod(a.*, t.*)
Expand Down Expand Up @@ -627,7 +627,7 @@ tablesSqlQuery pgVer =
info.description,
info.is_nullable::boolean,
info.data_type,
info.data_type_id::regtype::text,
info.nominal_data_type,
info.character_maximum_length,
info.column_default,
coalesce(enum_info.vals, '{}')) order by info.position) as columns
Expand Down
16 changes: 16 additions & 0 deletions test/spec/Feature/Query/InsertSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,22 @@ spec actualPgVersion = do
`shouldRespondWith` [json|[{ id: 20 }]|]
{ matchStatus = 201 }

-- https://github.com/PostgREST/postgrest/issues/2861
context "bit and char columns with length" $ do
it "should insert to a bit column with length" $
request methodPost "/bitchar_with_length?select=bit"
[("Prefer", "return=representation")]
[json|{"bit": "10101"}|]
`shouldRespondWith` [json|[{ "bit": "10101" }]|]
{ matchStatus = 201 }

it "should insert to a char column with length" $
request methodPost "/bitchar_with_length?select=char"
[("Prefer", "return=representation")]
[json|{"char": "abcde"}|]
`shouldRespondWith` [json|[{ "char": "abcde" }]|]
{ matchStatus = 201 }

context "POST with ?columns parameter" $ do
it "ignores json keys not included in ?columns" $ do
request methodPost "/articles?columns=id,body" [("Prefer", "return=representation")]
Expand Down
16 changes: 16 additions & 0 deletions test/spec/Feature/Query/UpdateSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,22 @@ spec actualPgVersion = do
, matchHeaders = ["Preference-Applied" <:> "missing=default"]
}

-- https://github.com/PostgREST/postgrest/issues/2861
context "bit and char columns with length" $ do
it "should update a bit column with length" $
request methodPatch "/bitchar_with_length?char=eq.aaaaa"
[("Prefer", "return=representation")]
[json|{"bit": "11100"}|]
`shouldRespondWith` [json|[{ "bit": "11100", "char": "aaaaa" }]|]
{ matchStatus = 200 }

it "should update a char column with length" $
request methodPatch "/bitchar_with_length?bit=eq.00000"
[("Prefer", "return=representation")]
[json|{"char": "zzzyy"}|]
`shouldRespondWith` [json|[{ "bit": "00000", "char": "zzzyy" }]|]
{ matchStatus = 200 }

context "tables with self reference foreign keys" $ do
context "embeds children after update" $ do
it "without filters" $
Expand Down
4 changes: 4 additions & 0 deletions test/spec/fixtures/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -849,3 +849,7 @@ INSERT INTO datarep_todos VALUES (4, 'Opus Magnum', NULL, NULL);
TRUNCATE TABLE datarep_next_two_todos CASCADE;
INSERT INTO datarep_next_two_todos VALUES (1, 2, 3, 'school related');
INSERT INTO datarep_next_two_todos VALUES (2, 1, 3, 'do these first');

TRUNCATE TABLE bitchar_with_length CASCADE;
INSERT INTO bitchar_with_length(bit, char) VALUES ('00000', 'aaaaa');
INSERT INTO bitchar_with_length(bit, char) VALUES ('11111', 'bbbbb');
6 changes: 6 additions & 0 deletions test/spec/fixtures/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3302,3 +3302,9 @@ create table bets (

create index bets_data_json on bets ((data_json ->>'contractId'));
create index bets_data_jsonb on bets ((data_jsonb ->>'contractId'));

-- https://github.com/PostgREST/postgrest/issues/2861
CREATE TABLE bitchar_with_length (
bit bit(5),
char char(5)
);

0 comments on commit 630e0a1

Please sign in to comment.