module Hasql.CursorQuery.Private.CursorQuery where import Hasql.CursorQuery.Private.Prelude import qualified Hasql.Encoders as A import qualified Hasql.Decoders as B import qualified Control.Foldl as D import qualified Hasql.CursorTransaction as H -- | -- A specification of a streaming query. -- -- Provides an abstraction over Postgres Cursor, -- which allows to process result sets of any size in constant memory. -- -- Essentially it is a parametric query specification extended with a reduction strategy and a batch size, -- where reduction strategy determines how to fold the rows into the final result, -- and batch size determines how many rows to fetch during each roundtrip to the database. data CursorQuery params result = CursorQuery !ByteString !(A.Params params) !(ReducingDecoder result) !H.BatchSize instance Profunctor CursorQuery where dimap fn1 fn2 (CursorQuery template encoder decoder batchSize) = CursorQuery template (contramap fn1 encoder) (fmap fn2 decoder) batchSize instance Functor (CursorQuery params) where fmap = rmap -- | -- Given an SQL template, a params encoder, a reducing result decoder and a batch-size, -- constructs CursorQuery. cursorQuery :: ByteString -> A.Params params -> ReducingDecoder result -> H.BatchSize -> CursorQuery params result cursorQuery = CursorQuery -- | -- A specification of how to decode and reduce multiple rows. -- -- Composable with the Applicative interface. data ReducingDecoder reduction = forall row. ReducingDecoder !(B.Row row) !(D.Fold row reduction) instance Functor ReducingDecoder where fmap fn (ReducingDecoder rowDecoder rowsFold) = ReducingDecoder rowDecoder (fmap fn rowsFold) instance Applicative ReducingDecoder where pure reduction = ReducingDecoder (pure ()) (pure reduction) (<*>) (ReducingDecoder rowDecoder1 rowsFold1) (ReducingDecoder rowDecoder2 rowsFold2) = ReducingDecoder rowDecoder3 rowsFold3 where rowDecoder3 = strictPair <$> rowDecoder1 <*> rowDecoder2 where strictPair !a !b = (a, b) rowsFold3 = lmap fst rowsFold1 <*> lmap snd rowsFold2 -- | -- Packs a row decoder and a fold over rows into ReducingDecoder. reducingDecoder :: B.Row row -> D.Fold row reduction -> ReducingDecoder reduction reducingDecoder = ReducingDecoder