fix: hasSingleUnnamedParam incorrectly matching named parameters
The hasSingleUnnamedParam function was only checking the parameter type but not whether the parameter actually had no name. This caused functions with a single NAMED parameter (e.g., `foo(data json)`) to incorrectly match the single-param fallback mode. The result was a confusing PostgreSQL error 42883 "function does not exist" instead of a clean PGRST202 error explaining that no matching function was found. Added ppName == mempty check so functions with named parameters don't incorrectly match the single-param fallback.
This commit is contained in:
@@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fix `hasSingleUnnamedParam` incorrectly matching functions with named parameters by @joelonsql in #4553
|
||||||
|
+ Functions with a single named parameter (e.g., `foo(data json)`) no longer incorrectly match the single-param fallback, returning a clean `PGRST202` error instead of a confusing PostgreSQL `42883` error.
|
||||||
- Fix misleading logs on unsupported PostgreSQL versions by @taimoorzaeem in #4519
|
- Fix misleading logs on unsupported PostgreSQL versions by @taimoorzaeem in #4519
|
||||||
- Fix regression where the `PGRST103` error response was truncated by @laurenceisla in #4455
|
- Fix regression where the `PGRST103` error response was truncated by @laurenceisla in #4455
|
||||||
+ Happened when an `offset` was greater than the rows requested and `Prefer: count=exact` was sent.
|
+ Happened when an `offset` was greater than the rows requested and `Prefer: count=exact` was sent.
|
||||||
|
|||||||
+10
-8
@@ -256,14 +256,16 @@ findProc qi argumentsKeys allProcs contentMediaType isInvPost =
|
|||||||
| hasSingleUnnamedParam proc = (ts,proc:fs)
|
| hasSingleUnnamedParam proc = (ts,proc:fs)
|
||||||
| otherwise = (ts,fs)
|
| otherwise = (ts,fs)
|
||||||
-- If the function is called with post and has a single unnamed parameter
|
-- If the function is called with post and has a single unnamed parameter
|
||||||
-- it can be called depending on content type and the parameter type
|
-- it can be called depending on content type and the parameter type.
|
||||||
hasSingleUnnamedParam Function{pdParams=[RoutineParam{ppType}]} = isInvPost && case (contentMediaType, ppType) of
|
-- The parameter must have no declared name (ppName == mempty).
|
||||||
(MTApplicationJSON, "json") -> True
|
hasSingleUnnamedParam Function{pdParams=[RoutineParam{ppName, ppType}]} =
|
||||||
(MTApplicationJSON, "jsonb") -> True
|
isInvPost && ppName == mempty && case (contentMediaType, ppType) of
|
||||||
(MTTextPlain, "text") -> True
|
(MTApplicationJSON, "json") -> True
|
||||||
(MTTextXML, "xml") -> True
|
(MTApplicationJSON, "jsonb") -> True
|
||||||
(MTOctetStream, "bytea") -> True
|
(MTTextPlain, "text") -> True
|
||||||
_ -> False
|
(MTTextXML, "xml") -> True
|
||||||
|
(MTOctetStream, "bytea") -> True
|
||||||
|
_ -> False
|
||||||
hasSingleUnnamedParam _ = False
|
hasSingleUnnamedParam _ = False
|
||||||
matchesParams proc =
|
matchesParams proc =
|
||||||
let
|
let
|
||||||
|
|||||||
@@ -1146,12 +1146,24 @@ spec =
|
|||||||
}
|
}
|
||||||
|
|
||||||
context "single unnamed param" $ do
|
context "single unnamed param" $ do
|
||||||
it "can insert json directly" $
|
it "can insert json directly with unnamed parameter" $
|
||||||
post "/rpc/unnamed_json_param"
|
post "/rpc/unnamed_json_param"
|
||||||
[json|{"A": 1, "B": 2, "C": 3}|]
|
[json|{"A": 1, "B": 2, "C": 3}|]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|{"A": 1, "B": 2, "C": 3}|]
|
[json|{"A": 1, "B": 2, "C": 3}|]
|
||||||
|
|
||||||
|
it "rejects json body when single param has a name" $
|
||||||
|
post "/rpc/named_json_param"
|
||||||
|
[json|{"A": 1, "B": 2, "C": 3}|]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|{
|
||||||
|
"code":"PGRST202",
|
||||||
|
"message":"Could not find the function test.named_json_param(A, B, C) in the schema cache",
|
||||||
|
"details":"Searched for the function test.named_json_param with parameters A, B, C or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache.",
|
||||||
|
"hint":null
|
||||||
|
}|]
|
||||||
|
{ matchStatus = 404 }
|
||||||
|
|
||||||
it "can insert text directly" $ do
|
it "can insert text directly" $ do
|
||||||
request methodPost "/rpc/unnamed_text_param"
|
request methodPost "/rpc/unnamed_text_param"
|
||||||
[("Content-Type", "text/plain"), ("Accept", "text/plain")]
|
[("Content-Type", "text/plain"), ("Accept", "text/plain")]
|
||||||
|
|||||||
Vendored
+5
@@ -2356,6 +2356,11 @@ create or replace function test.unnamed_json_param(json) returns json as $$
|
|||||||
select $1;
|
select $1;
|
||||||
$$ language sql;
|
$$ language sql;
|
||||||
|
|
||||||
|
-- Function with a NAMED json parameter (for testing single param fallback behavior)
|
||||||
|
create or replace function test.named_json_param(data json) returns json as $$
|
||||||
|
select data;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
create or replace function test.unnamed_text_param(text) returns "text/plain" as $$
|
create or replace function test.unnamed_text_param(text) returns "text/plain" as $$
|
||||||
select $1::"text/plain";
|
select $1::"text/plain";
|
||||||
$$ language sql;
|
$$ language sql;
|
||||||
|
|||||||
Reference in New Issue
Block a user