git.iko.soy/typeable/postgresql-simple
on master help sign in
Merge pull request #1 from phadej/prepare-0.6

Prepare for 0.6

commitf9315c47e282eeb7bf939640ed4ab3d2f3d02e32 authorOleg Grenrus <oleg.grenrus@iki.fi> dateTue 16 Oct 2018, 15:46 (8 years ago) parent14d00c2577e20b
9 files changed+399−97
.gitignore+2−1 .travis.yml+103−53 CHANGES.md+59−3 bench/Select.hs+32 postgresql-simple.cabal+73−34 src/Database/PostgreSQL/Simple.hs+1 src/Database/PostgreSQL/Simple/Internal/PQResultUtils.hs+40−6 src/Database/PostgreSQL/Simple/Vector.hs+45 src/Database/PostgreSQL/Simple/Vector/Unboxed.hs+44
.gitignore+2−1
@@ -11,4 +11,5 @@ dist/
1111.cabal-sandbox/
1212.stack-work/
1313cabal.sandbox.config
14−/dist-newstyle
14+/dist-newstyle
15+.ghc.environment.*
.travis.yml+103−53
@@ -1,73 +1,123 @@
1−# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
1+# This Travis job script has been generated by a script via
2+#
3+# runghc make_travis_yml_2.hs '--output' '.travis.yml' 'postgresql-simple.cabal'
4+#
5+# For more information, see https://github.com/haskell-CI/haskell-ci
6+#
27language: c
38sudo: false
49
10+services:
11+ - postgresql
12+
13+git:
14+ submodules: false # whether to recursively clone submodules
15+
516cache:
617 directories:
7− - $HOME/.cabsnap
818 - $HOME/.cabal/packages
19+ - $HOME/.cabal/store
920
1021before_cache:
1122 - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
12− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
23+ # remove files that are regenerated by 'cabal update'
24+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
25+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
26+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
27+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
28+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
29+
30+ - rm -rfv $HOME/.cabal/packages/head.hackage
1331
1432matrix:
1533 include:
16− - env: CABALVER=1.18 GHCVER=7.8.4
17− compiler: ": #GHC 7.8.4"
18− addons: { apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}, postgresql: "9.3"}
19− - env: CABALVER=1.22 GHCVER=7.10.2
20− compiler: ": #GHC 7.10.2"
21− addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}, postgresql: "9.3"}
22− - env: CABALVER=1.24 GHCVER=8.0.1
23− compiler: ": #GHC 8.0.1"
24− addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}, postgresql: "9.3"}
34+ - compiler: "ghc-8.6.1"
35+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
36+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}
37+ - compiler: "ghc-8.4.4"
38+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
39+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}
40+ - compiler: "ghc-8.2.2"
41+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
42+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}
43+ - compiler: "ghc-8.0.2"
44+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
45+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}
46+ - compiler: "ghc-7.10.3"
47+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
48+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}
49+ - compiler: "ghc-7.8.4"
50+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
51+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}
52+ - compiler: "ghc-7.6.3"
53+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
54+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.6.3], sources: [hvr-ghc]}}
2555
2656before_install:
27− - unset CC
28− - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
29− - createdb `whoami` || true
57+ - HC=${CC}
58+ - HCPKG=${HC/ghc/ghc-pkg}
59+ - unset CC
60+ - ROOTDIR=$(pwd)
61+ - mkdir -p $HOME/.local/bin
62+ - "PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$HOME/local/bin:$PATH"
63+ - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))
64+ - echo $HCNUMVER
3065
3166install:
32− - cabal --version
33− - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
34− - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
35− then
36− zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
37− $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
38− fi
39− - travis_retry cabal update -v
40− - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
41− - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
42− - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
43−
44−# check whether current requested install-plan matches cached package-db snapshot
45− - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
46− then
47− echo "cabal build-cache HIT";
48− rm -rfv .ghc;
49− cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
50− cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
51− else
52− echo "cabal build-cache MISS";
53− rm -rf $HOME/.cabsnap;
54− mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
55− cabal install --only-dependencies --enable-tests --enable-benchmarks;
56− fi
57−
58−# snapshot package-db on cache miss
59− - if [ ! -d $HOME/.cabsnap ];
60− then
61− echo "snapshotting package-db to build-cache";
62− mkdir $HOME/.cabsnap;
63− cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
64− cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
65− fi
67+ - cabal --version
68+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
69+ - BENCH=${BENCH---enable-benchmarks}
70+ - TEST=${TEST---enable-tests}
71+ - HADDOCK=${HADDOCK-true}
72+ - UNCONSTRAINED=${UNCONSTRAINED-true}
73+ - NOINSTALLEDCONSTRAINTS=${NOINSTALLEDCONSTRAINTS-false}
74+ - GHCHEAD=${GHCHEAD-false}
75+ - travis_retry cabal update -v
76+ - "sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"
77+ - rm -fv cabal.project cabal.project.local
78+ - grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
79+ - "printf 'packages: \".\"\\n' > cabal.project"
80+ - touch cabal.project.local
81+ - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | grep -vw -- postgresql-simple | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
82+ - cat cabal.project || true
83+ - cat cabal.project.local || true
84+ - if [ -f "./configure.ac" ]; then
85+ (cd "." && autoreconf -i);
86+ fi
87+ - rm -f cabal.project.freeze
88+ - cabal new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dep -j2 all
89+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project" --dep -j2 all
90+ - rm -rf .ghc.environment.* "."/dist
91+ - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
6692
6793# Here starts the actual work to be performed for the package under test;
6894# any command which exits with a non-zero exit code causes the build to fail.
6995script:
70− - if [ -f configure.ac ]; then autoreconf -i; fi
71− - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
72− - cabal build # this builds all libraries and executables (including tests/benchmarks)
73− - cabal test
96+ # test that source-distributions can be generated
97+ - cabal new-sdist all
98+ - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
99+ - cd ${DISTDIR} || false
100+ - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;
101+ - "printf 'packages: postgresql-simple-*/*.cabal\\n' > cabal.project"
102+ - touch cabal.project.local
103+ - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | grep -vw -- postgresql-simple | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
104+ - cat cabal.project || true
105+ - cat cabal.project.local || true
106+ # this builds all libraries and executables (without tests/benchmarks)
107+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
108+
109+ # build & run tests, build benchmarks
110+ - cabal new-build -w ${HC} ${TEST} ${BENCH} all
111+ - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} ${BENCH} all; fi
112+
113+ # cabal check
114+ - (cd postgresql-simple-* && cabal check)
115+
116+ # haddock
117+ - if $HADDOCK; then cabal new-haddock -w ${HC} ${TEST} ${BENCH} all; else echo "Skipping haddock generation";fi
118+
119+ # Build without installed constraints for packages in global-db
120+ - if $UNCONSTRAINED; then rm -f cabal.project.local; echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks all; else echo "Not building without installed constraints"; fi
121+
122+# REGENDATA ["--output",".travis.yml","postgresql-simple.cabal"]
123+# EOF
CHANGES.md+59−3
@@ -1,7 +1,63 @@
1−### Unreleased
2−
3− * Added `ToField` instances for case-insensitive strict and lazy text.
1+### Version 0.6 (2018-09-25)
2+
3+ * *Breaking change*: Use `Only` package's `Only for a common 1-tuple.
4+
5+ Consider a downstream library depending already both on
6+ `Only` and `postgresql-simple` package. This library my define
7+ a `MyClass` with instances for `Only.Only` and `PostgreSQL.Only`.
8+ As now these types are the same, a library would break.
9+ Therefore I consider "merging" types a breaking change.
10+
11+ There are two ways for adopting this change in that scenario:
12+
13+ - Either CPP-guard `PostgreSQL.Only` instance with
14+
15+ ```haskell
16+ #if !MIN_VERSION_postgresql_simple(0,6,0)
17+ instance MyClass (PostgreSQL.Only a) where ...
18+ #endif
19+ ```
20+
21+ - or simply remove it and add `postgresql-simple >=0.6` lower bound,
22+ making sure that there's only single `Only`.
23+
24+ * Add `ToField` instances for case-insensitive strict and lazy text.
425 Thanks to Max Tagher for the implementation.
26+ https://github.com/lpsmith/postgresql-simple/pull/232
27+
28+ * Add support to CockroachDB.
29+ Thanks to Georte Steel.
30+ https://github.com/lpsmith/postgresql-simple/pull/245
31+
32+ * Add Generic ConnectInfo instance
33+ Thanks to Dmitry Dzhus.
34+ https://github.com/lpsmith/postgresql-simple/pull/235
35+
36+ * Add `fromFieldRange :: Typeable a => FieldParser a -> FieldParser (PGRange a)`
37+ https://github.com/lpsmith/postgresql-simple/pull/221
38+
39+ * Add `fromFieldJSONByteString :: FieldParser ByteString`
40+ https://github.com/lpsmith/postgresql-simple/pull/222/files
41+
42+ * Fix off-by-one error in year builder.
43+ Thanks to Nathan Ferris Hunter.
44+ https://github.com/lpsmith/postgresql-simple/pull/230
45+
46+ * Extend ToRow and FromRow to tuples of size 18
47+ Thanks to Bardur Arantsson.
48+ https://github.com/lpsmith/postgresql-simple/pull/229
49+
50+ * Add `Vector` and `Vector.Unboxed` `query` variants.
51+ These are more memory efficient
52+ (especially, if you anyway will convert to some vector)
53+ https://github.com/phadej/1
54+
55+ * Documentation improvements
56+ https://github.com/lpsmith/postgresql-simple/pull/227
57+ https://github.com/lpsmith/postgresql-simple/pull/236
58+
59+### Version 0.5.4.0 (2018-05-23)
60+ * Support GHC-8.4 (Semigroup/Monoid)
561
662### Version 0.5.3.0 (2017-05-15)
763 * Refactored some rudimentary cursor handling code out of the
bench/Select.hsnew file+32
@@ -0,0 +1,32 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Main where
3+
4+import Database.PostgreSQL.Simple
5+import qualified Database.PostgreSQL.Simple.Vector as V
6+import qualified Database.PostgreSQL.Simple.Vector.Unboxed as VU
7+
8+import System.Environment (getArgs)
9+import Data.Foldable (Foldable, foldl')
10+import qualified Data.Vector.Unboxed as VU
11+
12+main :: IO ()
13+main = do
14+ args <- getArgs
15+ conn <- connectPostgreSQL ""
16+ case args of
17+ ("vector":_) -> do
18+ result <- V.query_ conn "SELECT * FROM generate_series(1, 10000000);"
19+ print (process result)
20+ ("unboxed":_) -> do
21+ -- dummy column
22+ result <- VU.query_ conn "SELECT (NULL :: VOID), * FROM generate_series(1, 10000000);"
23+ print (process' result)
24+ _ -> do
25+ result <- query_ conn "SELECT * FROM generate_series(1, 10000000);"
26+ print (process result)
27+
28+process :: Foldable f => f (Only Int) -> Int
29+process = foldl' (\x (Only y) -> max x y) 0
30+
31+process' :: VU.Vector ((), Int) -> Int
32+process' = VU.foldl' (\x (_, y) -> max x y) 0
postgresql-simple.cabal+73−34
@@ -1,5 +1,7 @@
1+Cabal-version: 1.12
12Name: postgresql-simple
2−Version: 0.5.3.0
3+Version: 0.6
4+
35Synopsis: Mid-Level PostgreSQL client library
46Description:
57 Mid-Level PostgreSQL client library, forked from mysql-simple.
@@ -12,13 +14,23 @@ Copyright: (c) 2011 MailRank, Inc.
1214Category: Database
1315Build-type: Simple
1416
15−Cabal-version: >= 1.9.2
16−
1717extra-source-files:
18− CONTRIBUTORS
19− CHANGELOG.md
18+ CONTRIBUTORS
19+ CHANGES.md
20+ test/results/malformed-input.expected
21+ test/results/unique-constraint-violation.expected
22+
23+tested-with:
24+ GHC == 7.6.3
25+ || == 7.8.4
26+ || == 7.10.3
27+ || == 8.0.2
28+ || == 8.2.2
29+ || == 8.4.4
30+ || == 8.6.1
2031
2132Library
33+ default-language: Haskell2010
2234 hs-source-dirs: src
2335 Exposed-modules:
2436 Database.PostgreSQL.Simple
@@ -44,6 +56,9 @@ Library
4456 Database.PostgreSQL.Simple.TypeInfo.Static
4557 Database.PostgreSQL.Simple.Types
4658 Database.PostgreSQL.Simple.Errors
59+ Database.PostgreSQL.Simple.Vector
60+ Database.PostgreSQL.Simple.Vector.Unboxed
61+
4762-- Other-modules:
4863 Database.PostgreSQL.Simple.Internal
4964
@@ -56,45 +71,57 @@ Library
5671 Database.PostgreSQL.Simple.Time.Internal.Printer
5772 Database.PostgreSQL.Simple.TypeInfo.Types
5873
74+ -- GHC bundled libs
5975 Build-depends:
60− aeson >= 0.6,
61− attoparsec >= 0.10.3,
62− base >= 4.6 && < 5,
63− bytestring >= 0.9,
64− bytestring-builder,
65− case-insensitive,
66− containers,
67− hashable,
68− Only,
69− postgresql-libpq >= 0.9 && < 0.10,
70− template-haskell,
71− text >= 0.11.1,
72− time,
73− transformers,
74− uuid-types >= 1.0.0,
75− scientific,
76− semigroups,
77− vector
76+ base >=4.6.0.0 && <4.13
77+ , bytestring >=0.10.0.0 && <0.11
78+ , containers >=0.5.0.0 && <0.7
79+ , time >=1.4.0.1 && <1.9
80+ , transformers >=0.3.0.0 && <0.6
81+ , template-haskell >=2.8.0.0 && <2.15
82+ , text >=1.2.3.0 && <1.3
83+
84+ -- Other dependencies
85+ Build-depends:
86+ aeson >=1.4.1.0 && <1.5
87+ , attoparsec >=0.13.2.2 && <0.14
88+ , bytestring-builder >=0.10.8.1.0 && <0.11
89+ , case-insensitive >=1.2.0.11 && <1.3
90+ , hashable >=1.2.7.0 && <1.3
91+ , Only >=0.1 && <0.1.1
92+ , postgresql-libpq >=0.9.4.2 && < 0.10
93+ , uuid-types >=1.0.3 && <1.1
94+ , scientific >=0.3.6.2 && <0.4
95+ , vector >=0.12.0.1 && <0.13
96+
97+ if !impl(ghc >= 8.0)
98+ Build-depends:
99+ semigroups >=0.18.5 && <0.19
78100
79101 if !impl(ghc >= 7.6)
80102 Build-depends:
81103 ghc-prim
82104
83− extensions: DoAndIfThenElse, OverloadedStrings, BangPatterns, ViewPatterns
84− TypeOperators
105+ default-extensions:
106+ DoAndIfThenElse
107+ OverloadedStrings
108+ BangPatterns
109+ ViewPatterns
110+ TypeOperators
85111
86112 ghc-options: -Wall -fno-warn-name-shadowing
87113
88114source-repository head
89115 type: git
90− location: http://github.com/lpsmith/postgresql-simple
116+ location: http://github.com/phadej/postgresql-simple
91117
92118source-repository this
93119 type: git
94− location: http://github.com/lpsmith/postgresql-simple
95− tag: v0.5.3.0
120+ location: http://github.com/phadej/postgresql-simple
121+ tag: v0.6
96122
97123test-suite test
124+ default-language: Haskell2010
98125 type: exitcode-stdio-1.0
99126
100127 hs-source-dirs: test
@@ -107,12 +134,13 @@ test-suite test
107134
108135 ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
109136
110− extensions: NamedFieldPuns
111− , OverloadedStrings
112− , Rank2Types
113− , RecordWildCards
114− , PatternGuards
115− , ScopedTypeVariables
137+ default-extensions:
138+ NamedFieldPuns
139+ OverloadedStrings
140+ Rank2Types
141+ RecordWildCards
142+ PatternGuards
143+ ScopedTypeVariables
116144
117145 build-depends: base
118146 , aeson
@@ -134,3 +162,14 @@ test-suite test
134162 if !impl(ghc >= 7.6)
135163 build-depends:
136164 ghc-prim
165+
166+benchmark select
167+ default-language: Haskell2010
168+ type: exitcode-stdio-1.0
169+
170+ hs-source-dirs: bench
171+ main-is: Select.hs
172+
173+ build-depends: base
174+ , postgresql-simple
175+ , vector
src/Database/PostgreSQL/Simple.hs+1
@@ -355,6 +355,7 @@ executeMany conn q qs = do
355355returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO [r]
356356returning = returningWith fromRow
357357
358+-- | A version of 'returning' taking parser as argument
358359returningWith :: (ToRow q) => RowParser r -> Connection -> Query -> [q] -> IO [r]
359360returningWith _ _ _ [] = return []
360361returningWith parser conn q qs = do
src/Database/PostgreSQL/Simple/Internal/PQResultUtils.hs+40−6
@@ -14,11 +14,14 @@
1414
1515module Database.PostgreSQL.Simple.Internal.PQResultUtils
1616 ( finishQueryWith
17+ , finishQueryWithV
18+ , finishQueryWithVU
1719 , getRowWith
1820 ) where
1921
2022import Control.Exception as E
2123import Data.ByteString (ByteString)
24+import Data.Foldable (for_)
2225import Database.PostgreSQL.Simple.FromField (ResultError(..))
2326import Database.PostgreSQL.Simple.Ok
2427import Database.PostgreSQL.Simple.Types (Query(..))
@@ -26,18 +29,49 @@ import Database.PostgreSQL.Simple.Internal as Base
2629import Database.PostgreSQL.Simple.TypeInfo
2730import qualified Database.PostgreSQL.LibPQ as PQ
2831import qualified Data.ByteString.Char8 as B
32+import qualified Data.Vector as V
33+import qualified Data.Vector.Mutable as MV
34+import qualified Data.Vector.Unboxed as VU
35+import qualified Data.Vector.Unboxed.Mutable as MVU
2936import Control.Monad.Trans.Reader
3037import Control.Monad.Trans.State.Strict
3138
3239finishQueryWith :: RowParser r -> Connection -> Query -> PQ.Result -> IO [r]
33−finishQueryWith parser conn q result = do
40+finishQueryWith parser conn q result = finishQueryWith' q result $ do
41+ nrows <- PQ.ntuples result
42+ ncols <- PQ.nfields result
43+ forM' 0 (nrows-1) $ \row ->
44+ getRowWith parser row ncols conn result
45+
46+finishQueryWithV :: RowParser r -> Connection -> Query -> PQ.Result -> IO (V.Vector r)
47+finishQueryWithV parser conn q result = finishQueryWith' q result $ do
48+ nrows <- PQ.ntuples result
49+ let PQ.Row nrows' = nrows
50+ ncols <- PQ.nfields result
51+ mv <- MV.unsafeNew (fromIntegral nrows')
52+ for_ [ 0 .. nrows-1 ] $ \row -> do
53+ let PQ.Row row' = row
54+ value <- getRowWith parser row ncols conn result
55+ MV.unsafeWrite mv (fromIntegral row') value
56+ V.unsafeFreeze mv
57+
58+finishQueryWithVU :: VU.Unbox r => RowParser r -> Connection -> Query -> PQ.Result -> IO (VU.Vector r)
59+finishQueryWithVU parser conn q result = finishQueryWith' q result $ do
60+ nrows <- PQ.ntuples result
61+ let PQ.Row nrows' = nrows
62+ ncols <- PQ.nfields result
63+ mv <- MVU.unsafeNew (fromIntegral nrows')
64+ for_ [ 0 .. nrows-1 ] $ \row -> do
65+ let PQ.Row row' = row
66+ value <- getRowWith parser row ncols conn result
67+ MVU.unsafeWrite mv (fromIntegral row') value
68+ VU.unsafeFreeze mv
69+
70+finishQueryWith' :: Query -> PQ.Result -> IO a -> IO a
71+finishQueryWith' q result k = do
3472 status <- PQ.resultStatus result
3573 case status of
36− PQ.TuplesOk -> do
37− nrows <- PQ.ntuples result
38− ncols <- PQ.nfields result
39− forM' 0 (nrows-1) $ \row ->
40− getRowWith parser row ncols conn result
74+ PQ.TuplesOk -> k
4175 PQ.EmptyQuery -> queryErr "query: Empty query"
4276 PQ.CommandOk -> queryErr "query resulted in a command response"
4377 PQ.CopyOut -> queryErr "query: COPY TO is not supported"
src/Database/PostgreSQL/Simple/Vector.hsnew file+45
@@ -0,0 +1,45 @@
1+-- | 'query' variants returning 'V.Vector'.
2+module Database.PostgreSQL.Simple.Vector where
3+
4+import Database.PostgreSQL.Simple (Connection, formatQuery, formatMany)
5+import Database.PostgreSQL.Simple.FromRow (FromRow(..))
6+import Database.PostgreSQL.Simple.ToRow (ToRow(..))
7+import Database.PostgreSQL.Simple.Internal (RowParser, exec)
8+import Database.PostgreSQL.Simple.Internal.PQResultUtils
9+import Database.PostgreSQL.Simple.Types ( Query (..) )
10+
11+import qualified Data.Vector as V
12+
13+-- | Perform a @SELECT@ or other SQL query that is expected to return
14+-- results. All results are retrieved and converted before this
15+-- function returns.
16+query :: (ToRow q, FromRow r) => Connection -> Query -> q -> IO (V.Vector r)
17+query = queryWith fromRow
18+
19+-- | A version of 'query' that does not perform query substitution.
20+query_ :: (FromRow r) => Connection -> Query -> IO (V.Vector r)
21+query_ = queryWith_ fromRow
22+
23+-- | A version of 'query' taking parser as argument
24+queryWith :: ToRow q => RowParser r -> Connection -> Query -> q -> IO (V.Vector r)
25+queryWith parser conn template qs = do
26+ result <- exec conn =<< formatQuery conn template qs
27+ finishQueryWithV parser conn template result
28+
29+-- | A version of 'query_' taking parser as argument
30+queryWith_ :: RowParser r -> Connection -> Query -> IO (V.Vector r)
31+queryWith_ parser conn q@(Query que) = do
32+ result <- exec conn que
33+ finishQueryWithV parser conn q result
34+
35+-- | Execute @INSERT ... RETURNING@, @UPDATE ... RETURNING@, or other SQL
36+-- query that accepts multi-row input and is expected to return results.
37+returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO (V.Vector r)
38+returning = returningWith fromRow
39+
40+-- | A version of 'returning' taking parser as argument
41+returningWith :: (ToRow q) => RowParser r -> Connection -> Query -> [q] -> IO (V.Vector r)
42+returningWith _ _ _ [] = return V.empty
43+returningWith parser conn q qs = do
44+ result <- exec conn =<< formatMany conn q qs
45+ finishQueryWithV parser conn q result
src/Database/PostgreSQL/Simple/Vector/Unboxed.hsnew file+44
@@ -0,0 +1,44 @@
1+module Database.PostgreSQL.Simple.Vector.Unboxed where
2+
3+import Database.PostgreSQL.Simple (Connection, formatQuery, formatMany)
4+import Database.PostgreSQL.Simple.FromRow (FromRow(..))
5+import Database.PostgreSQL.Simple.ToRow (ToRow(..))
6+import Database.PostgreSQL.Simple.Internal (RowParser, exec)
7+import Database.PostgreSQL.Simple.Internal.PQResultUtils
8+import Database.PostgreSQL.Simple.Types ( Query (..) )
9+
10+import qualified Data.Vector.Unboxed as VU
11+
12+-- | Perform a @SELECT@ or other SQL query that is expected to return
13+-- results. All results are retrieved and converted before this
14+-- function returns.
15+query :: (ToRow q, FromRow r, VU.Unbox r) => Connection -> Query -> q -> IO (VU.Vector r)
16+query = queryWith fromRow
17+
18+-- | A version of 'query' that does not perform query substitution.
19+query_ :: (FromRow r, VU.Unbox r) => Connection -> Query -> IO (VU.Vector r)
20+query_ = queryWith_ fromRow
21+
22+-- | A version of 'query' taking parser as argument
23+queryWith :: (ToRow q, VU.Unbox r) => RowParser r -> Connection -> Query -> q -> IO (VU.Vector r)
24+queryWith parser conn template qs = do
25+ result <- exec conn =<< formatQuery conn template qs
26+ finishQueryWithVU parser conn template result
27+
28+-- | A version of 'query_' taking parser as argument
29+queryWith_ :: VU.Unbox r => RowParser r -> Connection -> Query -> IO (VU.Vector r)
30+queryWith_ parser conn q@(Query que) = do
31+ result <- exec conn que
32+ finishQueryWithVU parser conn q result
33+
34+-- | Execute @INSERT ... RETURNING@, @UPDATE ... RETURNING@, or other SQL
35+-- query that accepts multi-row input and is expected to return results.
36+returning :: (ToRow q, FromRow r, VU.Unbox r) => Connection -> Query -> [q] -> IO (VU.Vector r)
37+returning = returningWith fromRow
38+
39+-- | A version of 'returning' taking parser as argument
40+returningWith :: (ToRow q, VU.Unbox r) => RowParser r -> Connection -> Query -> [q] -> IO (VU.Vector r)
41+returningWith _ _ _ [] = return VU.empty
42+returningWith parser conn q qs = do
43+ result <- exec conn =<< formatMany conn q qs
44+ finishQueryWithVU parser conn q result