feat: null filters on embedded resources

This commit is contained in:
steve-chavez
2022-12-12 17:14:54 -05:00
committed by Steve Chavez
parent 52c011f896
commit 3773cce246
7 changed files with 169 additions and 3 deletions
+33
View File
@@ -299,6 +299,39 @@ spec actualPgVersion = do
liftIO $ planCost r `shouldSatisfy` (< 70.9)
context "!inner vs embed not null" $ do
it "on an o2m, an !inner has a similar cost to not.null" $ do
r1 <- request methodGet "/clients?select=*,projects!inner(*)&id=eq.1"
[planHdr] ""
liftIO $ planCost r1 `shouldSatisfy` (< 33.3)
r2 <- request methodGet "/clients?select=*,projects(*)&projects=not.is.null&id=eq.1"
[planHdr] ""
liftIO $ planCost r2 `shouldSatisfy` (< 33.3)
it "on an m2o, an !inner has a similar cost to not.null" $ do
r1 <- request methodGet "/projects?select=*,clients!inner(*)&id=eq.1"
[planHdr] ""
liftIO $ planCost r1 `shouldSatisfy` (< 16.42)
r2 <- request methodGet "/projects?select=*,clients(*)&clients=not.is.null&id=eq.1"
[planHdr] ""
liftIO $ planCost r2 `shouldSatisfy` (< 16.42)
it "on an m2m, an !inner has a similar cost to not.null" $ do
r1 <- request methodGet "/users?select=*,tasks!inner(*)&tasks.id=eq.1"
[planHdr] ""
liftIO $ planCost r1 `shouldSatisfy` (< 20876.14)
r2 <- request methodGet "/users?select=*,tasks(*)&tasks.id=eq.1&tasks=not.is.null"
[planHdr] ""
liftIO $ planCost r2 `shouldSatisfy` (< 20876.14)
describe "function call costs" $ do
it "should not exceed cost when calling setof composite proc" $ do
+98 -2
View File
@@ -10,8 +10,8 @@ import Protolude hiding (get)
import SpecHelper
spec :: SpecWith ((), Application)
spec =
describe "related orders" $ do
spec = describe "related queries" $ do
context "related orders" $ do
it "works on a many-to-one relationship" $ do
get "/projects?select=id,clients(name)&order=clients(name).nullsfirst" `shouldRespondWith`
[json|[
@@ -148,3 +148,99 @@ spec =
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}
context "related conditions through null operator on embed" $ do
it "works on a many-to-one relationship" $ do
get "/projects?select=name,clients()&clients=not.is.null" `shouldRespondWith`
[json|[
{"name":"Windows 7"},
{"name":"Windows 10"},
{"name":"IOS"},
{"name":"OSX"}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/projects?select=name,clients()&clients=is.null" `shouldRespondWith`
[json|[{"name":"Orphan"}]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/projects?select=name,computed_clients()&computed_clients=is.null" `shouldRespondWith`
[json|[{"name":"Orphan"}]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
it "works on a one-to-many relationship" $ do
get "/entities?select=name,child_entities()&child_entities=not.is.null" `shouldRespondWith`
[json|[
{"name":"entity 1"},
{"name":"entity 2"}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/entities?select=name,child_entities()&child_entities=is.null" `shouldRespondWith`
[json|[
{"name":"entity 3"},
{"name":null}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/entities?select=name,childs:child_entities()&childs=is.null" `shouldRespondWith`
[json|[
{"name":"entity 3"},
{"name":null}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
it "works on a many-to-many relationship" $ do
get "/users?select=name,tasks()&tasks.id=eq.1&tasks=not.is.null" `shouldRespondWith`
[json|[
{"name":"Angela Martin"},
{"name":"Dwight Schrute"}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
get "/users?select=name,tasks()&tasks.id=eq.1&tasks=is.null" `shouldRespondWith`
[json|[
{"name":"Michael Scott"}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
it "works on nested embeds" $ do
get "/entities?select=name,child_entities(name,grandchild_entities())&child_entities.grandchild_entities=not.is.null&child_entities=not.is.null" `shouldRespondWith`
[json|[
{"name":"entity 1","child_entities":[{"name":"child entity 1"}, {"name":"child entity 2"}]}]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
it "can do an or across embeds" $
get "/client?select=*,clientinfo(),contact()&clientinfo.other=ilike.*main*&contact.name=ilike.*tabby*&or=(clientinfo.not.is.null,contact.not.is.null)" `shouldRespondWith`
[json|[
{"id":1,"name":"Walmart"},
{"id":2,"name":"Target"}
]|]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}
it "only works with is null or is not null operators" $
get "/projects?select=name,clients(*)&clients=eq.3" `shouldRespondWith`
[json|{
"code":"PGRST120",
"details":"Only is null or not is null filters are allowed on embedded resources",
"hint":null,
"message":"Bad operator on the 'clients' embedded resource"
}|]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}