diff --git a/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs b/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs index 1efc7454e47..b057e0e77c1 100644 --- a/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs +++ b/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs @@ -1,6 +1,7 @@ module Test.QuerySpec.OrderBySpec (spec) where -import Control.Lens (ix, (&), (.~), (?~), (^.), (^?), _1, _2, _3, _Just) +import Control.Arrow ((>>>)) +import Control.Lens (ix, (%~), (&), (.~), (?~), (^.), (^?), _1, _2, _3, _Just) import Control.Monad (when) import Data.Aeson (Value (..)) import Data.HashMap.Strict (HashMap) @@ -8,7 +9,7 @@ import Data.HashMap.Strict qualified as HashMap import Data.List (sortOn) import Data.List.NonEmpty (NonEmpty (..)) import Data.List.NonEmpty qualified as NonEmpty -import Data.Maybe (isJust) +import Data.Maybe (fromMaybe, isJust) import Data.Ord (Down (..)) import Hasura.Backends.DataConnector.API import Servant.API (NamedRoutes) @@ -154,6 +155,63 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By Data.responseRows receivedTracks `rowsShouldBe` expectedTracks _qrAggregates receivedTracks `jsonShouldBe` Nothing + it "can order results separately within each array relationship" $ do + let tracksOrdering = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| [] + let tracksField = + RelField . RelationshipField _tdTracksRelationshipName $ + tracksQuery + & qOrderBy ?~ tracksOrdering + & qLimit ?~ 5 + let albumsOrdering = OrderBy mempty $ _tdOrderByColumn [] "Title" Descending :| [] + let albumsField = + RelField . RelationshipField _tdAlbumsRelationshipName $ + albumsQuery + & qFields . _Just %~ Data.insertField "Tracks" tracksField + & qOrderBy ?~ albumsOrdering + & qLimit ?~ 3 + let artistsOrdering = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| [] + let query = + artistsQueryRequest + & qrQuery . qFields . _Just %~ Data.insertField "Albums" albumsField + & qrQuery . qOrderBy ?~ artistsOrdering + & qrQuery . qOffset ?~ 75 + & qrQuery . qLimit ?~ 5 + & qrTableRelationships + .~ [ Data.onlyKeepRelationships [_tdTracksRelationshipName] _tdAlbumsTableRelationships, + Data.onlyKeepRelationships [_tdAlbumsRelationshipName] _tdArtistsTableRelationships + ] + receivedArtists <- guardedQuery api sourceName config query + + let joinInTracks (album :: HashMap FieldName FieldValue) = fromMaybe album $ do + albumId <- album ^? Data.field "AlbumId" . Data._ColumnFieldNumber + let albums = + _tdTracksRows + & filter ((^? Data.field "AlbumId" . Data._ColumnFieldNumber) >>> (== Just albumId)) + & sortOn ((^? Data.field "Name") >>> Down) + & take 5 + & Data.filterColumns ["TrackId", "Name"] + pure $ Data.insertField "Tracks" (mkSubqueryResponse (Just albums) Nothing) album + + let joinInAlbums (artist :: HashMap FieldName FieldValue) = fromMaybe artist $ do + artistId <- artist ^? Data.field "ArtistId" . Data._ColumnFieldNumber + let albums = + _tdAlbumsRows + & filter ((^? Data.field "ArtistId" . Data._ColumnFieldNumber) >>> (== Just artistId)) + & sortOn ((^? Data.field "Title") >>> Down) + & take 3 + & fmap joinInTracks + pure $ Data.insertField "Albums" (mkSubqueryResponse (Just albums) Nothing) artist + + let expectedArtists = + _tdArtistsRows + & sortOn ((^? Data.field "Name") >>> Down) + & drop 75 + & take 5 + & fmap joinInAlbums + + Data.responseRows receivedArtists `rowsShouldBe` expectedArtists + _qrAggregates receivedArtists `jsonShouldBe` Nothing + it "can order results by an aggregate of a related table" $ do let orderByRelations = HashMap.fromList [(_tdAlbumsRelationshipName, OrderByRelation Nothing mempty)] let orderBy = @@ -256,11 +314,14 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By Data.responseRows receivedAlbums `rowsShouldBe` expectedArtists _qrAggregates receivedAlbums `jsonShouldBe` Nothing where + albumsQuery :: Query + albumsQuery = + let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] + in Data.emptyQuery & qFields ?~ fields + albumsQueryRequest :: QueryRequest albumsQueryRequest = - let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] - query = Data.emptyQuery & qFields ?~ fields - in QueryRequest _tdAlbumsTableName [] query + QueryRequest _tdAlbumsTableName [] albumsQuery artistsQueryRequest :: QueryRequest artistsQueryRequest = @@ -268,11 +329,14 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By query = Data.emptyQuery & qFields ?~ fields in QueryRequest _tdArtistsTableName [] query + tracksQuery :: Query + tracksQuery = + let fields = Data.mkFieldsMap [("TrackId", _tdColumnField "TrackId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] + in Data.emptyQuery & qFields ?~ fields + tracksQueryRequest :: QueryRequest tracksQueryRequest = - let fields = Data.mkFieldsMap [("TrackId", _tdColumnField "TrackId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] - query = Data.emptyQuery & qFields ?~ fields - in QueryRequest _tdTracksTableName [] query + QueryRequest _tdTracksTableName [] tracksQuery data NullableOrdered a = NullFirst @@ -282,3 +346,7 @@ data NullableOrdered a toNullsLastOrdering :: Maybe a -> NullableOrdered a toNullsLastOrdering = maybe NullLast Some + +mkSubqueryResponse :: Maybe [HashMap FieldName FieldValue] -> Maybe (HashMap FieldName Value) -> FieldValue +mkSubqueryResponse rows aggregates = + mkRelationshipFieldValue $ QueryResponse rows aggregates