Skip to content

Commit

Permalink
fix: paramaters of type character and bit not ignoring length
Browse files Browse the repository at this point in the history
- Fixes the error "value too long for type character(1)" when the char length of the parameter was bigger than one.
  • Loading branch information
laurenceisla authored Jul 31, 2023
1 parent 0dc67be commit 40c2bcd
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 16 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #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.
- #2862, Fix null filtering on embedded resource when using a column name equal to the relation name - @steve-chave
- #2862, Fix null filtering on embedded resource when using a column name equal to the relation name - @steve-chavez
- #1586, Fix function parameters of type character and bit not ignoring length - @laurenceisla
+ Fixes the error "value too long for type character(1)" when the char length of the parameter was bigger than one.

## [11.1.0] - 2023-06-07

Expand Down
2 changes: 1 addition & 1 deletion src/PostgREST/Query/QueryBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar re
fromCall = case params of
OnePosParam prm -> "FROM " <> callIt (singleParameter args $ encodeUtf8 $ ppType prm)
KeyParams [] -> "FROM " <> callIt mempty
KeyParams prms -> fromJsonBodyF args ((\p -> CoercibleField (ppName p) mempty False (ppType p) Nothing Nothing) <$> prms) False True False <> ", " <>
KeyParams prms -> fromJsonBodyF args ((\p -> CoercibleField (ppName p) mempty False (ppTypeMaxLength p) Nothing Nothing) <$> prms) False True False <> ", " <>
"LATERAL " <> callIt (fmtParams prms)

callIt :: SQL.Snippet -> SQL.Snippet
Expand Down
4 changes: 2 additions & 2 deletions src/PostgREST/Response/OpenAPI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ makeProcSchema pd =
& required .~ fmap ppName (filter ppReq (pdParams pd))

makeProcProperty :: RoutineParam -> (Text, Referenced Schema)
makeProcProperty (RoutineParam n t _ _) = (n, Inline s)
makeProcProperty (RoutineParam n t _ _ _) = (n, Inline s)
where
s = (mempty :: Schema)
& type_ .~ toSwaggerType t
Expand All @@ -181,7 +181,7 @@ makePreferParam ts =
_ -> []

makeProcGetParam :: RoutineParam -> Referenced Param
makeProcGetParam (RoutineParam n t r v) =
makeProcGetParam (RoutineParam n t _ r v) =
Inline $ (mempty :: Param)
& name .~ n
& required ?~ r
Expand Down
8 changes: 8 additions & 0 deletions src/PostgREST/SchemaCache.hs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ decodeFuncs =
(RoutineParam
<$> compositeField HD.text
<*> compositeField HD.text
<*> compositeField HD.text
<*> compositeField HD.bool
<*> compositeField HD.bool)
<*> (parseRetType
Expand Down Expand Up @@ -367,6 +368,13 @@ funcsSqlQuery pgVer = [q|
array_agg((
COALESCE(name, ''), -- name
type::regtype::text, -- type
CASE type
WHEN 'bit'::regtype THEN 'bit varying'
WHEN 'bit[]'::regtype THEN 'bit varying[]'
WHEN 'character'::regtype THEN 'character varying'
WHEN 'character[]'::regtype THEN 'character varying[]'
ELSE type::regtype::text
END, -- convert types that ignore the lenth and accept any value till maximum size
idx <= (pronargs - pronargdefaults), -- is_required
COALESCE(mode = 'v', FALSE) -- is_variadic
) ORDER BY idx) AS args,
Expand Down
9 changes: 5 additions & 4 deletions src/PostgREST/SchemaCache/Routine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ instance JSON.ToJSON Routine where
]

data RoutineParam = RoutineParam
{ ppName :: Text
, ppType :: Text
, ppReq :: Bool
, ppVar :: Bool
{ ppName :: Text
, ppType :: Text
, ppTypeMaxLength :: Text
, ppReq :: Bool
, ppVar :: Bool
}
deriving (Eq, Show, Ord, Generic, JSON.ToJSON)

Expand Down
22 changes: 22 additions & 0 deletions test/spec/Feature/Query/RpcSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1447,3 +1447,25 @@ spec actualPgVersion =
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

-- https://github.com/PostgREST/postgrest/issues/1586#issuecomment-696345442
context "a proc with bit and char parameters" $ do
it "modifies the param type from character to character varying" $ do
get "/rpc/char_param_select?char_=abcdefg&char_arr={abc,abcdefg}" `shouldRespondWith`
[json| [{ "char_": "abcdefg", "char_arr": [ "abc", "abcdefg" ] }] |]
{ matchHeaders = [matchContentTypeJson] }

post "/rpc/char_param_insert" [json| { "char_": "abcdefg", "char_arr": "{abc,abcdefg}" } |]
`shouldRespondWith`
[json| {"code":"22001","details":null,"hint":null,"message":"value too long for type character(5)"} |]
{ matchStatus = 400 }

it "modifies the param type from bit to bit varying" $ do
get "/rpc/bit_param_select?bit_=101010&bit_arr={101,101010}" `shouldRespondWith`
[json| [{ "bit_": "101010", "bit_arr": [ "101", "101010" ] }] |]
{ matchHeaders = [matchContentTypeJson] }

post "/rpc/bit_param_insert" [json| { "bit_": "101010", "bit_arr": "{101,101010}" } |]
`shouldRespondWith`
[json| {"code":"22026","details":null,"hint":null,"message":"bit string length 6 does not match type bit(5)"} |]
{ matchStatus = 400 }
4 changes: 2 additions & 2 deletions test/spec/Feature/Query/UpdateSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,14 @@ spec actualPgVersion = do
-- 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"
request methodPatch "/bitchar_with_length?select=bit,char&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"
request methodPatch "/bitchar_with_length?select=bit,char&bit=eq.00000"
[("Prefer", "return=representation")]
[json|{"char": "zzzyy"}|]
`shouldRespondWith` [json|[{ "bit": "00000", "char": "zzzyy" }]|]
Expand Down
35 changes: 29 additions & 6 deletions test/spec/fixtures/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3303,12 +3303,6 @@ 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)
);

--- https://github.com/PostgREST/postgrest/issues/2862
create table profiles (
id uuid primary key,
Expand All @@ -3329,3 +3323,32 @@ create table tournaments(
id bigint primary key,
status bigint references status(id)
);

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

-- https://github.com/PostgREST/postgrest/issues/1586
create or replace function char_param_select(char_ char(4), char_arr char(4)[])
returns table(char_ char, char_arr char[]) as $$
select $1, $2;
$$ language sql;

create or replace function bit_param_select(bit_ char(4), bit_arr char(4)[])
returns table(bit_ char, bit_arr char[]) as $$
select $1, $2;
$$ language sql;

create or replace function char_param_insert(char_ char(4), char_arr char(4)[])
returns void as $$
insert into bitchar_with_length(char, char_arr) values($1, $2);
$$ language sql;

create or replace function bit_param_insert(bit_ bit(4), bit_arr bit(4)[])
returns void as $$
insert into bitchar_with_length(bit, bit_arr) values($1, $2);
$$ language sql;

0 comments on commit 40c2bcd

Please sign in to comment.