module Database.Bolty.ResultSet
( ResultSet(..)
, decodeResultSet
, decodeHead
, groupByField
) where
import Data.Kind (Type)
import qualified Data.Text as T
import qualified Data.Vector as V
import Database.Bolty.Decode (DecodeError(..), RowDecoder, decodeRow, decodeRows)
import Database.Bolty.Record (Record)
type ResultSet :: Type
data ResultSet = ResultSet
{ ResultSet -> Vector Text
fields :: !(V.Vector T.Text)
, ResultSet -> Vector Record
records :: !(V.Vector Record)
} deriving stock (Int -> ResultSet -> ShowS
[ResultSet] -> ShowS
ResultSet -> String
(Int -> ResultSet -> ShowS)
-> (ResultSet -> String)
-> ([ResultSet] -> ShowS)
-> Show ResultSet
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ResultSet -> ShowS
showsPrec :: Int -> ResultSet -> ShowS
$cshow :: ResultSet -> String
show :: ResultSet -> String
$cshowList :: [ResultSet] -> ShowS
showList :: [ResultSet] -> ShowS
Show, ResultSet -> ResultSet -> Bool
(ResultSet -> ResultSet -> Bool)
-> (ResultSet -> ResultSet -> Bool) -> Eq ResultSet
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ResultSet -> ResultSet -> Bool
== :: ResultSet -> ResultSet -> Bool
$c/= :: ResultSet -> ResultSet -> Bool
/= :: ResultSet -> ResultSet -> Bool
Eq)
decodeResultSet :: RowDecoder a -> ResultSet -> Either DecodeError (V.Vector a)
decodeResultSet :: forall a.
RowDecoder a -> ResultSet -> Either DecodeError (Vector a)
decodeResultSet RowDecoder a
decoder (ResultSet Vector Text
fs Vector Record
rs) = RowDecoder a
-> Vector Text -> Vector Record -> Either DecodeError (Vector a)
forall a.
RowDecoder a
-> Vector Text -> Vector Record -> Either DecodeError (Vector a)
decodeRows RowDecoder a
decoder Vector Text
fs Vector Record
rs
decodeHead :: RowDecoder a -> ResultSet -> Either DecodeError a
decodeHead :: forall a. RowDecoder a -> ResultSet -> Either DecodeError a
decodeHead RowDecoder a
decoder (ResultSet Vector Text
fs Vector Record
rs) = case Vector Record -> Maybe (Record, Vector Record)
forall a. Vector a -> Maybe (a, Vector a)
V.uncons Vector Record
rs of
Maybe (Record, Vector Record)
Nothing -> DecodeError -> Either DecodeError a
forall a b. a -> Either a b
Left DecodeError
EmptyResultSet
Just (Record
rec, Vector Record
_) -> RowDecoder a -> Vector Text -> Record -> Either DecodeError a
forall a.
RowDecoder a -> Vector Text -> Record -> Either DecodeError a
decodeRow RowDecoder a
decoder Vector Text
fs Record
rec
groupByField
:: Eq k
=> RowDecoder (Maybe k)
-> ResultSet
-> Either DecodeError (V.Vector (k, ResultSet))
groupByField :: forall k.
Eq k =>
RowDecoder (Maybe k)
-> ResultSet -> Either DecodeError (Vector (k, ResultSet))
groupByField RowDecoder (Maybe k)
keyDecoder (ResultSet Vector Text
fs Vector Record
rs) =
[(k, [Record])] -> Either DecodeError (Vector (k, ResultSet))
buildGroups ([(k, [Record])] -> Either DecodeError (Vector (k, ResultSet)))
-> Either DecodeError [(k, [Record])]
-> Either DecodeError (Vector (k, ResultSet))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ([(k, [Record])] -> Record -> Either DecodeError [(k, [Record])])
-> [(k, [Record])]
-> Vector Record
-> Either DecodeError [(k, [Record])]
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> m a) -> a -> Vector b -> m a
V.foldM' [(k, [Record])] -> Record -> Either DecodeError [(k, [Record])]
accumulate [] Vector Record
rs
where
accumulate :: [(k, [Record])] -> Record -> Either DecodeError [(k, [Record])]
accumulate [(k, [Record])]
acc Record
rec = do
mk <- RowDecoder (Maybe k)
-> Vector Text -> Record -> Either DecodeError (Maybe k)
forall a.
RowDecoder a -> Vector Text -> Record -> Either DecodeError a
decodeRow RowDecoder (Maybe k)
keyDecoder Vector Text
fs Record
rec
pure $ case mk of
Maybe k
Nothing -> [(k, [Record])]
acc
Just k
k -> case [(k, [Record])]
acc of
(k
curK, [Record]
curRecs) : [(k, [Record])]
rest
| k
curK k -> k -> Bool
forall a. Eq a => a -> a -> Bool
== k
k -> (k
curK, Record
rec Record -> [Record] -> [Record]
forall a. a -> [a] -> [a]
: [Record]
curRecs) (k, [Record]) -> [(k, [Record])] -> [(k, [Record])]
forall a. a -> [a] -> [a]
: [(k, [Record])]
rest
[(k, [Record])]
_ -> (k
k, [Record
rec]) (k, [Record]) -> [(k, [Record])] -> [(k, [Record])]
forall a. a -> [a] -> [a]
: [(k, [Record])]
acc
buildGroups :: [(k, [Record])] -> Either DecodeError (Vector (k, ResultSet))
buildGroups [(k, [Record])]
groups =
Vector (k, ResultSet) -> Either DecodeError (Vector (k, ResultSet))
forall a b. b -> Either a b
Right (Vector (k, ResultSet)
-> Either DecodeError (Vector (k, ResultSet)))
-> Vector (k, ResultSet)
-> Either DecodeError (Vector (k, ResultSet))
forall a b. (a -> b) -> a -> b
$ [(k, ResultSet)] -> Vector (k, ResultSet)
forall a. [a] -> Vector a
V.fromList
[ (k
k, Vector Text -> Vector Record -> ResultSet
ResultSet Vector Text
fs ([Record] -> Vector Record
forall a. [a] -> Vector a
V.fromList ([Record] -> [Record]
forall a. [a] -> [a]
reverse [Record]
recs)))
| (k
k, [Record]
recs) <- [(k, [Record])] -> [(k, [Record])]
forall a. [a] -> [a]
reverse [(k, [Record])]
groups
]