packages feed

hasql-cursor-query (empty) → 0.4

raw patch · 17 files changed

+475/−0 lines, 17 filesdep +QuickCheckdep +basedep +base-preludesetup-changed

Dependencies added: QuickCheck, base, base-prelude, bytestring, contravariant, foldl, hasql, hasql-cursor-query, hasql-cursor-transaction, hasql-transaction, profunctors, quickcheck-instances, rebase, tasty, tasty-hunit, tasty-quickcheck, tasty-smallcheck

Files

+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2016, Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hasql-cursor-query.cabal view
@@ -0,0 +1,100 @@+name:+  hasql-cursor-query+version:+  0.4+category:+  Hasql, Database, PostgreSQL, Streaming+synopsis:+  A declarative abstraction over PostgreSQL Cursor+homepage:+  https://github.com/nikita-volkov/hasql-cursor-query +bug-reports:+  https://github.com/nikita-volkov/hasql-cursor-query/issues +author:+  Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer:+  Nikita Volkov <nikita.y.volkov@mail.ru>+copyright:+  (c) 2016, Nikita Volkov+license:+  MIT+license-file:+  LICENSE+build-type:+  Simple+cabal-version:+  >=1.10+++source-repository head+  type:+    git+  location:+    git://github.com/nikita-volkov/hasql-cursor-query.git+++library+  hs-source-dirs:+    library+  ghc-options:+  default-extensions:+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language:+    Haskell2010+  other-modules:+    Hasql.CursorQuery.Private.Prelude+    Hasql.CursorQuery.Private.CursorQuery+    Hasql.CursorQuery.Private.Decoders+    Hasql.CursorQuery.Private.Transactions+    Hasql.CursorQuery.Private.CursorTransactions+    Hasql.CursorQuery.Private.Sessions+  exposed-modules:+    Hasql.CursorQuery.Transactions+    Hasql.CursorQuery.CursorTransactions+    Hasql.CursorQuery.Sessions+    Hasql.CursorQuery+  build-depends:+    -- database:+    hasql >= 0.19 && < 0.20,+    hasql-transaction >= 0.4.5.1 && < 0.5,+    hasql-cursor-transaction >= 0.5 && < 0.6,+    -- data:+    bytestring >= 0.10 && < 0.11,+    -- control:+    foldl > 1 && < 2,+    profunctors == 5.*,+    contravariant >= 1.3 && < 2,+    -- general:+    base-prelude >= 0.1.19 && < 2,+    base >= 4.6 && < 5+++test-suite tasty+  type:+    exitcode-stdio-1.0+  hs-source-dirs:+    tasty+  main-is:+    Main.hs+  other-modules:+    Main.CursorQueries+    Main.Queries+    Main.IO+  default-extensions:+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language:+    Haskell2010+  build-depends:+    -- database:+    hasql,+    hasql-cursor-query,+    -- testing:+    tasty == 0.11.*,+    tasty-quickcheck == 0.8.*,+    tasty-smallcheck == 0.8.*,+    tasty-hunit == 0.9.*,+    quickcheck-instances >= 0.3.11 && < 0.4,+    QuickCheck >= 2.8.1 && < 2.9,+    -- +    foldl >= 1.2 && < 2,+    rebase < 2
+ library/Hasql/CursorQuery.hs view
@@ -0,0 +1,19 @@+-- |+-- A DSL for declaring queries.+module Hasql.CursorQuery+(+  A.CursorQuery,+  A.cursorQuery,+  A.ReducingDecoder,+  A.reducingDecoder,+  B.BatchSize,+  B.batchSize_10,+  B.batchSize_100,+  B.batchSize_1000,+  B.batchSize_10000,+)+where++import qualified Hasql.CursorQuery.Private.CursorQuery as A+import qualified Hasql.CursorTransaction as B+
+ library/Hasql/CursorQuery/CursorTransactions.hs view
@@ -0,0 +1,7 @@+module Hasql.CursorQuery.CursorTransactions+(+  cursorQuery,+)+where++import Hasql.CursorQuery.Private.CursorTransactions
+ library/Hasql/CursorQuery/Private/CursorQuery.hs view
@@ -0,0 +1,69 @@+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+
+ library/Hasql/CursorQuery/Private/CursorTransactions.hs view
@@ -0,0 +1,43 @@+module Hasql.CursorQuery.Private.CursorTransactions+where++import Hasql.CursorQuery.Private.Prelude+import qualified Hasql.CursorQuery.Private.CursorQuery as B+import qualified Hasql.CursorQuery.Private.Decoders as I+import qualified Hasql.Decoders as E+import qualified Hasql.Encoders as F+import qualified Hasql.CursorTransaction as G+import qualified Control.Foldl as D+++-- |+-- Fetch and fold the data from cursor until it dries out.+fetchAndFoldCursor :: G.Cursor s -> G.BatchSize -> E.Row row -> D.Fold row result -> G.CursorTransaction s result+fetchAndFoldCursor cursor batchSize rowDecoder (D.Fold progress enter exit) =+  fmap exit $+  fetchAndFoldMore enter+  where+    fetchAndFoldMore batch =+      do+        (null, fetchedBatch) <- fetchBatch+        if null+          then return batch+          else fetchAndFoldMore fetchedBatch+      where+        fetchBatch =+          fetchAndFoldCursorBatch cursor batchSize rowDecoder fold+          where+            fold =+              (,) <$> D.null <*> D.Fold progress batch id++fetchAndFoldCursorBatch :: G.Cursor s -> G.BatchSize -> E.Row row -> D.Fold row result -> G.CursorTransaction s result+fetchAndFoldCursorBatch cursor batchSize rowDecoder rowsFold =+  G.fetchBatch cursor batchSize (I.fold rowsFold rowDecoder)++-- |+-- Executes CursorQuery in CursorTransaction provided the parameters.+cursorQuery :: params -> B.CursorQuery params result -> G.CursorTransaction s result+cursorQuery params (B.CursorQuery template encoder (B.ReducingDecoder rowDecoder rowsFold) batchSize) =+  G.withCursor template (G.encodedParams encoder params) $+  \ cursor ->+    fetchAndFoldCursor cursor batchSize rowDecoder rowsFold
+ library/Hasql/CursorQuery/Private/Decoders.hs view
@@ -0,0 +1,11 @@+module Hasql.CursorQuery.Private.Decoders+where++import Hasql.CursorQuery.Private.Prelude+import qualified Hasql.Decoders as A+import qualified Control.Foldl as B+++fold :: B.Fold a b -> A.Row a -> A.Result b+fold (B.Fold progress enter exit) rowDecoder =+  fmap exit (A.foldlRows progress enter rowDecoder)
+ library/Hasql/CursorQuery/Private/Prelude.hs view
@@ -0,0 +1,23 @@+module Hasql.CursorQuery.Private.Prelude+( +  module Exports,+)+where+++-- base-prelude+-------------------------+import BasePrelude as Exports hiding (assert, left, right, isLeft, isRight, error)++-- profunctors+-------------------------+import Data.Profunctor.Unsafe as Exports++-- contravariant+-------------------------+import Data.Functor.Contravariant as Exports+import Data.Functor.Contravariant.Divisible as Exports++-- bytestring+-------------------------+import Data.ByteString as Exports (ByteString)
+ library/Hasql/CursorQuery/Private/Sessions.hs view
@@ -0,0 +1,17 @@+module Hasql.CursorQuery.Private.Sessions+where++import Hasql.CursorQuery.Private.Prelude+import qualified Hasql.CursorQuery.Private.CursorQuery as B+import qualified Hasql.CursorQuery.Private.CursorTransactions as C+import qualified Hasql.CursorTransaction.Sessions as A+import qualified Hasql.Session as D+++-- |+-- Executes CursorQuery in Session provided the parameters.+-- +-- During the execution it establishes a Read transaction with the ReadCommitted isolation level.+cursorQuery :: params -> B.CursorQuery params result -> D.Session result+cursorQuery params cursorQuery =+  A.cursorTransaction (C.cursorQuery params cursorQuery)
+ library/Hasql/CursorQuery/Private/Transactions.hs view
@@ -0,0 +1,15 @@+module Hasql.CursorQuery.Private.Transactions+where++import Hasql.CursorQuery.Private.Prelude+import qualified Hasql.CursorQuery.Private.CursorQuery as B+import qualified Hasql.CursorQuery.Private.CursorTransactions as C+import qualified Hasql.Transaction as A+import qualified Hasql.CursorTransaction.Transactions as D+++-- |+-- Executes CursorQuery in Transaction provided the parameters.+cursorQuery :: params -> B.CursorQuery params result -> A.Transaction result+cursorQuery params cursorQuery =+  D.cursorTransaction (C.cursorQuery params cursorQuery)
+ library/Hasql/CursorQuery/Sessions.hs view
@@ -0,0 +1,7 @@+module Hasql.CursorQuery.Sessions+(+  cursorQuery,+)+where++import Hasql.CursorQuery.Private.Sessions
+ library/Hasql/CursorQuery/Transactions.hs view
@@ -0,0 +1,7 @@+module Hasql.CursorQuery.Transactions+(+  cursorQuery,+)+where++import Hasql.CursorQuery.Private.Transactions
+ tasty/Main.hs view
@@ -0,0 +1,29 @@+module Main where++import Rebase.Prelude+import Test.Tasty+import Test.Tasty.Runners+import Test.Tasty.HUnit+import qualified Hasql.Session as A+import qualified Hasql.CursorQuery.Sessions as C+import qualified Main.CursorQueries as D+import qualified Main.Queries as E+import qualified Main.IO as F+++main :: IO ()+main =+  defaultMain $+  localOption (NumThreads 1) $+  testGroup "All tests"+  [+    testCase "Amount" $+    do+      (count1, count2) <- F.session ((,) <$> A.query () E.countPGType <*> C.cursorQuery () D.countPGType)+      assertEqual (show (count1, count2)) count1 count2+    ,+    testCase "Equality" $+    do+      (result1, result2) <- F.session ((,) <$> A.query () E.slectOIDAndTypeName <*> C.cursorQuery () D.slectOIDAndTypeName)+      assertEqual (show (result1, result2)) result1 result2+  ]
+ tasty/Main/CursorQueries.hs view
@@ -0,0 +1,41 @@+module Main.CursorQueries where++import Rebase.Prelude+import Hasql.CursorQuery+import qualified Hasql.Encoders as A+import qualified Hasql.Decoders as B+import qualified Control.Foldl as C+++countPGType :: CursorQuery () Int+countPGType =+  cursorQuery sql encoder decoder batchSize_10+  where+    sql =+      "select oid, typname from pg_type"+    encoder =+      A.unit+    decoder =+      reducingDecoder rowDecoder fold+      where+        rowDecoder =+          (,) <$> B.value B.int8 <*> B.value B.text+        fold =+          C.length++slectOIDAndTypeName :: CursorQuery () [(Int64, Text)]+slectOIDAndTypeName =+  cursorQuery sql encoder decoder batchSize_10+  where+    sql =+      "select oid, typname from pg_type"+    encoder =+      A.unit+    decoder =+      reducingDecoder rowDecoder fold+      where+        rowDecoder =+          (,) <$> B.value B.int8 <*> B.value B.text+        fold =+          C.list+
+ tasty/Main/IO.hs view
@@ -0,0 +1,31 @@+module Main.IO where++import Rebase.Prelude+import qualified Hasql.Session as A+import qualified Hasql.Connection as B+++session :: A.Session a -> IO a+session session =+  withConnection (A.run session) >>=+  either (fail . show) (either (fail . show) return)+  where+    withConnection :: (B.Connection -> IO a) -> IO (Either B.ConnectionError a)+    withConnection handler =+      runExceptT $ acquire >>= \connection -> use connection <* release connection+      where+        acquire =+          ExceptT $ B.acquire settings+          where+            settings =+              B.settings host port user password database+              where+                host = "localhost"+                port = 5432+                user = "postgres"+                password = ""+                database = "postgres"+        use connection =+          lift $ handler connection+        release connection =+          lift $ B.release connection
+ tasty/Main/Queries.hs view
@@ -0,0 +1,32 @@+module Main.Queries where++import Rebase.Prelude+import Hasql.Query+import qualified Hasql.Encoders as A+import qualified Hasql.Decoders as B+++countPGType :: Query () Int+countPGType =+  statement sql encoder decoder True+  where+    sql =+      "select count(*) from pg_type"+    encoder =+      A.unit+    decoder =+      B.singleRow (B.value (fmap fromIntegral B.int8))+      +slectOIDAndTypeName :: Query () [(Int64, Text)]+slectOIDAndTypeName =+  statement sql encoder decoder True+  where+    sql =+      "select oid, typname from pg_type"+    encoder =+      A.unit+    decoder =+      B.rowsList rowDecoder+      where+        rowDecoder =+          (,) <$> B.value B.int8 <*> B.value B.text