git.iko.soy/typeable/postgresql-simple
on 2800db2 help sign in
.ghcinew file+16
since splitsnapshots
unifiedsplit
@@ -0,0 +1,16 @@
1+:set -isrc -itest -optP-includedist/build/autogen/cabal_macros.h
2+:set -Wall -fno-warn-name-shadowing
3+
4+:set -XDoAndIfThenElse
5+:set -XOverloadedStrings
6+:set -XBangPatterns
7+:set -XViewPatterns
8+:set -XTypeOperators
9+
10+-- for tests
11+:set -XNamedFieldPuns
12+:set -XRank2Types
13+:set -XRecordWildCards
14+:set -XPatternGuards
15+:set -XScopedTypeVariables
16+:set -fno-warn-unused-do-bind
.github/workflows/haskell-ci.ymldeleted−256
@@ -1,256 +0,0 @@
1−# This GitHub workflow config has been generated by a script via
2−#
3−# haskell-ci 'github' 'cabal.project'
4−#
5−# To regenerate the script (for example after adjusting tested-with) run
6−#
7−# haskell-ci regenerate
8−#
9−# For more information, see https://github.com/haskell-CI/haskell-ci
10−#
11−# version: 0.17.20231110
12−#
13−# REGENDATA ("0.17.20231110",["github","cabal.project"])
14−#
15−name: Haskell-CI
16−on:
17− push:
18− branches:
19− - master
20− pull_request:
21− branches:
22− - master
23−jobs:
24− linux:
25− name: Haskell-CI - Linux - ${{ matrix.compiler }}
26− runs-on: ubuntu-20.04
27− timeout-minutes:
28− 60
29− container:
30− image: buildpack-deps:bionic
31− services:
32− postgres:
33− image: postgres:14
34− env:
35− POSTGRES_PASSWORD: postgres
36− options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
37− continue-on-error: ${{ matrix.allow-failure }}
38− strategy:
39− matrix:
40− include:
41− - compiler: ghc-9.8.1
42− compilerKind: ghc
43− compilerVersion: 9.8.1
44− setup-method: ghcup
45− allow-failure: false
46− - compiler: ghc-9.6.3
47− compilerKind: ghc
48− compilerVersion: 9.6.3
49− setup-method: ghcup
50− allow-failure: false
51− - compiler: ghc-9.4.8
52− compilerKind: ghc
53− compilerVersion: 9.4.8
54− setup-method: ghcup
55− allow-failure: false
56− - compiler: ghc-9.2.8
57− compilerKind: ghc
58− compilerVersion: 9.2.8
59− setup-method: ghcup
60− allow-failure: false
61− - compiler: ghc-9.0.2
62− compilerKind: ghc
63− compilerVersion: 9.0.2
64− setup-method: ghcup
65− allow-failure: false
66− - compiler: ghc-8.10.7
67− compilerKind: ghc
68− compilerVersion: 8.10.7
69− setup-method: ghcup
70− allow-failure: false
71− - compiler: ghc-8.8.4
72− compilerKind: ghc
73− compilerVersion: 8.8.4
74− setup-method: hvr-ppa
75− allow-failure: false
76− - compiler: ghc-8.6.5
77− compilerKind: ghc
78− compilerVersion: 8.6.5
79− setup-method: hvr-ppa
80− allow-failure: false
81− fail-fast: false
82− steps:
83− - name: apt
84− run: |
85− apt-get update
86− apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5
87− if [ "${{ matrix.setup-method }}" = ghcup ]; then
88− mkdir -p "$HOME/.ghcup/bin"
89− curl -sL https://downloads.haskell.org/ghcup/0.1.20.0/x86_64-linux-ghcup-0.1.20.0 > "$HOME/.ghcup/bin/ghcup"
90− chmod a+x "$HOME/.ghcup/bin/ghcup"
91− "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false)
92− "$HOME/.ghcup/bin/ghcup" install cabal 3.10.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
93− else
94− apt-add-repository -y 'ppa:hvr/ghc'
95− apt-get update
96− apt-get install -y "$HCNAME"
97− mkdir -p "$HOME/.ghcup/bin"
98− curl -sL https://downloads.haskell.org/ghcup/0.1.20.0/x86_64-linux-ghcup-0.1.20.0 > "$HOME/.ghcup/bin/ghcup"
99− chmod a+x "$HOME/.ghcup/bin/ghcup"
100− "$HOME/.ghcup/bin/ghcup" install cabal 3.10.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
101− fi
102− env:
103− HCKIND: ${{ matrix.compilerKind }}
104− HCNAME: ${{ matrix.compiler }}
105− HCVER: ${{ matrix.compilerVersion }}
106− - name: Set PATH and environment variables
107− run: |
108− echo "$HOME/.cabal/bin" >> $GITHUB_PATH
109− echo "LANG=C.UTF-8" >> "$GITHUB_ENV"
110− echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV"
111− echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV"
112− HCDIR=/opt/$HCKIND/$HCVER
113− if [ "${{ matrix.setup-method }}" = ghcup ]; then
114− HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER")
115− HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#')
116− HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#')
117− echo "HC=$HC" >> "$GITHUB_ENV"
118− echo "HCPKG=$HCPKG" >> "$GITHUB_ENV"
119− echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV"
120− echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.2.0 -vnormal+nowrap" >> "$GITHUB_ENV"
121− else
122− HC=$HCDIR/bin/$HCKIND
123− echo "HC=$HC" >> "$GITHUB_ENV"
124− echo "HCPKG=$HCDIR/bin/$HCKIND-pkg" >> "$GITHUB_ENV"
125− echo "HADDOCK=$HCDIR/bin/haddock" >> "$GITHUB_ENV"
126− echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.2.0 -vnormal+nowrap" >> "$GITHUB_ENV"
127− fi
128−
129− HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')
130− echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV"
131− echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV"
132− echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV"
133− echo "HEADHACKAGE=false" >> "$GITHUB_ENV"
134− echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV"
135− echo "GHCJSARITH=0" >> "$GITHUB_ENV"
136− env:
137− HCKIND: ${{ matrix.compilerKind }}
138− HCNAME: ${{ matrix.compiler }}
139− HCVER: ${{ matrix.compilerVersion }}
140− - name: env
141− run: |
142− env
143− - name: write cabal config
144− run: |
145− mkdir -p $CABAL_DIR
146− cat >> $CABAL_CONFIG <<EOF
147− remote-build-reporting: anonymous
148− write-ghc-environment-files: never
149− remote-repo-cache: $CABAL_DIR/packages
150− logs-dir: $CABAL_DIR/logs
151− world-file: $CABAL_DIR/world
152− extra-prog-path: $CABAL_DIR/bin
153− symlink-bindir: $CABAL_DIR/bin
154− installdir: $CABAL_DIR/bin
155− build-summary: $CABAL_DIR/logs/build.log
156− store-dir: $CABAL_DIR/store
157− install-dirs user
158− prefix: $CABAL_DIR
159− repository hackage.haskell.org
160− url: http://hackage.haskell.org/
161− EOF
162− cat >> $CABAL_CONFIG <<EOF
163− program-default-options
164− ghc-options: $GHCJOBS +RTS -M3G -RTS
165− EOF
166− cat $CABAL_CONFIG
167− - name: versions
168− run: |
169− $HC --version || true
170− $HC --print-project-git-commit-id || true
171− $CABAL --version || true
172− - name: update cabal index
173− run: |
174− $CABAL v2-update -v
175− - name: install cabal-plan
176− run: |
177− mkdir -p $HOME/.cabal/bin
178− curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.7.3.0/cabal-plan-0.7.3.0-x86_64-linux.xz > cabal-plan.xz
179− echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c -
180− xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan
181− rm -f cabal-plan.xz
182− chmod a+x $HOME/.cabal/bin/cabal-plan
183− cabal-plan --version
184− - name: checkout
185− uses: actions/checkout@v3
186− with:
187− path: source
188− - name: initial cabal.project for sdist
189− run: |
190− touch cabal.project
191− echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project
192− cat cabal.project
193− - name: sdist
194− run: |
195− mkdir -p sdist
196− $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist
197− - name: unpack
198− run: |
199− mkdir -p unpacked
200− find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \;
201− - name: generate cabal.project
202− run: |
203− PKGDIR_postgresql_simple="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/postgresql-simple-[0-9.]*')"
204− echo "PKGDIR_postgresql_simple=${PKGDIR_postgresql_simple}" >> "$GITHUB_ENV"
205− rm -f cabal.project cabal.project.local
206− touch cabal.project
207− touch cabal.project.local
208− echo "packages: ${PKGDIR_postgresql_simple}" >> cabal.project
209− echo "package postgresql-simple" >> cabal.project
210− echo " ghc-options: -Werror=missing-methods" >> cabal.project
211− cat >> cabal.project <<EOF
212− allow-newer: cryptohash-md5-0.11.100.1:base
213− EOF
214− $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: $_ installed\n" unless /^(postgresql-simple)$/; }' >> cabal.project.local
215− cat cabal.project
216− cat cabal.project.local
217− - name: dump install plan
218− run: |
219− $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
220− cabal-plan
221− - name: restore cache
222− uses: actions/cache/restore@v3
223− with:
224− key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
225− path: ~/.cabal/store
226− restore-keys: ${{ runner.os }}-${{ matrix.compiler }}-
227− - name: install dependencies
228− run: |
229− $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all
230− $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all
231− - name: build w/o tests
232− run: |
233− $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
234− - name: build
235− run: |
236− $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always
237− - name: tests
238− run: |
239− $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct
240− - name: cabal check
241− run: |
242− cd ${PKGDIR_postgresql_simple} || false
243− ${CABAL} -vnormal check
244− - name: haddock
245− run: |
246− $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
247− - name: unconstrained build
248− run: |
249− rm -f cabal.project.local
250− $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
251− - name: save cache
252− uses: actions/cache/save@v3
253− if: always()
254− with:
255− key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
256− path: ~/.cabal/store
.github/workflows/simple.ymldeleted−58
@@ -1,58 +0,0 @@
1−name: Simple
2−on:
3− push:
4− branches:
5− - master
6− pull_request:
7− branches:
8− - master
9−
10−jobs:
11− native:
12− name: "Simple: GHC ${{ matrix.ghc }} on ${{ matrix.os }}"
13− runs-on: ${{ matrix.os }}
14− strategy:
15− matrix:
16− os: [macos-latest, windows-latest]
17− ghc: ['8.10','9.0','9.2','9.4.8','9.6.3','9.8.1']
18− fail-fast: false
19− timeout-minutes:
20− 60
21− steps:
22− - name: Set git to use LF
23− run: |
24− git config --global core.autocrlf false
25− git config --global core.eol lf
26−
27− - name: Set up Haskell
28− id: setup-haskell
29− uses: haskell/actions/setup@v2
30− with:
31− ghc-version: ${{ matrix.ghc }}
32− cabal-version: '3.10.2.0'
33−
34− - name: Set up PostgreSQL
35− uses: ikalnytskyi/action-setup-postgres@v3
36− id: postgres
37− with:
38− username: ci
39− password: sw0rdfish
40− database: test
41−
42− - name: Checkout
43− uses: actions/checkout@v3.0.2
44−
45− - name: Cache
46− uses: actions/cache@v2.1.3
47− with:
48− path: ${{ steps.setup-haskell.outputs.cabal-store }}
49− key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }}
50− restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
51−
52− - name: Build
53− run: cabal build all --enable-tests
54−
55− - name: Test
56− run: cabal test all --enable-tests --test-show-details=direct
57− env:
58− DATABASE_CONNSTRING: ${{ steps.postgres.outputs.connection-uri }}
.gitignore−5
@@ -7,11 +7,6 @@ dist/
7*.o
7*.o
8\#*\#
8\#*\#
9.#*
9.#*
10−/CHANGELOG.md
11.cabal-sandbox/
10.cabal-sandbox/
12.stack-work/
11.stack-work/
13cabal.sandbox.config
12cabal.sandbox.config
14−/dist-newstyle
15−.ghc.environment.*
16−cabal.project.local
17−dump-core
.travis.ymlnew file+11
@@ -0,0 +1,11 @@
1+language: haskell
2+
3+ghc:
4+ - "7.6"
5+ - "7.8"
6+
7+addons:
8+ postgresql: "9.3"
9+
10+before_install:
11+ - createdb `whoami` || true
CHANGES.md+5−195
@@ -1,193 +1,3 @@
1−### Version 0.7.0.0 (2023-07-31)
2−
3− * Remove Eq Null instance. (Future `base` may break it, we remove it profilacticly).
4− * Use `postgresql-libpq >=0.10.0.0`. It includes critical fixes,
5− by using `postgresql-simple >=0.7` you won't get older `postgresql-libpq`.
6− * Drop support for GHC prior 8.6
7− * Added a class for `postgresql-simple` exceptions: `SomePostgreSqlException`.
8− This allows to catch all `postgresql-simple` exceptions at once.
9− (c.f. `AsyncException` in `base).
10−
11−### Version 0.6.5.1 (2023-07-09)
12−
13− * Support `aeson-2.2.0.0`
14−
15−### Version 0.6.5 (2022-10-30)
16−
17− * Add `withConnect`
18−
19−### Version 0.6.4 (2021-01-06)
20−
21− * Add foldCopyData helper function
22− Thanks to Sebastián Estrella for the implementation
23− https://github.com/haskellari/postgresql-simple/pull/56
24− * Implement support for postgresql 'interval' type
25− Thanks to Andre Marques Lee for the implementation
26− https://github.com/haskellari/postgresql-simple/pull/60
27− * Depend on `time-compat` to provide uniform `time` related interface.
28−
29−### Version 0.6.3 (2020-11-15)
30−
31− * Add `fromFieldJSONByteString`
32− Thanks to tomjaguarpaw for the implementation
33− https://github.com/haskellari/postgresql-simple/pull/47
34− * Add `attoFieldParser`
35− Thanks to Victor Nawothnig for the implementation
36− https://github.com/haskellari/postgresql-simple/pull/45
37− * Add `Identity` and `Const` instance
38− Thanks to Cary Robbins for the implementation
39− https://github.com/haskellari/postgresql-simple/pull/46
40− * Add `withTransactionModeRetry'`, a variant of `withTransactionModeRetry`
41− for all exception types.
42− Thanks to Elliot Cameron for the implementation
43− https://github.com/haskellari/postgresql-simple/pull/42
44− * Fix spurious aborts when retrying transactions
45− Thanks to Elliot Cameron for the implementation
46− https://github.com/haskellari/postgresql-simple/pull/34
47− * Add `Database.PostgreSQL.Simple.Newtypes` module
48− with `Aeson` newtype.
49− https://github.com/haskellari/postgresql-simple/pull/55
50−
51−### Version 0.6.2 (2019-04-26)
52−
53− * Define `MonadFail Ok`.
54−
55−### Version 0.6.1 (2019-03-04)
56−
57− * Escape double '??' to a literal '?
58− Thanks to Felix Paulusma for the implementation.
59− https://github.com/phadej/postgresql-simple/pull/5
60−
61− * Mention GHC Generics support in the documentation.
62− Thanks to Gabriel Gonzalez for the implementation.
63− https://github.com/phadej/postgresql-simple/pull/6
64−
65− * Better error message for "Query resulted in a command response
66− Thanks to Max Amanshauser for the implementation.
67− https://github.com/phadej/postgresql-simple/pull/7
68−
69− * fromJSONField: Include JSONPath on JSON parse errors
70− Thanks to Simon Hengel for the implementation.
71− https://github.com/phadej/postgresql-simple/pull/2
72−
73− * No TH in implementation
74− https://github.com/phadej/postgresql-simple/pull/4
75−
76−### Version 0.6 (2018-10-16)
77−
78− * *Breaking change*: Use `Only` package's `Only` for a common 1-tuple.
79−
80− Consider a downstream library depending already both on
81− `Only` and `postgresql-simple` package. This library my define
82− a `MyClass` with instances for `Only.Only` and `PostgreSQL.Only`.
83− As now these types are the same, a library would break.
84− Therefore I consider "merging" types a breaking change.
85−
86− There are two ways for adopting this change in that scenario:
87−
88− - Either CPP-guard `PostgreSQL.Only` instance with
89−
90− ```haskell
91− #if !MIN_VERSION_postgresql_simple(0,6,0)
92− instance MyClass (PostgreSQL.Only a) where ...
93− #endif
94− ```
95−
96− - or simply remove it and add `postgresql-simple >=0.6` lower bound,
97− making sure that there's only single `Only`.
98−
99− * Add `ToField` instances for case-insensitive strict and lazy text.
100− Thanks to Max Tagher for the implementation.
101− https://github.com/lpsmith/postgresql-simple/pull/232
102−
103− * Add support to CockroachDB.
104− Thanks to Georte Steel.
105− https://github.com/lpsmith/postgresql-simple/pull/245
106−
107− * Add Generic ConnectInfo instance
108− Thanks to Dmitry Dzhus.
109− https://github.com/lpsmith/postgresql-simple/pull/235
110−
111− * Add `fromFieldRange :: Typeable a => FieldParser a -> FieldParser (PGRange a)`
112− https://github.com/lpsmith/postgresql-simple/pull/221
113−
114− * Add `fromFieldJSONByteString :: FieldParser ByteString`
115− https://github.com/lpsmith/postgresql-simple/pull/222/files
116−
117− * Fix off-by-one error in year builder.
118− Thanks to Nathan Ferris Hunter.
119− https://github.com/lpsmith/postgresql-simple/pull/230
120−
121− * Extend ToRow and FromRow to tuples of size 18
122− Thanks to Bardur Arantsson.
123− https://github.com/lpsmith/postgresql-simple/pull/229
124−
125− * Add `Vector` and `Vector.Unboxed` `query` variants.
126− These are more memory efficient
127− (especially, if you anyway will convert to some vector)
128− https://github.com/phadej/1
129−
130− * Documentation improvements
131− https://github.com/lpsmith/postgresql-simple/pull/227
132− https://github.com/lpsmith/postgresql-simple/pull/236
133−
134−### Version 0.5.4.0 (2018-05-23)
135− * Support GHC-8.4 (Semigroup/Monoid)
136−
137−### Version 0.5.3.0 (2017-05-15)
138− * Refactored some rudimentary cursor handling code out of the
139− implementation of the fold operators, into a new
140− `Database.PostgreSQL.Simple.Cursor` module, thanks to Bardur Arantsson.
141−
142− * Made the `FromField` instance for `Char` compatible with
143− postgresql's `bpchar` type. Thanks to Ivan Lazar Miljenovic for
144− reporting the issue.
145−
146− * Added `Show` and `Eq` instances for `Notification`, thanks to
147− Matvey Aksenov.
148−
149− * Fixed some example code, thanks to Matvey Aksenov.
150−
151− * Fixed a problem with using `conversionError` to throw exceptions
152− of type `SomeException`. Previously, the exception would be
153− wrapped in a second `SomeException` dynamic constructor which
154− would cause normal GHC typecase idioms over `SomeException` to fail.
155−
156−### Version 0.5.2.1 (2016-06-29)
157− * Bumped the lower bound for `base` to 4.6. Thanks to Herbert
158− Valerio Riedel for reporting the issue.
159−
160− * Added an `Eq` instance for `SqlError`, thanks to Chris Allen
161−
162− * Fixed a bug where a all-caps `"NULL"` text value inside a
163− postgresql array would get parsed as the SQL null value. Thanks
164− goes to Edgar Gomes and Silk for finding and fixing this mistake.
165−
166− * Modified `withTransaction` and friends to ignore `IOError`s when
167− attempting to roll back the transaction. This fixes a buggy
168− interaction between `withTransaction` and async exceptions (e.g.
169− `System.Timeout`) on unix platforms. Thanks goes to Erik
170− Hesselink and Silk for providing the test case that exposed this
171− issue.
172−
173− * Added the `testTimeout` regression test for the problem above.
174−
175−### Version 0.5.2.0 (2016-05-25)
176− * Significantly improved the error reporting from
177− `Copy.putCopyData`, thanks to Ben Gamari.
178−
179− * Moved the test suite to use `tasty`, with a big thanks
180− to Ben Gamari.
181−
182− * Added `FromField.optionalField`, and updated the documentation
183− of `FromField.fromJSONField`, as inspired by an email conversation
184− with Ian Wagner.
185−
186− * Updated all links in the haddocks to use https, and added a link
187− to the documentation of `connectPostgreSQL`.
188−
189− * Added a truncated changelog to the source distribution.
190−
191### Version 0.5.1.3 (2016-04-30)
1### Version 0.5.1.3 (2016-04-30)
192 * Implemented the Monad of No Return proposal, future-proofing
2 * Implemented the Monad of No Return proposal, future-proofing
193 postgresql-simple against future releases of GHC.
3 postgresql-simple against future releases of GHC.
@@ -271,7 +81,7 @@
271 support UTF8 except for Mule Internal Code, the Multilingual
81 support UTF8 except for Mule Internal Code, the Multilingual
272 Extensions for Emacs. An exception should be raised upon
82 Extensions for Emacs. An exception should be raised upon
273 connecting to a database by the backend if the backend cannot
83 connecting to a database by the backend if the backend cannot
274− accommodate this requirement.
84+ accomodate this requirement.
275
85
276 * Added `Eq` and `Typeable` instances for `Connection`.
86 * Added `Eq` and `Typeable` instances for `Connection`.
277
87
@@ -391,7 +201,7 @@
391 * De-emphasized connect and ConnectInfo in favor of connectPostgreSQL.
201 * De-emphasized connect and ConnectInfo in favor of connectPostgreSQL.
392
202
393### Version 0.4.2.2 (2014-05-15)
203### Version 0.4.2.2 (2014-05-15)
394− * Fixed compatibility with scientific-0.3.\*, thanks to Adam Bergmark
204+ * Fixed compatibility with scientific-0.3.*, thanks to Adam Bergmark
395
205
396 * Improved documentation of the FromField module, as well as the fold,
206 * Improved documentation of the FromField module, as well as the fold,
397 foldWithOptions, executeMany, and returning operators.
207 foldWithOptions, executeMany, and returning operators.
@@ -409,7 +219,7 @@
409
219
410 * Changed the Identifier and QualifiedIdentifier to use Text in
220 * Changed the Identifier and QualifiedIdentifier to use Text in
411 order to avoid encoding errors. Technically this requires a
221 order to avoid encoding errors. Technically this requires a
412− major version bump, but let's pretend 0.4.1.0 didn't happen.
222+ major verson bump, but let's pretend 0.4.1.0 didn't happen.
413
223
414 * Removed non-exhaustive cases in the ToField instance for Values,
224 * Removed non-exhaustive cases in the ToField instance for Values,
415 and tweaked error messages.
225 and tweaked error messages.
@@ -569,7 +379,7 @@
569
379
570 * Added a brand new TypeInfo system that gives FromField instances
380 * Added a brand new TypeInfo system that gives FromField instances
571 convenient and efficient access to the pg_type metatable. This
381 convenient and efficient access to the pg_type metatable. This
572− replaced the older typename cache, and was necessary to properly
382+ replaced the older typename cache, and was neccesary to properly
573 support postgres array types. Thanks to Bas van Dijk for his
383 support postgres array types. Thanks to Bas van Dijk for his
574 work on this feature.
384 work on this feature.
575
385
@@ -661,7 +471,7 @@
661 now the preferred way of dealing with `timestamp` (without time zone).
471 now the preferred way of dealing with `timestamp` (without time zone).
662
472
663 * `Database.PostgreSQL.Simple.Time` is a new module that offers types
473 * `Database.PostgreSQL.Simple.Time` is a new module that offers types
664− that accommodate PostgreSQL's infinities.
474+ that accomodate PostgreSQL's infinities.
665
475
666 * All time-related `FromField`/`ToField` instances are now based on new,
476 * All time-related `FromField`/`ToField` instances are now based on new,
667 higher-speed parsers and printers instead of those provided by the
477 higher-speed parsers and printers instead of those provided by the
CONTRIBUTING.mddeleted−13
@@ -1,13 +0,0 @@
1−Patches welcome!
2−
3−- If you are only going to bump bounds:
4− - If it's really **only bounds**, please simply open an issue (so you'll have a URL to refer to). I have a semi-automated process to make revisions, pull requests only disturb it.
5− - If patch includes **source code change** (i.e. I'll need to make a release), and it's a patch to support **newer base/GHC version**:
6− - Amend `tested-with` to include that GHC
7− - Regenerate `.github/workflows/haskell-ci.yml` with `haskell-ci regenerate` (get the latest from [GitHub haskell-ci/haskell-ci](https://github.com/haskell-ci/haskell-ci))
8−
9−- Don't edit `CHANGELOG.md`, rather include a copyable entry in your pull request description. I often process pull requests in bulk, and everyone editing the `CHANGELOG.md` causes unnecessary conflicts.
10−- For the same reason, do not edit `version` or `x-revision`
11−
12−- I use [`stylish-haskell`](https://github.com/jaspervdj/stylish-haskell) to format imports. I encourage you to use it too, when contributing.
13−- General code style is 4 spaces, just look around how it looks, it's not so strict.
CONTRIBUTORS−4
@@ -30,7 +30,3 @@ Timmy Tofu <timmytofu@users.noreply.github.com>
30Alexey Khudyakov <alexey.skladnoy@gmail.com>
30Alexey Khudyakov <alexey.skladnoy@gmail.com>
31Timo von Holtz <tvh@anchor.com.au>
31Timo von Holtz <tvh@anchor.com.au>
32Amit Levy <amit@amitlevy.com>
32Amit Levy <amit@amitlevy.com>
33−Ben Gamari <ben@smart-cactus.org>
34−Edgar Gomes Araujo <talktoedgar@gmail.com>
35−Erik Hesselink <hesselink@gmail.com>
36−Matvey Aksenov <matvey.aksenov@gmail.com>
README.md+3
@@ -1,4 +1,7 @@
1+[![Continuous Integration status][status-png]][status]
1[![Hackage page (downloads and API reference)][hackage-png]][hackage]
2[![Hackage page (downloads and API reference)][hackage-png]][hackage]
2
3
4+ [status-png]: https://api.travis-ci.org/lpsmith/postgresql-simple.svg
5+ [status]: http://travis-ci.org/lpsmith/postgresql-simple?branch=master
3 [hackage-png]: http://img.shields.io/hackage/v/postgresql-simple.svg
6 [hackage-png]: http://img.shields.io/hackage/v/postgresql-simple.svg
4 [hackage]: http://hackage.haskell.org/package/postgresql-simple
7 [hackage]: http://hackage.haskell.org/package/postgresql-simple
bench/Select.hsdeleted−32
@@ -1,32 +0,0 @@
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
cabal.haskell-cideleted−5
@@ -1,5 +0,0 @@
1−branches: master
2−postgresql: True
3−
4−-- services aren't supported on Travis on macOS
5−-- osx: 8.4.4
cabal.projectdeleted−4
@@ -1,4 +0,0 @@
1−packages: .
2−tests: true
3−
4−allow-newer: cryptohash-md5-0.11.100.1:base
cabal.project.local.windeleted−4
@@ -1,4 +0,0 @@
1−constraints: these -assoc
2−
3−package postgresql-libpq
4− flags: -use-pkg-config
postgresql-simple.cabal+118−163
@@ -1,175 +1,130 @@
1−cabal-version: 1.12
2−name: postgresql-simple
1+Name: postgresql-simple
3−version: 0.7.0.0
2+Version: 0.5.1.3
4−x-revision: 1
5−synopsis: Mid-Level PostgreSQL client library
3+Synopsis: Mid-Level PostgreSQL client library
6−description:
4+Description:
7− Mid-Level PostgreSQL client library, forked from mysql-simple.
5+ Mid-Level PostgreSQL client library, forked from mysql-simple.
8−
6+License: BSD3
9−license: BSD3
10−license-file: LICENSE
7+License-file: LICENSE
11−author: Bryan O'Sullivan, Leon P Smith
8+Author: Bryan O'Sullivan, Leon P Smith
12−maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>
9+Maintainer: Leon P Smith <leon@melding-monads.com>
13−copyright:
14− (c) 2011 MailRank, Inc.
10+Copyright: (c) 2011 MailRank, Inc.
15− (c) 2011-2018 Leon P Smith
11+ (c) 2011-2015 Leon P Smith
16− (c) 2018-2020 Oleg Grenrus
17−
18−category: Database
12+Category: Database
19−build-type: Simple
13+Build-type: Simple
14+
15+Cabal-version: >= 1.9.2
16+
20extra-source-files:
17extra-source-files:
21− CHANGES.md
22− CONTRIBUTORS
18+ CONTRIBUTORS
23− test/results/malformed-input.expected
19+
24− test/results/unique-constraint-violation.expected
20+Library
25−
26−tested-with:
27− GHC ==8.6.5
28− || ==8.8.4
29− || ==8.10.7
30− || ==9.0.2
31− || ==9.2.8
32− || ==9.4.8
33− || ==9.6.3
34− || ==9.8.1
35−
36−library
37− default-language: Haskell2010
38− hs-source-dirs: src
21+ hs-source-dirs: src
39− exposed-modules:
22+ Exposed-modules:
40− Database.PostgreSQL.Simple
23+ Database.PostgreSQL.Simple
41− Database.PostgreSQL.Simple.Arrays
24+ Database.PostgreSQL.Simple.Arrays
42− Database.PostgreSQL.Simple.Copy
25+ Database.PostgreSQL.Simple.Copy
43− Database.PostgreSQL.Simple.Cursor
44− Database.PostgreSQL.Simple.Errors
45− Database.PostgreSQL.Simple.FromField
26+ Database.PostgreSQL.Simple.FromField
46− Database.PostgreSQL.Simple.FromRow
27+ Database.PostgreSQL.Simple.FromRow
47− Database.PostgreSQL.Simple.HStore
48− Database.PostgreSQL.Simple.HStore.Internal
49− Database.PostgreSQL.Simple.Internal
50− Database.PostgreSQL.Simple.LargeObjects
28+ Database.PostgreSQL.Simple.LargeObjects
51− Database.PostgreSQL.Simple.Newtypes
29+ Database.PostgreSQL.Simple.HStore
30+ Database.PostgreSQL.Simple.HStore.Internal
52− Database.PostgreSQL.Simple.Notification
31+ Database.PostgreSQL.Simple.Notification
53− Database.PostgreSQL.Simple.Ok
32+ Database.PostgreSQL.Simple.Ok
54− Database.PostgreSQL.Simple.Range
33+ Database.PostgreSQL.Simple.Range
55− Database.PostgreSQL.Simple.SqlQQ
34+ Database.PostgreSQL.Simple.SqlQQ
56− Database.PostgreSQL.Simple.Time
35+ Database.PostgreSQL.Simple.Time
57− Database.PostgreSQL.Simple.Time.Internal
36+ Database.PostgreSQL.Simple.Time.Internal
58− Database.PostgreSQL.Simple.ToField
37+ Database.PostgreSQL.Simple.ToField
59− Database.PostgreSQL.Simple.ToRow
38+ Database.PostgreSQL.Simple.ToRow
60− Database.PostgreSQL.Simple.Transaction
39+ Database.PostgreSQL.Simple.Transaction
61− Database.PostgreSQL.Simple.TypeInfo
40+ Database.PostgreSQL.Simple.TypeInfo
62− Database.PostgreSQL.Simple.TypeInfo.Macro
41+ Database.PostgreSQL.Simple.TypeInfo.Macro
63− Database.PostgreSQL.Simple.TypeInfo.Static
42+ Database.PostgreSQL.Simple.TypeInfo.Static
64− Database.PostgreSQL.Simple.Types
43+ Database.PostgreSQL.Simple.Types
65− Database.PostgreSQL.Simple.Vector
44+ Database.PostgreSQL.Simple.Errors
45+-- Other-modules:
66− Database.PostgreSQL.Simple.Vector.Unboxed
46+ Database.PostgreSQL.Simple.Internal
67−
47+
68− -- Other-modules:
48+ Other-modules:
69− other-modules:
70− Database.PostgreSQL.Simple.Compat
49+ Database.PostgreSQL.Simple.Compat
71− Database.PostgreSQL.Simple.HStore.Implementation
50+ Database.PostgreSQL.Simple.HStore.Implementation
72− Database.PostgreSQL.Simple.Internal.PQResultUtils
73− Database.PostgreSQL.Simple.Time.Implementation
51+ Database.PostgreSQL.Simple.Time.Implementation
74− Database.PostgreSQL.Simple.Time.Internal.Parser
52+ Database.PostgreSQL.Simple.Time.Internal.Parser
75− Database.PostgreSQL.Simple.Time.Internal.Printer
53+ Database.PostgreSQL.Simple.Time.Internal.Printer
76− Database.PostgreSQL.Simple.TypeInfo.Types
54+ Database.PostgreSQL.Simple.TypeInfo.Types
77−
55+
78− -- GHC bundled libs
79− build-depends:
56+ Build-depends:
80− base >=4.12.0.0 && <4.20
81− , bytestring >=0.10.8.2 && <0.13
82− , containers >=0.6.0.1 && <0.7
83− , template-haskell >=2.14.0.0 && <2.22
84− , text >=1.2.3.0 && <1.3 || >=2.0 && <2.2
85− , time-compat >=1.9.5 && <1.12
86− , transformers >=0.5.6.2 && <0.7
87−
88− -- Other dependencies
89− build-depends:
90− aeson >=2.1.2.1 && <2.3
57+ aeson >= 0.6,
91− , attoparsec >=0.14.4 && <0.15
58+ attoparsec >= 0.10.3,
59+ base >= 4.4 && < 5,
60+ bytestring >= 0.9,
61+ bytestring-builder,
92− , case-insensitive >=1.2.1.0 && <1.3
62+ case-insensitive,
63+ containers,
93− , hashable >=1.4.3.0 && <1.5
64+ hashable,
94− , Only >=0.1 && <0.1.1
95− , postgresql-libpq >=0.10.0.0 && <0.11
65+ postgresql-libpq >= 0.9 && < 0.10,
96− , scientific >=0.3.7.0 && <0.4
66+ template-haskell,
67+ text >= 0.11.1,
68+ time,
69+ transformers,
97− , uuid-types >=1.0.5 && <1.1
70+ uuid-types >= 1.0.0,
71+ scientific,
98− , vector >=0.13.0.0 && <0.14
72+ vector
99−
73+
100− default-extensions:
74+ if !impl(ghc >= 7.6)
101− BangPatterns
75+ Build-depends:
102− DoAndIfThenElse
76+ ghc-prim
77+
103− OverloadedStrings
78+ extensions: DoAndIfThenElse, OverloadedStrings, BangPatterns, ViewPatterns
104− TypeOperators
79+ TypeOperators
105− ViewPatterns
80+
106−
107− ghc-options: -Wall -fno-warn-name-shadowing
81+ ghc-options: -Wall -fno-warn-name-shadowing
108
82
109source-repository head
83source-repository head
110 type: git
84 type: git
111− location: http://github.com/haskellari/postgresql-simple
85+ location: http://github.com/lpsmith/postgresql-simple
112−
86+
113−test-suite inspection
87+source-repository this
114− default-language: Haskell2010
88+ type: git
115− type: exitcode-stdio-1.0
89+ location: http://github.com/lpsmith/postgresql-simple
116− hs-source-dirs: test
90+ tag: v0.5.1.3
117− main-is: Inspection.hs
118− build-depends:
119− base
120− , inspection-testing >=0.4.1.1 && <0.6
121− , postgresql-libpq
122− , postgresql-simple
123− , tasty
124− , tasty-hunit
125
91
126test-suite test
92test-suite test
127− default-language: Haskell2010
128− type: exitcode-stdio-1.0
93+ type: exitcode-stdio-1.0
94+
129− hs-source-dirs: test
95+ hs-source-dirs: test
130− main-is: Main.hs
96+ main-is: Main.hs
131 other-modules:
97 other-modules:
132 Common
98 Common
133− Exception
134− Interval
135 Notify
99 Notify
136 Serializable
100 Serializable
137 Time
101 Time
138
102
139− ghc-options: -threaded
140− ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
103+ ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
141− default-extensions:
104+
142− NamedFieldPuns
105+ extensions: NamedFieldPuns
143− OverloadedStrings
106+ , OverloadedStrings
144− PatternGuards
145− Rank2Types
107+ , Rank2Types
146− RecordWildCards
108+ , RecordWildCards
109+ , PatternGuards
147− ScopedTypeVariables
110+ , ScopedTypeVariables
148−
111+
149− build-depends:
112+ build-depends: base
150− aeson
113+ , aeson
151− , base
152− , base16-bytestring
114+ , base16-bytestring
153− , bytestring
115+ , bytestring
154− , case-insensitive
155− , containers
116+ , containers
156− , cryptohash-md5 >=0.11.100.1 && <0.12
117+ , cryptohash
157− , filepath
118+ , filepath
158− , HUnit
159− , postgresql-simple
160− , tasty
161− , tasty-golden
119+ , tasty
162− , tasty-hunit
120+ , tasty-hunit
121+ , tasty-golden
122+ , HUnit
123+ , postgresql-simple
163− , text
124+ , text
164− , time-compat
125+ , time
165− , vector
126+ , vector
166−
127+
167−benchmark select
128+ if !impl(ghc >= 7.6)
168− default-language: Haskell2010
169− type: exitcode-stdio-1.0
170− hs-source-dirs: bench
171− main-is: Select.hs
172− build-depends:
129+ build-depends:
173− base
130+ ghc-prim
174− , postgresql-simple
175− , vector
sdist.shdeleted−25
@@ -1,25 +0,0 @@
1−#!/bin/bash
2−
3−echo "Generating CHANGELOG.md"
4−echo
5−
6−cat <<HEADER > CHANGELOG.md
7−For the full changelog, see
8−<https://github.com/lpsmith/postgresql-simple/blob/master/CHANGES.md>
9−
10−HEADER
11−
12−perl -ne '$n++ if /^###/; exit if $n==2; print' CHANGES.md >> CHANGELOG.md
13−
14−cat CHANGELOG.md
15−rm -f ./dist/*.tar
16−rm -f ./dist/*.tar.gz
17−cabal sdist
18−cd dist
19−wc *.tar.gz
20−gunzip *.gz
21−wc *.tar
22−zopfli *.tar
23−wc *.tar.gz
24−cd ..
25−rm -f ./dist/*.tar
src/Database/PostgreSQL/Simple.hs+119−36
@@ -64,7 +64,6 @@ module Database.PostgreSQL.Simple
64 , Only(..)
64 , Only(..)
65 , (:.)(..)
65 , (:.)(..)
66 -- ** Exceptions
66 -- ** Exceptions
67− , SomePostgreSqlException(..)
68 , SqlError(..)
67 , SqlError(..)
69 , PQ.ExecStatus(..)
68 , PQ.ExecStatus(..)
70 , FormatError(..)
69 , FormatError(..)
@@ -74,7 +73,6 @@ module Database.PostgreSQL.Simple
74 , Base.connectPostgreSQL
73 , Base.connectPostgreSQL
75 , Base.close
74 , Base.close
76 , Base.connect
75 , Base.connect
77− , Base.withConnect
78 , Base.ConnectInfo(..)
76 , Base.ConnectInfo(..)
79 , Base.defaultConnectInfo
77 , Base.defaultConnectInfo
80 , Base.postgreSQLConnectionString
78 , Base.postgreSQLConnectionString
@@ -120,26 +118,30 @@ module Database.PostgreSQL.Simple
120 , formatQuery
118 , formatQuery
121 ) where
119 ) where
122
120
123−import Data.ByteString.Builder (Builder, byteString, char8)
121+import Data.ByteString.Builder
122+ ( Builder, byteString, char8, intDec )
124import Control.Applicative ((<$>))
123import Control.Applicative ((<$>))
125import Control.Exception as E
124import Control.Exception as E
125+import Control.Monad (unless)
126import Data.ByteString (ByteString)
126import Data.ByteString (ByteString)
127import Data.Int (Int64)
127import Data.Int (Int64)
128import Data.List (intersperse)
128import Data.List (intersperse)
129import Data.Monoid (mconcat)
129import Data.Monoid (mconcat)
130−import Database.PostgreSQL.Simple.Compat ((<>), toByteString)
130+import Database.PostgreSQL.Simple.Compat ( (<>), toByteString )
131−import Database.PostgreSQL.Simple.Cursor
132import Database.PostgreSQL.Simple.FromField (ResultError(..))
131import Database.PostgreSQL.Simple.FromField (ResultError(..))
133import Database.PostgreSQL.Simple.FromRow (FromRow(..))
132import Database.PostgreSQL.Simple.FromRow (FromRow(..))
133+import Database.PostgreSQL.Simple.Ok
134import Database.PostgreSQL.Simple.ToField (Action(..))
134import Database.PostgreSQL.Simple.ToField (Action(..))
135import Database.PostgreSQL.Simple.ToRow (ToRow(..))
135import Database.PostgreSQL.Simple.ToRow (ToRow(..))
136import Database.PostgreSQL.Simple.Types
136import Database.PostgreSQL.Simple.Types
137 ( Binary(..), In(..), Only(..), Query(..), (:.)(..) )
137 ( Binary(..), In(..), Only(..), Query(..), (:.)(..) )
138import Database.PostgreSQL.Simple.Internal as Base
138import Database.PostgreSQL.Simple.Internal as Base
139−import Database.PostgreSQL.Simple.Internal.PQResultUtils
140import Database.PostgreSQL.Simple.Transaction
139import Database.PostgreSQL.Simple.Transaction
140+import Database.PostgreSQL.Simple.TypeInfo
141import qualified Database.PostgreSQL.LibPQ as PQ
141import qualified Database.PostgreSQL.LibPQ as PQ
142import qualified Data.ByteString.Char8 as B
142import qualified Data.ByteString.Char8 as B
143+import Control.Monad.Trans.Reader
144+import Control.Monad.Trans.State.Strict
143
145
144
146
145-- | Format a query string.
147-- | Format a query string.
@@ -278,31 +280,21 @@ parseTemplate template =
278 skipSpace = B.dropWhile isSpace_ascii
280 skipSpace = B.dropWhile isSpace_ascii
279
281
280
282
283+
281buildQuery :: Connection -> Query -> ByteString -> [Action] -> IO Builder
284buildQuery :: Connection -> Query -> ByteString -> [Action] -> IO Builder
282buildQuery conn q template xs =
285buildQuery conn q template xs =
283 zipParams (split template) <$> mapM (buildAction conn q xs) xs
286 zipParams (split template) <$> mapM (buildAction conn q xs) xs
284 where split s =
287 where split s =
285− -- This part escapes double '??'s to make literal '?'s possible
288+ let (h,t) = B.break (=='?') s
286− -- in PostgreSQL queries using the JSON operators: @?@, @?|@ and @?&@
287− let (h,t) = breakOnSingleQuestionMark s
288 in byteString h
289 in byteString h
289 : if B.null t
290 : if B.null t
290 then []
291 then []
291 else split (B.tail t)
292 else split (B.tail t)
292 zipParams (t:ts) (p:ps) = t <> p <> zipParams ts ps
293 zipParams (t:ts) (p:ps) = t <> p <> zipParams ts ps
293 zipParams [t] [] = t
294 zipParams [t] [] = t
294− zipParams _ _ = fmtError (show countSingleQs ++
295+ zipParams _ _ = fmtError (show (B.count '?' template) ++
295− " single '?' characters, but " ++
296+ " '?' characters, but " ++
296 show (length xs) ++ " parameters") q xs
297 show (length xs) ++ " parameters") q xs
297− countSingleQs = go 0 template
298− where go i "" = (i :: Int)
299− go i bs = case qms of
300− ("?","?") -> go i nextQMBS
301− ("?",_) -> go (i+1) nextQMBS
302− _ -> i
303− where qms = B.splitAt 1 qmBS
304− (qmBS,nextQMBS) = B.splitAt 2 qmBS'
305− qmBS' = B.dropWhile (/= '?') bs
306
298
307-- | Execute an @INSERT@, @UPDATE@, or other SQL query that is not
299-- | Execute an @INSERT@, @UPDATE@, or other SQL query that is not
308-- expected to return results.
300-- expected to return results.
@@ -340,7 +332,7 @@ execute conn template qs = do
340-- @
332-- @
341-- executeMany c [sql|
333-- executeMany c [sql|
342-- UPDATE sometable
334-- UPDATE sometable
343−-- SET y = upd.y
335+-- SET sometable.y = upd.y
344-- FROM (VALUES (?,?)) as upd(x,y)
336-- FROM (VALUES (?,?)) as upd(x,y)
345-- WHERE sometable.x = upd.x
337-- WHERE sometable.x = upd.x
346-- |] [(1, \"hello\"),(2, \"world\")]
338-- |] [(1, \"hello\"),(2, \"world\")]
@@ -367,7 +359,6 @@ executeMany conn q qs = do
367returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO [r]
359returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO [r]
368returning = returningWith fromRow
360returning = returningWith fromRow
369
361
370−-- | A version of 'returning' taking parser as argument
371returningWith :: (ToRow q) => RowParser r -> Connection -> Query -> [q] -> IO [r]
362returningWith :: (ToRow q) => RowParser r -> Connection -> Query -> [q] -> IO [r]
372returningWith _ _ _ [] = return []
363returningWith _ _ _ [] = return []
373returningWith parser conn q qs = do
364returningWith parser conn q qs = do
@@ -533,7 +524,7 @@ foldWithOptions_ :: (FromRow r) =>
533 -> a -- ^ Initial state for result consumer.
524 -> a -- ^ Initial state for result consumer.
534 -> (a -> r -> IO a) -- ^ Result consumer.
525 -> (a -> r -> IO a) -- ^ Result consumer.
535 -> IO a
526 -> IO a
536−foldWithOptions_ opts conn query' a f = doFold opts fromRow conn query' query' a f
527+foldWithOptions_ opts conn query a f = doFold opts fromRow conn query query a f
537
528
538-- | A version of 'foldWithOptions_' taking a parser as an argument
529-- | A version of 'foldWithOptions_' taking a parser as an argument
539foldWithOptionsAndParser_ :: FoldOptions
530foldWithOptionsAndParser_ :: FoldOptions
@@ -543,7 +534,7 @@ foldWithOptionsAndParser_ :: FoldOptions
543 -> a -- ^ Initial state for result consumer.
534 -> a -- ^ Initial state for result consumer.
544 -> (a -> r -> IO a) -- ^ Result consumer.
535 -> (a -> r -> IO a) -- ^ Result consumer.
545 -> IO a
536 -> IO a
546−foldWithOptionsAndParser_ opts parser conn query' a f = doFold opts parser conn query' query' a f
537+foldWithOptionsAndParser_ opts parser conn query a f = doFold opts parser conn query query a f
547
538
548doFold :: FoldOptions
539doFold :: FoldOptions
549 -> RowParser row
540 -> RowParser row
@@ -571,17 +562,39 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
571 PQ.TransUnknown -> fail "foldWithOpts FIXME: PQ.TransUnknown"
562 PQ.TransUnknown -> fail "foldWithOpts FIXME: PQ.TransUnknown"
572 -- Not sure what this means.
563 -- Not sure what this means.
573 where
564 where
574− declare =
565+ declare = do
575− declareCursor conn q
566+ name <- newTempName conn
576− fetch cursor a =
567+ _ <- execute_ conn $ mconcat
577− foldForwardWithParser cursor parser chunkSize f a
568+ [ "DECLARE ", name, " NO SCROLL CURSOR FOR ", q ]
578−
569+ return name
570+ close name =
571+ (execute_ conn ("CLOSE " <> name) >> return ()) `E.catch` \ex ->
572+ -- Don't throw exception if CLOSE failed because the transaction is
573+ -- aborted. Otherwise, it will throw away the original error.
574+ unless (isFailedTransactionError ex) $ throwIO ex
575+
579− go = bracket declare closeCursor $ \cursor ->
576+ go = bracket declare close $ \(Query name) ->
580− let loop a = fetch cursor a >>=
577+ let q = toByteString (byteString "FETCH FORWARD "
578+ <> intDec chunkSize
579+ <> byteString " FROM "
580+ <> byteString name
581+ )
582+ loop a = do
583+ result <- exec conn q
584+ status <- PQ.resultStatus result
581− \r -> case r of
585+ case status of
582− Left x -> return x
586+ PQ.TuplesOk -> do
583− Right x -> loop x
587+ nrows <- PQ.ntuples result
588+ ncols <- PQ.nfields result
589+ if nrows > 0
590+ then do
591+ let inner a row = do
592+ x <- getRowWith parser row ncols conn result
593+ f a x
594+ foldM' inner a 0 (nrows - 1) >>= loop
595+ else return a
596+ _ -> throwResultError "fold" result status
584− in loop a0
597+ in loop a0
585
598
586-- FIXME: choose the Automatic chunkSize more intelligently
599-- FIXME: choose the Automatic chunkSize more intelligently
587-- One possibility is to use the type of the results, although this
600-- One possibility is to use the type of the results, although this
@@ -631,6 +644,76 @@ forEachWith_ :: RowParser r
631forEachWith_ parser conn template = foldWith_ parser conn template () . const
644forEachWith_ parser conn template = foldWith_ parser conn template () . const
632{-# INLINE forEachWith_ #-}
645{-# INLINE forEachWith_ #-}
633
646
647+forM' :: (Ord n, Num n) => n -> n -> (n -> IO a) -> IO [a]
648+forM' lo hi m = loop hi []
649+ where
650+ loop !n !as
651+ | n < lo = return as
652+ | otherwise = do
653+ a <- m n
654+ loop (n-1) (a:as)
655+{-# INLINE forM' #-}
656+
657+foldM' :: (Ord n, Num n) => (a -> n -> IO a) -> a -> n -> n -> IO a
658+foldM' f a lo hi = loop a lo
659+ where
660+ loop a !n
661+ | n > hi = return a
662+ | otherwise = do
663+ a' <- f a n
664+ loop a' (n+1)
665+{-# INLINE foldM' #-}
666+
667+finishQueryWith :: RowParser r -> Connection -> Query -> PQ.Result -> IO [r]
668+finishQueryWith parser conn q result = do
669+ status <- PQ.resultStatus result
670+ case status of
671+ PQ.EmptyQuery ->
672+ throwIO $ QueryError "query: Empty query" q
673+ PQ.CommandOk ->
674+ throwIO $ QueryError "query resulted in a command response" q
675+ PQ.TuplesOk -> do
676+ nrows <- PQ.ntuples result
677+ ncols <- PQ.nfields result
678+ forM' 0 (nrows-1) $ \row ->
679+ getRowWith parser row ncols conn result
680+ PQ.CopyOut ->
681+ throwIO $ QueryError "query: COPY TO is not supported" q
682+ PQ.CopyIn ->
683+ throwIO $ QueryError "query: COPY FROM is not supported" q
684+ PQ.BadResponse -> throwResultError "query" result status
685+ PQ.NonfatalError -> throwResultError "query" result status
686+ PQ.FatalError -> throwResultError "query" result status
687+
688+getRowWith :: RowParser r -> PQ.Row -> PQ.Column -> Connection -> PQ.Result -> IO r
689+getRowWith parser row ncols conn result = do
690+ let rw = Row row result
691+ let unCol (PQ.Col x) = fromIntegral x :: Int
692+ okvc <- runConversion (runStateT (runReaderT (unRP parser) rw) 0) conn
693+ case okvc of
694+ Ok (val,col) | col == ncols -> return val
695+ | otherwise -> do
696+ vals <- forM' 0 (ncols-1) $ \c -> do
697+ tinfo <- getTypeInfo conn =<< PQ.ftype result c
698+ v <- PQ.getvalue result row c
699+ return ( tinfo
700+ , fmap ellipsis v )
701+ throw (ConversionFailed
702+ (show (unCol ncols) ++ " values: " ++ show vals)
703+ Nothing
704+ ""
705+ (show (unCol col) ++ " slots in target type")
706+ "mismatch between number of columns to \
707+ \convert and number in target type")
708+ Errors [] -> throwIO $ ConversionFailed "" Nothing "" "" "unknown error"
709+ Errors [x] -> throwIO x
710+ Errors xs -> throwIO $ ManyErrors xs
711+
712+ellipsis :: ByteString -> ByteString
713+ellipsis bs
714+ | B.length bs > 15 = B.take 10 bs `B.append` "[...]"
715+ | otherwise = bs
716+
634
717
635-- $use
718-- $use
636--
719--
@@ -902,7 +985,7 @@ forEachWith_ parser conn template = foldWith_ parser conn template () . const
902-- all values of the given PostgreSQL type is considered \"compatible\".
985-- all values of the given PostgreSQL type is considered \"compatible\".
903-- For instance, you can always extract a PostgreSQL 16-bit @SMALLINT@
986-- For instance, you can always extract a PostgreSQL 16-bit @SMALLINT@
904-- column to a Haskell 'Int'. The Haskell 'Float' type can accurately
987-- column to a Haskell 'Int'. The Haskell 'Float' type can accurately
905−-- represent a @SMALLINT@, so it is considered compatible with those types.
988+-- represent a @SMALLINT@, so it is considered compatble with those types.
906--
989--
907-- * A numeric compatibility check is based only on the type of a
990-- * A numeric compatibility check is based only on the type of a
908-- column, /not/ on its values. For instance, a PostgreSQL 64-bit
991-- column, /not/ on its values. For instance, a PostgreSQL 64-bit
src/Database/PostgreSQL/Simple/Arrays.hs+2−2
@@ -42,9 +42,9 @@ array delim = char '{' *> option [] (arrays <|> strings) <* char '}'
42quoted :: Parser ByteString
42quoted :: Parser ByteString
43quoted = char '"' *> option "" contents <* char '"'
43quoted = char '"' *> option "" contents <* char '"'
44 where
44 where
45− esc' = char '\\' *> (char '\\' <|> char '"')
45+ esc = char '\\' *> (char '\\' <|> char '"')
46 unQ = takeWhile1 (notInClass "\"\\")
46 unQ = takeWhile1 (notInClass "\"\\")
47− contents = mconcat <$> many (unQ <|> B.singleton <$> esc')
47+ contents = mconcat <$> many (unQ <|> B.singleton <$> esc)
48
48
49-- | Recognizes a plain string literal, not containing quotes or brackets and
49-- | Recognizes a plain string literal, not containing quotes or brackets and
50-- not containing the delimiter character.
50-- not containing the delimiter character.
src/Database/PostgreSQL/Simple/Compat.hs+53
@@ -12,13 +12,36 @@ module Database.PostgreSQL.Simple.Compat
12 ) where
12 ) where
13
13
14import qualified Control.Exception as E
14import qualified Control.Exception as E
15+import Data.Monoid
15import Data.ByteString (ByteString)
16import Data.ByteString (ByteString)
17+#if MIN_VERSION_bytestring(0,10,0)
16import Data.ByteString.Lazy (toStrict)
18import Data.ByteString.Lazy (toStrict)
19+#else
20+import qualified Data.ByteString as B
21+import Data.ByteString.Lazy (toChunks)
22+#endif
17import Data.ByteString.Builder (Builder, toLazyByteString)
23import Data.ByteString.Builder (Builder, toLazyByteString)
24+
25+#if MIN_VERSION_scientific(0,3,0)
18import Data.Text.Lazy.Builder.Scientific (scientificBuilder)
26import Data.Text.Lazy.Builder.Scientific (scientificBuilder)
27+#else
28+import Data.Scientific (scientificBuilder)
29+#endif
30+
31+#if __GLASGOW_HASKELL__ >= 702
19import System.IO.Unsafe (unsafeDupablePerformIO)
32import System.IO.Unsafe (unsafeDupablePerformIO)
33+#elif __GLASGOW_HASKELL__ >= 611
34+import GHC.IO (unsafeDupablePerformIO)
35+#else
36+import GHC.IOBase (unsafeDupablePerformIO)
37+#endif
38+
20import Data.Fixed (Pico)
39import Data.Fixed (Pico)
40+#if MIN_VERSION_base(4,7,0)
21import Data.Fixed (Fixed(MkFixed))
41import Data.Fixed (Fixed(MkFixed))
42+#else
43+import Unsafe.Coerce (unsafeCoerce)
44+#endif
22
45
23-- | Like 'E.mask', but backported to base before version 4.3.0.
46-- | Like 'E.mask', but backported to base before version 4.3.0.
24--
47--
@@ -28,14 +51,44 @@ import Data.Fixed (Fixed(MkFixed))
28-- 'withTransactionMode' function calls the restore callback only once, so we
51-- 'withTransactionMode' function calls the restore callback only once, so we
29-- don't need that polymorphism.
52-- don't need that polymorphism.
30mask :: ((IO a -> IO a) -> IO b) -> IO b
53mask :: ((IO a -> IO a) -> IO b) -> IO b
54+#if MIN_VERSION_base(4,3,0)
31mask io = E.mask $ \restore -> io restore
55mask io = E.mask $ \restore -> io restore
56+#else
57+mask io = do
58+ b <- E.blocked
59+ E.block $ io $ \m -> if b then m else E.unblock m
60+#endif
32{-# INLINE mask #-}
61{-# INLINE mask #-}
33
62
63+#if !MIN_VERSION_base(4,5,0)
64+infixr 6 <>
65+
66+(<>) :: Monoid m => m -> m -> m
67+(<>) = mappend
68+{-# INLINE (<>) #-}
69+#endif
70+
34toByteString :: Builder -> ByteString
71toByteString :: Builder -> ByteString
72+#if MIN_VERSION_bytestring(0,10,0)
35toByteString x = toStrict (toLazyByteString x)
73toByteString x = toStrict (toLazyByteString x)
74+#else
75+toByteString x = B.concat (toChunks (toLazyByteString x))
76+#endif
77+
78+#if MIN_VERSION_base(4,7,0)
36
79
37toPico :: Integer -> Pico
80toPico :: Integer -> Pico
38toPico = MkFixed
81toPico = MkFixed
39
82
40fromPico :: Pico -> Integer
83fromPico :: Pico -> Integer
41fromPico (MkFixed i) = i
84fromPico (MkFixed i) = i
85+
86+#else
87+
88+toPico :: Integer -> Pico
89+toPico = unsafeCoerce
90+
91+fromPico :: Pico -> Integer
92+fromPico = unsafeCoerce
93+
94+#endif
src/Database/PostgreSQL/Simple/Copy.hs+5−33
@@ -9,7 +9,7 @@
9-- Stability: experimental
9-- Stability: experimental
10--
10--
11-- mid-level support for COPY IN and COPY OUT. See
11-- mid-level support for COPY IN and COPY OUT. See
12−-- <https://www.postgresql.org/docs/9.5/static/sql-copy.html> for
12+-- <http://www.postgresql.org/docs/9.2/static/sql-copy.html> for
13-- more information.
13-- more information.
14--
14--
15-- To use this binding, first call 'copy' with an appropriate
15-- To use this binding, first call 'copy' with an appropriate
@@ -32,7 +32,6 @@ module Database.PostgreSQL.Simple.Copy
32 ( copy
32 ( copy
33 , copy_
33 , copy_
34 , CopyOutResult(..)
34 , CopyOutResult(..)
35− , foldCopyData
36 , getCopyData
35 , getCopyData
37 , putCopyData
36 , putCopyData
38 , putCopyEnd
37 , putCopyEnd
@@ -49,13 +48,13 @@ import qualified Data.ByteString.Char8 as B
49import qualified Database.PostgreSQL.LibPQ as PQ
48import qualified Database.PostgreSQL.LibPQ as PQ
50import Database.PostgreSQL.Simple
49import Database.PostgreSQL.Simple
51import Database.PostgreSQL.Simple.Types
50import Database.PostgreSQL.Simple.Types
52−import Database.PostgreSQL.Simple.Internal hiding (result, row)
51+import Database.PostgreSQL.Simple.Internal
53
52
54
53
55-- | Issue a @COPY FROM STDIN@ or @COPY TO STDOUT@ query. In the former
54-- | Issue a @COPY FROM STDIN@ or @COPY TO STDOUT@ query. In the former
56-- case, the connection's state will change to @CopyIn@; in the latter,
55-- case, the connection's state will change to @CopyIn@; in the latter,
57-- @CopyOut@. The connection must be in the ready state in order
56-- @CopyOut@. The connection must be in the ready state in order
58−-- to call this function. Performs parameter substitution.
57+-- to call this function. Performs parameter subsitution.
59
58
60copy :: ( ToRow params ) => Connection -> Query -> params -> IO ()
59copy :: ( ToRow params ) => Connection -> Query -> params -> IO ()
61copy conn template qs = do
60copy conn template qs = do
@@ -76,18 +75,15 @@ doCopy :: B.ByteString -> Connection -> Query -> B.ByteString -> IO ()
76doCopy funcName conn template q = do
75doCopy funcName conn template q = do
77 result <- exec conn q
76 result <- exec conn q
78 status <- PQ.resultStatus result
77 status <- PQ.resultStatus result
79− let errMsg msg = throwIO $ QueryError
78+ let err = throwIO $ QueryError
80− (B.unpack funcName ++ " " ++ msg)
79+ (B.unpack funcName ++ " " ++ show status)
81 template
80 template
82− let err = errMsg $ show status
83 case status of
81 case status of
84 PQ.EmptyQuery -> err
82 PQ.EmptyQuery -> err
85 PQ.CommandOk -> err
83 PQ.CommandOk -> err
86 PQ.TuplesOk -> err
84 PQ.TuplesOk -> err
87 PQ.CopyOut -> return ()
85 PQ.CopyOut -> return ()
88 PQ.CopyIn -> return ()
86 PQ.CopyIn -> return ()
89− PQ.CopyBoth -> errMsg "COPY BOTH is not supported"
90− PQ.SingleTuple -> errMsg "single-row mode is not supported"
91 PQ.BadResponse -> throwResultError funcName result status
87 PQ.BadResponse -> throwResultError funcName result status
92 PQ.NonfatalError -> throwResultError funcName result status
88 PQ.NonfatalError -> throwResultError funcName result status
93 PQ.FatalError -> throwResultError funcName result status
89 PQ.FatalError -> throwResultError funcName result status
@@ -101,30 +97,6 @@ data CopyOutResult
101 deriving (Eq, Typeable, Show)
97 deriving (Eq, Typeable, Show)
102
98
103
99
104−-- | Fold over @COPY TO STDOUT@ query passing each copied row to an accumulator
105−-- and calling a post-process at the end. A connection must be in the
106−-- @CopyOut@ state in order to call this function.
107−--
108−-- __Example__
109−--
110−-- > (acc, count) <- foldCopyData conn
111−-- > (\acc row -> return (row:acc))
112−-- > (\acc count -> return (acc, count))
113−-- > []
114−
115−foldCopyData
116− :: Connection -- ^ Database connection
117− -> (a -> B.ByteString -> IO a) -- ^ Accumulate one row of the result
118− -> (a -> Int64 -> IO b) -- ^ Post-process accumulator with a count of rows
119− -> a -- ^ Initial accumulator
120− -> IO b -- ^ Result
121−foldCopyData conn f g !acc = do
122− result <- getCopyData conn
123− case result of
124− CopyOutRow row -> f acc row >>= foldCopyData conn f g
125− CopyOutDone count -> g acc count
126−
127−
128-- | Retrieve some data from a @COPY TO STDOUT@ query. A connection
100-- | Retrieve some data from a @COPY TO STDOUT@ query. A connection
129-- must be in the @CopyOut@ state in order to call this function. If this
101-- must be in the @CopyOut@ state in order to call this function. If this
130-- returns a 'CopyOutRow', the connection remains in the @CopyOut@ state,
102-- returns a 'CopyOutRow', the connection remains in the @CopyOut@ state,
src/Database/PostgreSQL/Simple/Cursor.hsdeleted−98
@@ -1,98 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−------------------------------------------------------------------------------
4−-- |
5−-- Module: Database.PostgreSQL.Simple.Cursor
6−-- Copyright: (c) 2011-2012 Leon P Smith
7−-- (c) 2017 Bardur Arantsson
8−-- License: BSD3
9−-- Maintainer: Leon P Smith <leon@melding-monads.com>
10−--
11−------------------------------------------------------------------------------
12−
13−module Database.PostgreSQL.Simple.Cursor
14− (
15− -- * Types
16− Cursor
17− -- * Cursor management
18− , declareCursor
19− , closeCursor
20− -- * Folding over rows from a cursor
21− , foldForward
22− , foldForwardWithParser
23− ) where
24−
25−import Data.ByteString.Builder (intDec)
26−import Control.Applicative ((<$>))
27−import Control.Exception as E
28−import Control.Monad (unless, void)
29−import Data.Monoid (mconcat)
30−import Database.PostgreSQL.Simple.Compat ((<>), toByteString)
31−import Database.PostgreSQL.Simple.FromRow (FromRow(..))
32−import Database.PostgreSQL.Simple.Types (Query(..))
33−import Database.PostgreSQL.Simple.Internal as Base hiding (result, row)
34−import Database.PostgreSQL.Simple.Internal.PQResultUtils
35−import Database.PostgreSQL.Simple.Transaction
36−import qualified Database.PostgreSQL.LibPQ as PQ
37−
38−-- | Cursor within a transaction.
39−data Cursor = Cursor !Query !Connection
40−
41−-- | Declare a temporary cursor. The cursor is given a
42−-- unique name for the given connection.
43−declareCursor :: Connection -> Query -> IO Cursor
44−declareCursor conn q = do
45− name <- newTempName conn
46− void $ execute_ conn $ mconcat ["DECLARE ", name, " NO SCROLL CURSOR FOR ", q]
47− return $ Cursor name conn
48−
49−-- | Close the given cursor.
50−closeCursor :: Cursor -> IO ()
51−closeCursor (Cursor name conn) =
52− (void $ execute_ conn ("CLOSE " <> name)) `E.catch` \ex ->
53− -- Don't throw exception if CLOSE failed because the transaction is
54− -- aborted. Otherwise, it will throw away the original error.
55− unless (isFailedTransactionError ex) $ throwIO ex
56−
57−-- | Fold over a chunk of rows from the given cursor, calling the
58−-- supplied fold-like function on each row as it is received. In case
59−-- the cursor is exhausted, a 'Left' value is returned, otherwise a
60−-- 'Right' value is returned.
61−foldForwardWithParser :: Cursor -> RowParser r -> Int -> (a -> r -> IO a) -> a -> IO (Either a a)
62−foldForwardWithParser (Cursor name conn) parser chunkSize f a0 = do
63− let q = "FETCH FORWARD "
64− <> (toByteString $ intDec chunkSize)
65− <> " FROM "
66− <> fromQuery name
67− result <- exec conn q
68− status <- PQ.resultStatus result
69− case status of
70− PQ.TuplesOk -> do
71− nrows <- PQ.ntuples result
72− ncols <- PQ.nfields result
73− if nrows > 0
74− then do
75− let inner a row = do
76− x <- getRowWith parser row ncols conn result
77− f a x
78− Right <$> foldM' inner a0 0 (nrows - 1)
79− else
80− return $ Left a0
81− _ -> throwResultError "foldForwardWithParser" result status
82−
83−-- | Fold over a chunk of rows, calling the supplied fold-like function
84−-- on each row as it is received. In case the cursor is exhausted,
85−-- a 'Left' value is returned, otherwise a 'Right' value is returned.
86−foldForward :: FromRow r => Cursor -> Int -> (a -> r -> IO a) -> a -> IO (Either a a)
87−foldForward cursor = foldForwardWithParser cursor fromRow
88−
89−
90−foldM' :: (Ord n, Num n) => (a -> n -> IO a) -> a -> n -> n -> IO a
91−foldM' f a lo hi = loop a lo
92− where
93− loop x !n
94− | n > hi = return x
95− | otherwise = do
96− x' <- f x n
97− loop x' (n+1)
98−{-# INLINE foldM' #-}
src/Database/PostgreSQL/Simple/Errors.hs+11−12
@@ -25,6 +25,7 @@ module Database.PostgreSQL.Simple.Errors
25 )
25 )
26 where
26 where
27
27
28+import Control.Applicative
28import Control.Exception as E
29import Control.Exception as E
29
30
30import Data.Attoparsec.ByteString.Char8
31import Data.Attoparsec.ByteString.Char8
@@ -59,18 +60,16 @@ data ConstraintViolation
59 deriving (Show, Eq, Ord, Typeable)
60 deriving (Show, Eq, Ord, Typeable)
60
61
61-- Default instance should be enough
62-- Default instance should be enough
62−instance Exception ConstraintViolation where
63+instance Exception ConstraintViolation
63− toException = postgresqlExceptionToException
64− fromException = postgresqlExceptionFromException
65
64
66
65
67-- | Tries to convert 'SqlError' to 'ConstrainViolation', checks sqlState and
66-- | Tries to convert 'SqlError' to 'ConstrainViolation', checks sqlState and
68−-- succeeds only if able to parse sqlErrorMsg.
67+-- succeedes only if able to parse sqlErrorMsg.
69--
68--
70−-- > createUser = handleJust constraintViolation handler $ execute conn ...
69+-- > createUser = catchJust constraintViolation catcher $ execute conn ...
71-- > where
70-- > where
72−-- > handler (UniqueViolation "user_login_key") = ...
71+-- > catcher UniqueViolation "user_login_key" = ...
73−-- > handler _ = ...
72+-- > catcher _ = ...
74constraintViolation :: SqlError -> Maybe ConstraintViolation
73constraintViolation :: SqlError -> Maybe ConstraintViolation
75constraintViolation e =
74constraintViolation e =
76 case sqlState e of
75 case sqlState e of
@@ -85,16 +84,16 @@ constraintViolation e =
85
84
86-- | Like constraintViolation, but also packs original SqlError.
85-- | Like constraintViolation, but also packs original SqlError.
87--
86--
88−-- > createUser = handleJust constraintViolationE handler $ execute conn ...
87+-- > createUser = catchJust constraintViolationE catcher $ execute conn ...
89-- > where
88-- > where
90−-- > handler (_, UniqueViolation "user_login_key") = ...
89+-- > catcher (_, UniqueViolation "user_login_key") = ...
91−-- > handler (e, _) = throwIO e
90+-- > catcher (e, _) = throwIO e
92--
91--
93constraintViolationE :: SqlError -> Maybe (SqlError, ConstraintViolation)
92constraintViolationE :: SqlError -> Maybe (SqlError, ConstraintViolation)
94constraintViolationE e = fmap ((,) e) $ constraintViolation e
93constraintViolationE e = fmap ((,) e) $ constraintViolation e
95
94
96-- | Catches SqlError, tries to convert to ConstraintViolation, re-throws
95-- | Catches SqlError, tries to convert to ConstraintViolation, re-throws
97−-- on fail. Provides alternative interface to 'E.handleJust'
96+-- on fail. Provides alternative interface to catchJust
98--
97--
99-- > createUser = catchViolation catcher $ execute conn ...
98-- > createUser = catchViolation catcher $ execute conn ...
100-- > where
99-- > where
@@ -125,7 +124,7 @@ parseMaybe p b = either (const Nothing) Just $ parseOnly p b
125------------------------------------------------------------------------
124------------------------------------------------------------------------
126-- Error predicates
125-- Error predicates
127--
126--
128−-- https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
127+-- http://www.postgresql.org/docs/current/static/errcodes-appendix.html
129
128
130isSerializationError :: SqlError -> Bool
129isSerializationError :: SqlError -> Bool
131isSerializationError = isSqlState "40001"
130isSerializationError = isSqlState "40001"
src/Database/PostgreSQL/Simple/FromField.hs+73−127
@@ -1,8 +1,7 @@
1{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor #-}
1{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor #-}
2{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
2{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
3{-# LANGUAGE PatternGuards, ScopedTypeVariables #-}
3{-# LANGUAGE PatternGuards, ScopedTypeVariables #-}
4−{-# LANGUAGE RecordWildCards #-}
4+{-# LANGUAGE RecordWildCards, TemplateHaskell #-}
5−{-# LANGUAGE PolyKinds #-}
6
5
7{- |
6{- |
8Module: Database.PostgreSQL.Simple.FromField
7Module: Database.PostgreSQL.Simple.FromField
@@ -107,27 +106,25 @@ module Database.PostgreSQL.Simple.FromField
107 , PQ.Oid(..)
106 , PQ.Oid(..)
108 , PQ.Format(..)
107 , PQ.Format(..)
109 , pgArrayFieldParser
108 , pgArrayFieldParser
110− , attoFieldParser
111
109
112 , optionalField
110 , optionalField
113 , fromJSONField
111 , fromJSONField
114− , fromFieldJSONByteString
115 ) where
112 ) where
116
113
117#include "MachDeps.h"
114#include "MachDeps.h"
118
115
119−import Control.Applicative ( Const(Const), (<|>), (<$>), pure, (*>), (<*) )
116+import Control.Applicative ( (<|>), (<$>), pure, (*>), (<*) )
120import Control.Concurrent.MVar (MVar, newMVar)
117import Control.Concurrent.MVar (MVar, newMVar)
121−import Control.Exception (Exception (toException, fromException))
118+import Control.Exception (Exception)
122import qualified Data.Aeson as JSON
119import qualified Data.Aeson as JSON
120+import qualified Data.Aeson.Parser as JSON (value')
123import Data.Attoparsec.ByteString.Char8 hiding (Result)
121import Data.Attoparsec.ByteString.Char8 hiding (Result)
124import Data.ByteString (ByteString)
122import Data.ByteString (ByteString)
125import qualified Data.ByteString.Char8 as B
123import qualified Data.ByteString.Char8 as B
126−import Data.Functor.Identity (Identity(Identity))
127import Data.Int (Int16, Int32, Int64)
124import Data.Int (Int16, Int32, Int64)
128import Data.IORef (IORef, newIORef)
125import Data.IORef (IORef, newIORef)
129import Data.Ratio (Ratio)
126import Data.Ratio (Ratio)
130−import Data.Time.Compat ( UTCTime, ZonedTime, LocalTime, Day, TimeOfDay, CalendarDiffTime )
127+import Data.Time ( UTCTime, ZonedTime, LocalTime, Day, TimeOfDay )
131import Data.Typeable (Typeable, typeOf)
128import Data.Typeable (Typeable, typeOf)
132import Data.Vector (Vector)
129import Data.Vector (Vector)
133import Data.Vector.Mutable (IOVector)
130import Data.Vector.Mutable (IOVector)
@@ -138,6 +135,7 @@ import Database.PostgreSQL.Simple.Ok
138import Database.PostgreSQL.Simple.Types
135import Database.PostgreSQL.Simple.Types
139import Database.PostgreSQL.Simple.TypeInfo as TI
136import Database.PostgreSQL.Simple.TypeInfo as TI
140import qualified Database.PostgreSQL.Simple.TypeInfo.Static as TI
137import qualified Database.PostgreSQL.Simple.TypeInfo.Static as TI
138+import Database.PostgreSQL.Simple.TypeInfo.Macro as TI
141import Database.PostgreSQL.Simple.Time
139import Database.PostgreSQL.Simple.Time
142import Database.PostgreSQL.Simple.Arrays as Arrays
140import Database.PostgreSQL.Simple.Arrays as Arrays
143import qualified Database.PostgreSQL.LibPQ as PQ
141import qualified Database.PostgreSQL.LibPQ as PQ
@@ -154,8 +152,6 @@ import qualified Data.UUID.Types as UUID
154import Data.Scientific (Scientific)
152import Data.Scientific (Scientific)
155import GHC.Real (infinity, notANumber)
153import GHC.Real (infinity, notANumber)
156
154
157−import qualified Data.Aeson.Types as JSON
158−
159-- | Exception thrown if conversion from a SQL value to a Haskell
155-- | Exception thrown if conversion from a SQL value to a Haskell
160-- value fails.
156-- value fails.
161data ResultError = Incompatible { errSQLType :: String
157data ResultError = Incompatible { errSQLType :: String
@@ -182,9 +178,7 @@ data ResultError = Incompatible { errSQLType :: String
182 -- between metadata and actual data in a row).
178 -- between metadata and actual data in a row).
183 deriving (Eq, Show, Typeable)
179 deriving (Eq, Show, Typeable)
184
180
185−instance Exception ResultError where
181+instance Exception ResultError
186− toException = postgresqlExceptionToException
187− fromException = postgresqlExceptionFromException
188
182
189left :: Exception a => a -> Conversion b
183left :: Exception a => a -> Conversion b
190left = conversionError
184left = conversionError
@@ -250,11 +244,9 @@ tableOid Field{..} = toMaybeOid (unsafeDupablePerformIO (PQ.ftable result column
250 then Nothing
244 then Nothing
251 else Just x
245 else Just x
252
246
253−-- | If the column has a table associated with it, this returns the
247+-- | If the column has a table associated with it, this returns the number
254−-- number of the associated table column. Table columns have
248+-- off the associated table column. Numbering starts from 0. Analogous
255−-- nonzero numbers. Zero is returned if the specified column is not
256−-- a simple reference to a table column, or when using pre-3.0
257−-- protocol. Analogous to libpq's @PQftablecol@.
249+-- to libpq's @PQftablecol@.
258
250
259tableColumn :: Field -> Int
251tableColumn :: Field -> Int
260tableColumn Field{..} = fromCol (unsafeDupablePerformIO (PQ.ftablecol result column))
252tableColumn Field{..} = fromCol (unsafeDupablePerformIO (PQ.ftablecol result column))
@@ -270,15 +262,9 @@ format Field{..} = unsafeDupablePerformIO (PQ.fformat result column)
270-- | void
262-- | void
271instance FromField () where
263instance FromField () where
272 fromField f _bs
264 fromField f _bs
273− | typeOid f /= TI.voidOid = returnError Incompatible f ""
265+ | typeOid f /= $(inlineTypoid TI.void) = returnError Incompatible f ""
274 | otherwise = pure ()
266 | otherwise = pure ()
275
267
276−instance (FromField a) => FromField (Const a b) where
277− fromField f bs = Const <$> fromField f bs
278−
279−instance (FromField a) => FromField (Identity a) where
280− fromField f bs = Identity <$> fromField f bs
281−
282-- | For dealing with null values. Compatible with any postgresql type
268-- | For dealing with null values. Compatible with any postgresql type
283-- compatible with type @a@. Note that the type is not checked if
269-- compatible with type @a@. Note that the type is not checked if
284-- the value is null, although it is inadvisable to rely on this
270-- the value is null, although it is inadvisable to rely on this
@@ -306,30 +292,30 @@ instance FromField Null where
306-- | bool
292-- | bool
307instance FromField Bool where
293instance FromField Bool where
308 fromField f bs
294 fromField f bs
309− | typeOid f /= TI.boolOid = returnError Incompatible f ""
295+ | typeOid f /= $(inlineTypoid TI.bool) = returnError Incompatible f ""
310 | bs == Nothing = returnError UnexpectedNull f ""
296 | bs == Nothing = returnError UnexpectedNull f ""
311 | bs == Just "t" = pure True
297 | bs == Just "t" = pure True
312 | bs == Just "f" = pure False
298 | bs == Just "f" = pure False
313 | otherwise = returnError ConversionFailed f ""
299 | otherwise = returnError ConversionFailed f ""
314
300
315−-- | \"char\", bpchar
301+-- | \"char\"
316instance FromField Char where
302instance FromField Char where
317− fromField f bs0 =
303+ fromField f bs =
318− if (eq TI.charOid \/ eq TI.bpcharOid) (typeOid f)
304+ if typeOid f /= $(inlineTypoid TI.char)
305+ then returnError Incompatible f ""
319− then case bs0 of
306+ else case bs of
320 Nothing -> returnError UnexpectedNull f ""
307 Nothing -> returnError UnexpectedNull f ""
321 Just bs -> if B.length bs /= 1
308 Just bs -> if B.length bs /= 1
322 then returnError ConversionFailed f "length not 1"
309 then returnError ConversionFailed f "length not 1"
323 else return $! (B.head bs)
310 else return $! (B.head bs)
324− else returnError Incompatible f ""
325
311
326-- | int2
312-- | int2
327instance FromField Int16 where
313instance FromField Int16 where
328− fromField = attoFieldParser ok16 $ signed decimal
314+ fromField = atto ok16 $ signed decimal
329
315
330-- | int2, int4
316-- | int2, int4
331instance FromField Int32 where
317instance FromField Int32 where
332− fromField = attoFieldParser ok32 $ signed decimal
318+ fromField = atto ok32 $ signed decimal
333
319
334#if WORD_SIZE_IN_BITS < 64
320#if WORD_SIZE_IN_BITS < 64
335-- | int2, int4, and if compiled as 64-bit code, int8 as well.
321-- | int2, int4, and if compiled as 64-bit code, int8 as well.
@@ -339,37 +325,37 @@ instance FromField Int32 where
339-- This library was compiled as 64-bit code.
325-- This library was compiled as 64-bit code.
340#endif
326#endif
341instance FromField Int where
327instance FromField Int where
342− fromField = attoFieldParser okInt $ signed decimal
328+ fromField = atto okInt $ signed decimal
343
329
344-- | int2, int4, int8
330-- | int2, int4, int8
345instance FromField Int64 where
331instance FromField Int64 where
346− fromField = attoFieldParser ok64 $ signed decimal
332+ fromField = atto ok64 $ signed decimal
347
333
348-- | int2, int4, int8
334-- | int2, int4, int8
349instance FromField Integer where
335instance FromField Integer where
350− fromField = attoFieldParser ok64 $ signed decimal
336+ fromField = atto ok64 $ signed decimal
351
337
352-- | int2, float4 (Uses attoparsec's 'double' routine, for
338-- | int2, float4 (Uses attoparsec's 'double' routine, for
353-- better accuracy convert to 'Scientific' or 'Rational' first)
339-- better accuracy convert to 'Scientific' or 'Rational' first)
354instance FromField Float where
340instance FromField Float where
355− fromField = attoFieldParser ok (realToFrac <$> pg_double)
341+ fromField = atto ok (realToFrac <$> pg_double)
356− where ok = eq TI.float4Oid \/ eq TI.int2Oid
342+ where ok = $(mkCompats [TI.float4,TI.int2])
357
343
358-- | int2, int4, float4, float8 (Uses attoparsec's 'double' routine, for
344-- | int2, int4, float4, float8 (Uses attoparsec's 'double' routine, for
359-- better accuracy convert to 'Scientific' or 'Rational' first)
345-- better accuracy convert to 'Scientific' or 'Rational' first)
360instance FromField Double where
346instance FromField Double where
361− fromField = attoFieldParser ok pg_double
347+ fromField = atto ok pg_double
362− where ok = eq TI.float4Oid \/ eq TI.float8Oid \/ eq TI.int2Oid \/ eq TI.int4Oid
348+ where ok = $(mkCompats [TI.float4,TI.float8,TI.int2,TI.int4])
363
349
364-- | int2, int4, int8, float4, float8, numeric
350-- | int2, int4, int8, float4, float8, numeric
365instance FromField (Ratio Integer) where
351instance FromField (Ratio Integer) where
366− fromField = attoFieldParser ok pg_rational
352+ fromField = atto ok pg_rational
367− where ok = eq TI.float4Oid \/ eq TI.float8Oid \/ eq TI.int2Oid \/ eq TI.int4Oid \/ eq TI.int8Oid \/ eq TI.numericOid
353+ where ok = $(mkCompats [TI.float4,TI.float8,TI.int2,TI.int4,TI.int8,TI.numeric])
368
354
369-- | int2, int4, int8, float4, float8, numeric
355-- | int2, int4, int8, float4, float8, numeric
370instance FromField Scientific where
356instance FromField Scientific where
371− fromField = attoFieldParser ok rational
357+ fromField = atto ok rational
372− where ok = eq TI.float4Oid \/ eq TI.float8Oid \/ eq TI.int2Oid \/ eq TI.int4Oid \/ eq TI.int8Oid \/ eq TI.numericOid
358+ where ok = $(mkCompats [TI.float4,TI.float8,TI.int2,TI.int4,TI.int8,TI.numeric])
373
359
374unBinary :: Binary t -> t
360unBinary :: Binary t -> t
375unBinary (Binary x) = x
361unBinary (Binary x) = x
@@ -390,13 +376,13 @@ pg_rational
390
376
391-- | bytea, name, text, \"char\", bpchar, varchar, unknown
377-- | bytea, name, text, \"char\", bpchar, varchar, unknown
392instance FromField SB.ByteString where
378instance FromField SB.ByteString where
393− fromField f dat = if typeOid f == TI.byteaOid
379+ fromField f dat = if typeOid f == $(inlineTypoid TI.bytea)
394 then unBinary <$> fromField f dat
380 then unBinary <$> fromField f dat
395 else doFromField f okText' pure dat
381 else doFromField f okText' pure dat
396
382
397-- | oid
383-- | oid
398instance FromField PQ.Oid where
384instance FromField PQ.Oid where
399− fromField f dat = PQ.Oid <$> attoFieldParser (== TI.oidOid) decimal f dat
385+ fromField f dat = PQ.Oid <$> atto (== $(inlineTypoid TI.oid)) decimal f dat
400
386
401-- | bytea, name, text, \"char\", bpchar, varchar, unknown
387-- | bytea, name, text, \"char\", bpchar, varchar, unknown
402instance FromField LB.ByteString where
388instance FromField LB.ByteString where
@@ -404,7 +390,7 @@ instance FromField LB.ByteString where
404
390
405unescapeBytea :: Field -> SB.ByteString
391unescapeBytea :: Field -> SB.ByteString
406 -> Conversion (Binary SB.ByteString)
392 -> Conversion (Binary SB.ByteString)
407−unescapeBytea f str' = case unsafeDupablePerformIO (PQ.unescapeBytea str') of
393+unescapeBytea f str = case unsafeDupablePerformIO (PQ.unescapeBytea str) of
408 Nothing -> returnError ConversionFailed f "unescapeBytea failed"
394 Nothing -> returnError ConversionFailed f "unescapeBytea failed"
409 Just str -> pure (Binary str)
395 Just str -> pure (Binary str)
410
396
@@ -455,57 +441,48 @@ instance FromField [Char] where
455
441
456-- | timestamptz
442-- | timestamptz
457instance FromField UTCTime where
443instance FromField UTCTime where
458− fromField = ff TI.timestamptzOid "UTCTime" parseUTCTime
444+ fromField = ff $(inlineTypoid TI.timestamptz) "UTCTime" parseUTCTime
459
445
460-- | timestamptz
446-- | timestamptz
461instance FromField ZonedTime where
447instance FromField ZonedTime where
462− fromField = ff TI.timestamptzOid "ZonedTime" parseZonedTime
448+ fromField = ff $(inlineTypoid TI.timestamptz) "ZonedTime" parseZonedTime
463
449
464-- | timestamp
450-- | timestamp
465instance FromField LocalTime where
451instance FromField LocalTime where
466− fromField = ff TI.timestampOid "LocalTime" parseLocalTime
452+ fromField = ff $(inlineTypoid TI.timestamp) "LocalTime" parseLocalTime
467
453
468-- | date
454-- | date
469instance FromField Day where
455instance FromField Day where
470− fromField = ff TI.dateOid "Day" parseDay
456+ fromField = ff $(inlineTypoid TI.date) "Day" parseDay
471
457
472-- | time
458-- | time
473instance FromField TimeOfDay where
459instance FromField TimeOfDay where
474− fromField = ff TI.timeOid "TimeOfDay" parseTimeOfDay
460+ fromField = ff $(inlineTypoid TI.time) "TimeOfDay" parseTimeOfDay
475
461
476-- | timestamptz
462-- | timestamptz
477instance FromField UTCTimestamp where
463instance FromField UTCTimestamp where
478− fromField = ff TI.timestamptzOid "UTCTimestamp" parseUTCTimestamp
464+ fromField = ff $(inlineTypoid TI.timestamptz) "UTCTimestamp" parseUTCTimestamp
479
465
480-- | timestamptz
466-- | timestamptz
481instance FromField ZonedTimestamp where
467instance FromField ZonedTimestamp where
482− fromField = ff TI.timestamptzOid "ZonedTimestamp" parseZonedTimestamp
468+ fromField = ff $(inlineTypoid TI.timestamptz) "ZonedTimestamp" parseZonedTimestamp
483
469
484-- | timestamp
470-- | timestamp
485instance FromField LocalTimestamp where
471instance FromField LocalTimestamp where
486− fromField = ff TI.timestampOid "LocalTimestamp" parseLocalTimestamp
472+ fromField = ff $(inlineTypoid TI.timestamp) "LocalTimestamp" parseLocalTimestamp
487
473
488-- | date
474-- | date
489instance FromField Date where
475instance FromField Date where
490− fromField = ff TI.dateOid "Date" parseDate
476+ fromField = ff $(inlineTypoid TI.date) "Date" parseDate
491−
492−-- | interval. Requires you to configure intervalstyle as @iso_8601@.
493−--
494−-- You can configure intervalstyle on every connection with a @SET@ command,
495−-- but for better performance you may want to configure it permanently in the
496−-- file found with @SHOW config_file;@ .
497−--
498−instance FromField CalendarDiffTime where
499− fromField = ff TI.intervalOid "CalendarDiffTime" parseCalendarDiffTime
500
477
501ff :: PQ.Oid -> String -> (B8.ByteString -> Either String a)
478ff :: PQ.Oid -> String -> (B8.ByteString -> Either String a)
502 -> Field -> Maybe B8.ByteString -> Conversion a
479 -> Field -> Maybe B8.ByteString -> Conversion a
503−ff compatOid hsType parseBS f mstr =
480+ff compatOid hsType parse f mstr =
504 if typeOid f /= compatOid
481 if typeOid f /= compatOid
505 then err Incompatible ""
482 then err Incompatible ""
506 else case mstr of
483 else case mstr of
507 Nothing -> err UnexpectedNull ""
484 Nothing -> err UnexpectedNull ""
508− Just str -> case parseBS str of
485+ Just str -> case parse str of
509 Left msg -> err ConversionFailed msg
486 Left msg -> err ConversionFailed msg
510 Right val -> return val
487 Right val -> return val
511 where
488 where
@@ -543,13 +520,13 @@ pgArrayFieldParser fieldParser f mdat = do
543 _ -> returnError Incompatible f ""
520 _ -> returnError Incompatible f ""
544
521
545fromArray :: FieldParser a -> TypeInfo -> Field -> Parser (Conversion [a])
522fromArray :: FieldParser a -> TypeInfo -> Field -> Parser (Conversion [a])
546−fromArray fieldParser typInfo f = sequence . (parseIt <$>) <$> array delim
523+fromArray fieldParser typeInfo f = sequence . (parseIt <$>) <$> array delim
547 where
524 where
548− delim = typdelim (typelem typInfo)
525+ delim = typdelim (typelem typeInfo)
549− fElem = f{ typeOid = typoid (typelem typInfo) }
526+ fElem = f{ typeOid = typoid (typelem typeInfo) }
550
527
551 parseIt item =
528 parseIt item =
552− fieldParser f' $ if item == Arrays.Plain "NULL" then Nothing else Just item'
529+ fieldParser f' $ if item' == "NULL" then Nothing else Just item'
553 where
530 where
554 item' = fmt delim item
531 item' = fmt delim item
555 f' | Arrays.Array _ <- item = f
532 f' | Arrays.Array _ <- item = f
@@ -564,7 +541,7 @@ instance (FromField a, Typeable a) => FromField (IOVector a) where
564-- | uuid
541-- | uuid
565instance FromField UUID where
542instance FromField UUID where
566 fromField f mbs =
543 fromField f mbs =
567− if typeOid f /= TI.uuidOid
544+ if typeOid f /= $(inlineTypoid TI.uuid)
568 then returnError Incompatible f ""
545 then returnError Incompatible f ""
569 else case mbs of
546 else case mbs of
570 Nothing -> returnError UnexpectedNull f ""
547 Nothing -> returnError UnexpectedNull f ""
@@ -573,26 +550,20 @@ instance FromField UUID where
573 Nothing -> returnError ConversionFailed f "Invalid UUID"
550 Nothing -> returnError ConversionFailed f "Invalid UUID"
574 Just uuid -> pure uuid
551 Just uuid -> pure uuid
575
552
576−-- | json, jsonb
553+-- | json
577instance FromField JSON.Value where
554instance FromField JSON.Value where
578− fromField f mbs = parseBS =<< fromFieldJSONByteString f mbs
555+ fromField f mbs =
579− where parseBS bs = case JSON.eitherDecodeStrict' bs of
580− Left err -> returnError ConversionFailed f err
581− Right val -> pure val
582−
583−-- | Return the JSON ByteString directly
584−--
585−-- @since 0.6.3
586−fromFieldJSONByteString :: Field -> Maybe ByteString -> Conversion ByteString
587−fromFieldJSONByteString f mbs =
588− if typeOid f /= TI.jsonOid && typeOid f /= TI.jsonbOid
556+ if typeOid f /= $(inlineTypoid TI.json) && typeOid f /= $(inlineTypoid TI.jsonb)
589 then returnError Incompatible f ""
557 then returnError Incompatible f ""
590 else case mbs of
558 else case mbs of
591 Nothing -> returnError UnexpectedNull f ""
559 Nothing -> returnError UnexpectedNull f ""
592− Just bs -> pure bs
560+ Just bs ->
561+ case parseOnly (JSON.value' <* endOfInput) bs of
562+ Left err -> returnError ConversionFailed f err
563+ Right val -> pure val
593
564
594-- | Parse a field to a JSON 'JSON.Value' and convert that into a
565-- | Parse a field to a JSON 'JSON.Value' and convert that into a
595−-- Haskell value using the 'JSON.FromJSON' instance.
566+-- Haskell value using 'JSON.fromJSON'.
596--
567--
597-- This can be used as the default implementation for the 'fromField'
568-- This can be used as the default implementation for the 'fromField'
598-- method for Haskell types that have a JSON representation in
569-- method for Haskell types that have a JSON representation in
@@ -613,10 +584,10 @@ fromFieldJSONByteString f mbs =
613fromJSONField :: (JSON.FromJSON a, Typeable a) => FieldParser a
584fromJSONField :: (JSON.FromJSON a, Typeable a) => FieldParser a
614fromJSONField f mbBs = do
585fromJSONField f mbBs = do
615 value <- fromField f mbBs
586 value <- fromField f mbBs
616− case JSON.ifromJSON value of
587+ case JSON.fromJSON value of
617− JSON.IError path err -> returnError ConversionFailed f $
588+ JSON.Error err -> returnError ConversionFailed f $
618− "JSON decoding error: " ++ (JSON.formatError path err)
589+ "JSON decoding error: " ++ err
619− JSON.ISuccess x -> pure x
590+ JSON.Success x -> pure x
620
591
621-- | Compatible with the same set of types as @a@. Note that
592-- | Compatible with the same set of types as @a@. Note that
622-- modifying the 'IORef' does not have any effects outside
593-- modifying the 'IORef' does not have any effects outside
@@ -633,33 +604,20 @@ instance FromField a => FromField (MVar a) where
633type Compat = PQ.Oid -> Bool
604type Compat = PQ.Oid -> Bool
634
605
635okText, okText', okBinary, ok16, ok32, ok64, okInt :: Compat
606okText, okText', okBinary, ok16, ok32, ok64, okInt :: Compat
636−okText = eq TI.nameOid \/ eq TI.textOid \/ eq TI.charOid
607+okText = $( mkCompats [ TI.name, TI.text, TI.char,
637− \/ eq TI.bpcharOid \/ eq TI.varcharOid
608+ TI.bpchar, TI.varchar ] )
638−okText' = eq TI.nameOid \/ eq TI.textOid \/ eq TI.charOid
609+okText' = $( mkCompats [ TI.name, TI.text, TI.char,
639− \/ eq TI.bpcharOid \/ eq TI.varcharOid \/ eq TI.unknownOid
610+ TI.bpchar, TI.varchar, TI.unknown ] )
640−okBinary = eq TI.byteaOid
611+okBinary = (== $( inlineTypoid TI.bytea ))
641−ok16 = eq TI.int2Oid
612+ok16 = (== $( inlineTypoid TI.int2 ))
642−ok32 = eq TI.int2Oid \/ eq TI.int4Oid
613+ok32 = $( mkCompats [TI.int2,TI.int4] )
643−ok64 = eq TI.int2Oid \/ eq TI.int4Oid \/ eq TI.int8Oid
614+ok64 = $( mkCompats [TI.int2,TI.int4,TI.int8] )
644#if WORD_SIZE_IN_BITS < 64
615#if WORD_SIZE_IN_BITS < 64
645okInt = ok32
616okInt = ok32
646#else
617#else
647okInt = ok64
618okInt = ok64
648#endif
619#endif
649
620
650−-- | eq and \/ are used to imlement what Macro stuff did,
651−-- i.e. mkCompats and inlineTypoid
652−eq :: PQ.Oid -> PQ.Oid -> Bool
653−eq = (==)
654−{-# INLINE eq #-}
655−
656−infixr 2 \/
657−(\/) :: (PQ.Oid -> Bool)
658− -> (PQ.Oid -> Bool)
659− -> (PQ.Oid -> Bool)
660−f \/ g = \x -> f x || g x
661−{-# INLINE (\/) #-}
662−
663doFromField :: forall a . (Typeable a)
621doFromField :: forall a . (Typeable a)
664 => Field -> Compat -> (ByteString -> Conversion a)
622 => Field -> Compat -> (ByteString -> Conversion a)
665 -> Maybe ByteString -> Conversion a
623 -> Maybe ByteString -> Conversion a
@@ -684,22 +642,10 @@ returnError mkErr f msg = do
684 (show (typeOf (undefined :: a)))
642 (show (typeOf (undefined :: a)))
685 msg
643 msg
686
644
687−-- | Construct a field parser from an attoparsec parser. An 'Incompatible' error is thrown if the
688−-- PostgreSQL oid does not match the specified predicate.
689−--
690−-- @
691−-- instance FromField Int16 where
692−-- fromField = attoFieldParser ok16 (signed decimal)
693−-- @
694−--
695−-- @since 0.6.3
696−attoFieldParser :: forall a. (Typeable a)
645+atto :: forall a. (Typeable a)
697− => (PQ.Oid -> Bool)
646+ => Compat -> Parser a -> Field -> Maybe ByteString
698− -- ^ Predicate for whether the postgresql type oid is compatible with this parser
647+ -> Conversion a
699− -> Parser a
700− -- ^ An attoparsec parser.
701− -> FieldParser a
702−attoFieldParser types p0 f dat = doFromField f types (go p0) dat
648+atto types p0 f dat = doFromField f types (go p0) dat
703 where
649 where
704 go :: Parser a -> ByteString -> Conversion a
650 go :: Parser a -> ByteString -> Conversion a
705 go p s =
651 go p s =
src/Database/PostgreSQL/Simple/FromRow.hs+2−209
@@ -67,23 +67,6 @@ import GHC.Generics
67-- in a single row of the query result. Otherwise, a 'ConversionFailed'
67-- in a single row of the query result. Otherwise, a 'ConversionFailed'
68-- exception will be thrown.
68-- exception will be thrown.
69--
69--
70−-- You can also derive 'FromRow' for your data type using GHC generics, like
71−-- this:
72−--
73−-- @
74−-- \{-# LANGUAGE DeriveAnyClass \#-}
75−-- \{-# LANGUAGE DeriveGeneric \#-}
76−--
77−-- import "GHC.Generics" ('GHC.Generics.Generic')
78−-- import "Database.PostgreSQL.Simple" ('FromRow')
79−--
80−-- data User = User { name :: String, fileQuota :: Int }
81−-- deriving ('GHC.Generics.Generic', 'FromRow')
82−-- @
83−--
84−-- Note that this only works for product types (e.g. records) and does not
85−-- support sum types or recursive types.
86−--
87-- Note that 'field' evaluates its result to WHNF, so the caveats listed in
70-- Note that 'field' evaluates its result to WHNF, so the caveats listed in
88-- mysql-simple and very early versions of postgresql-simple no longer apply.
71-- mysql-simple and very early versions of postgresql-simple no longer apply.
89-- Instead, look at the caveats associated with user-defined implementations
72-- Instead, look at the caveats associated with user-defined implementations
@@ -131,8 +114,8 @@ fieldWith fieldP = RP $ do
131 else do
114 else do
132 let !result = rowresult
115 let !result = rowresult
133 !typeOid = unsafeDupablePerformIO (PQ.ftype result column)
116 !typeOid = unsafeDupablePerformIO (PQ.ftype result column)
134− !field' = Field{..}
117+ !field = Field{..}
135− lift (lift (fieldP field' (getvalue result row column)))
118+ lift (lift (fieldP field (getvalue result row column)))
136
119
137field :: FromField a => RowParser a
120field :: FromField a => RowParser a
138field = fieldWith fromField
121field = fieldWith fromField
@@ -255,196 +238,6 @@ instance (FromField a, FromField b, FromField c, FromField d, FromField e,
255 null *> null *> null *> null *> null *> pure Nothing)
238 null *> null *> null *> null *> null *> pure Nothing)
256 <|> (Just <$> fromRow)
239 <|> (Just <$> fromRow)
257
240
258−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
259− FromField f, FromField g, FromField h, FromField i, FromField j,
260− FromField k) =>
261− FromRow (a,b,c,d,e,f,g,h,i,j,k) where
262− fromRow = (,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
263− <*> field <*> field <*> field <*> field <*> field
264− <*> field
265−
266−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
267− FromField f, FromField g, FromField h, FromField i, FromField j,
268− FromField k) =>
269− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k)) where
270− fromRow = (null *> null *> null *> null *> null *>
271− null *> null *> null *> null *> null *>
272− null *> pure Nothing)
273− <|> (Just <$> fromRow)
274−
275−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
276− FromField f, FromField g, FromField h, FromField i, FromField j,
277− FromField k, FromField l) =>
278− FromRow (a,b,c,d,e,f,g,h,i,j,k,l) where
279− fromRow = (,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
280− <*> field <*> field <*> field <*> field <*> field
281− <*> field <*> field
282−
283−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
284− FromField f, FromField g, FromField h, FromField i, FromField j,
285− FromField k, FromField l) =>
286− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l)) where
287− fromRow = (null *> null *> null *> null *> null *>
288− null *> null *> null *> null *> null *>
289− null *> null *> pure Nothing)
290− <|> (Just <$> fromRow)
291−
292−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
293− FromField f, FromField g, FromField h, FromField i, FromField j,
294− FromField k, FromField l, FromField m) =>
295− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m) where
296− fromRow = (,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
297− <*> field <*> field <*> field <*> field <*> field
298− <*> field <*> field <*> field
299−
300−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
301− FromField f, FromField g, FromField h, FromField i, FromField j,
302− FromField k, FromField l, FromField m) =>
303− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m)) where
304− fromRow = (null *> null *> null *> null *> null *>
305− null *> null *> null *> null *> null *>
306− null *> null *> null *> pure Nothing)
307− <|> (Just <$> fromRow)
308−
309−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
310− FromField f, FromField g, FromField h, FromField i, FromField j,
311− FromField k, FromField l, FromField m, FromField n) =>
312− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where
313− fromRow = (,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
314− <*> field <*> field <*> field <*> field <*> field
315− <*> field <*> field <*> field <*> field
316−
317−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
318− FromField f, FromField g, FromField h, FromField i, FromField j,
319− FromField k, FromField l, FromField m, FromField n) =>
320− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n)) where
321− fromRow = (null *> null *> null *> null *> null *>
322− null *> null *> null *> null *> null *>
323− null *> null *> null *> null *> pure Nothing)
324− <|> (Just <$> fromRow)
325−
326−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
327− FromField f, FromField g, FromField h, FromField i, FromField j,
328− FromField k, FromField l, FromField m, FromField n, FromField o) =>
329− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where
330− fromRow = (,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
331− <*> field <*> field <*> field <*> field <*> field
332− <*> field <*> field <*> field <*> field <*> field
333−
334−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
335− FromField f, FromField g, FromField h, FromField i, FromField j,
336− FromField k, FromField l, FromField m, FromField n, FromField o) =>
337− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)) where
338− fromRow = (null *> null *> null *> null *> null *>
339− null *> null *> null *> null *> null *>
340− null *> null *> null *> null *> null *> pure Nothing)
341− <|> (Just <$> fromRow)
342−
343−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
344− FromField f, FromField g, FromField h, FromField i, FromField j,
345− FromField k, FromField l, FromField m, FromField n, FromField o,
346− FromField p) =>
347− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) where
348− fromRow = (,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
349− <*> field <*> field <*> field <*> field <*> field
350− <*> field <*> field <*> field <*> field <*> field
351− <*> field
352−
353−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
354− FromField f, FromField g, FromField h, FromField i, FromField j,
355− FromField k, FromField l, FromField m, FromField n, FromField o,
356− FromField p) =>
357− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)) where
358− fromRow = (null *> null *> null *> null *> null *>
359− null *> null *> null *> null *> null *>
360− null *> null *> null *> null *> null *>
361− null *> pure Nothing)
362− <|> (Just <$> fromRow)
363−
364−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
365− FromField f, FromField g, FromField h, FromField i, FromField j,
366− FromField k, FromField l, FromField m, FromField n, FromField o,
367− FromField p, FromField q) =>
368− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) where
369− fromRow = (,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
370− <*> field <*> field <*> field <*> field <*> field
371− <*> field <*> field <*> field <*> field <*> field
372− <*> field <*> field
373−
374−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
375− FromField f, FromField g, FromField h, FromField i, FromField j,
376− FromField k, FromField l, FromField m, FromField n, FromField o,
377− FromField p, FromField q) =>
378− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q)) where
379− fromRow = (null *> null *> null *> null *> null *>
380− null *> null *> null *> null *> null *>
381− null *> null *> null *> null *> null *>
382− null *> null *> pure Nothing)
383− <|> (Just <$> fromRow)
384−
385−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
386− FromField f, FromField g, FromField h, FromField i, FromField j,
387− FromField k, FromField l, FromField m, FromField n, FromField o,
388− FromField p, FromField q, FromField r) =>
389− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) where
390− fromRow = (,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
391− <*> field <*> field <*> field <*> field <*> field
392− <*> field <*> field <*> field <*> field <*> field
393− <*> field <*> field <*> field
394−
395−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
396− FromField f, FromField g, FromField h, FromField i, FromField j,
397− FromField k, FromField l, FromField m, FromField n, FromField o,
398− FromField p, FromField q, FromField r) =>
399− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)) where
400− fromRow = (null *> null *> null *> null *> null *>
401− null *> null *> null *> null *> null *>
402− null *> null *> null *> null *> null *>
403− null *> null *> null *> pure Nothing)
404− <|> (Just <$> fromRow)
405−
406−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
407− FromField f, FromField g, FromField h, FromField i, FromField j,
408− FromField k, FromField l, FromField m, FromField n, FromField o,
409− FromField p, FromField q, FromField r, FromField s) =>
410− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) where
411− fromRow = (,,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
412− <*> field <*> field <*> field <*> field <*> field
413− <*> field <*> field <*> field <*> field <*> field
414− <*> field <*> field <*> field <*> field
415−
416−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
417− FromField f, FromField g, FromField h, FromField i, FromField j,
418− FromField k, FromField l, FromField m, FromField n, FromField o,
419− FromField p, FromField q, FromField r, FromField s) =>
420− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s)) where
421− fromRow = (null *> null *> null *> null *> null *>
422− null *> null *> null *> null *> null *>
423− null *> null *> null *> null *> null *>
424− null *> null *> null *> null *> pure Nothing)
425− <|> (Just <$> fromRow)
426−
427−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
428− FromField f, FromField g, FromField h, FromField i, FromField j,
429− FromField k, FromField l, FromField m, FromField n, FromField o,
430− FromField p, FromField q, FromField r, FromField s, FromField t) =>
431− FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) where
432− fromRow = (,,,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
433− <*> field <*> field <*> field <*> field <*> field
434− <*> field <*> field <*> field <*> field <*> field
435− <*> field <*> field <*> field <*> field <*> field
436−
437−instance (FromField a, FromField b, FromField c, FromField d, FromField e,
438− FromField f, FromField g, FromField h, FromField i, FromField j,
439− FromField k, FromField l, FromField m, FromField n, FromField o,
440− FromField p, FromField q, FromField r, FromField s, FromField t) =>
441− FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t)) where
442− fromRow = (null *> null *> null *> null *> null *>
443− null *> null *> null *> null *> null *>
444− null *> null *> null *> null *> null *>
445− null *> null *> null *> null *> null *> pure Nothing)
446− <|> (Just <$> fromRow)
447−
448instance FromField a => FromRow [a] where
241instance FromField a => FromRow [a] where
449 fromRow = do
242 fromRow = do
450 n <- numFieldsRemaining
243 n <- numFieldsRemaining
src/Database/PostgreSQL/Simple/HStore.hs+2−2
@@ -8,14 +8,14 @@
8--
8--
9-- Parsers and printers for hstore, a extended type bundled with
9-- Parsers and printers for hstore, a extended type bundled with
10-- PostgreSQL providing finite maps from text strings to text strings.
10-- PostgreSQL providing finite maps from text strings to text strings.
11−-- See <https://www.postgresql.org/docs/9.5/static/hstore.html> for more
11+-- See <http://www.postgresql.org/docs/9.2/static/hstore.html> for more
12-- information.
12-- information.
13--
13--
14-- Note that in order to use this type, a database superuser must
14-- Note that in order to use this type, a database superuser must
15-- install it by running a sql script in the share directory. This
15-- install it by running a sql script in the share directory. This
16-- can be done on PostgreSQL 9.1 and later with the command
16-- can be done on PostgreSQL 9.1 and later with the command
17-- @CREATE EXTENSION hstore@. See
17-- @CREATE EXTENSION hstore@. See
18−-- <https://www.postgresql.org/docs/9.5/static/contrib.html> for more
18+-- <http://www.postgresql.org/docs/9.2/static/contrib.html> for more
19-- information.
19-- information.
20--
20--
21------------------------------------------------------------------------------
21------------------------------------------------------------------------------
src/Database/PostgreSQL/Simple/HStore/Implementation.hs+11−11
@@ -22,6 +22,9 @@ import Data.ByteString.Builder (Builder, byteString, char8)
22import qualified Data.ByteString.Builder as BU
22import qualified Data.ByteString.Builder as BU
23import Data.ByteString.Internal (c2w, w2c)
23import Data.ByteString.Internal (c2w, w2c)
24import qualified Data.ByteString.Lazy as BL
24import qualified Data.ByteString.Lazy as BL
25+#if !MIN_VERSION_bytestring(0,10,0)
26+import qualified Data.ByteString.Lazy.Internal as BL (foldrChunks)
27+#endif
25import Data.Map(Map)
28import Data.Map(Map)
26import qualified Data.Map as Map
29import qualified Data.Map as Map
27import Data.Text(Text)
30import Data.Text(Text)
@@ -31,7 +34,6 @@ import Data.Text.Encoding.Error(UnicodeException)
31import qualified Data.Text.Lazy as TL
34import qualified Data.Text.Lazy as TL
32import Data.Typeable
35import Data.Typeable
33import Data.Monoid(Monoid(..))
36import Data.Monoid(Monoid(..))
34−import Data.Semigroup
35import Database.PostgreSQL.Simple.FromField
37import Database.PostgreSQL.Simple.FromField
36import Database.PostgreSQL.Simple.ToField
38import Database.PostgreSQL.Simple.ToField
37
39
@@ -50,28 +52,26 @@ instance ToHStore HStoreBuilder where
50toBuilder :: HStoreBuilder -> Builder
52toBuilder :: HStoreBuilder -> Builder
51toBuilder x = case x of
53toBuilder x = case x of
52 Empty -> mempty
54 Empty -> mempty
53− Comma c -> c
55+ Comma x -> x
54
56
55toLazyByteString :: HStoreBuilder -> BL.ByteString
57toLazyByteString :: HStoreBuilder -> BL.ByteString
56toLazyByteString x = case x of
58toLazyByteString x = case x of
57 Empty -> BL.empty
59 Empty -> BL.empty
58− Comma c -> BU.toLazyByteString c
60+ Comma x -> BU.toLazyByteString x
59
61
60−instance Semigroup HStoreBuilder where
62+instance Monoid HStoreBuilder where
61− Empty <> x = x
63+ mempty = Empty
64+ mappend Empty x = x
62− Comma a <> x
65+ mappend (Comma a) x
63 = Comma (a `mappend` case x of
66 = Comma (a `mappend` case x of
64 Empty -> mempty
67 Empty -> mempty
65 Comma b -> char8 ',' `mappend` b)
68 Comma b -> char8 ',' `mappend` b)
66
69
67−instance Monoid HStoreBuilder where
68− mempty = Empty
69−
70class ToHStoreText a where
70class ToHStoreText a where
71 toHStoreText :: a -> HStoreText
71 toHStoreText :: a -> HStoreText
72
72
73-- | Represents escape text, ready to be the key or value to a hstore value
73-- | Represents escape text, ready to be the key or value to a hstore value
74−newtype HStoreText = HStoreText Builder deriving (Typeable, Semigroup, Monoid)
74+newtype HStoreText = HStoreText Builder deriving (Typeable, Monoid)
75
75
76instance ToHStoreText HStoreText where
76instance ToHStoreText HStoreText where
77 toHStoreText = id
77 toHStoreText = id
@@ -144,7 +144,7 @@ newtype HStoreMap = HStoreMap {fromHStoreMap :: Map Text Text} deriving (Eq, Or
144
144
145instance ToHStore HStoreMap where
145instance ToHStore HStoreMap where
146 toHStore (HStoreMap xs) = Map.foldrWithKey f mempty xs
146 toHStore (HStoreMap xs) = Map.foldrWithKey f mempty xs
147− where f k v xs' = hstore k v `mappend` xs'
147+ where f k v xs = hstore k v `mappend` xs
148
148
149instance ToField HStoreMap where
149instance ToField HStoreMap where
150 toField xs = toField (toHStore xs)
150 toField xs = toField (toHStore xs)
src/Database/PostgreSQL/Simple/Internal.hs+18−69
@@ -1,8 +1,5 @@
1{-# LANGUAGE CPP, BangPatterns, DoAndIfThenElse, RecordWildCards #-}
1{-# LANGUAGE CPP, BangPatterns, DoAndIfThenElse, RecordWildCards #-}
2−{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
3−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
4−{-# LANGUAGE ExistentialQuantification #-}
5−{-# LANGUAGE InstanceSigs #-}
6
3
7------------------------------------------------------------------------------
4------------------------------------------------------------------------------
8-- |
5-- |
@@ -36,6 +33,7 @@ import Data.Int (Int64)
36import qualified Data.IntMap as IntMap
33import qualified Data.IntMap as IntMap
37import Data.IORef
34import Data.IORef
38import Data.Maybe(fromMaybe)
35import Data.Maybe(fromMaybe)
36+import Data.Monoid
39import Data.String
37import Data.String
40import qualified Data.Text as T
38import qualified Data.Text as T
41import qualified Data.Text.Encoding as TE
39import qualified Data.Text.Encoding as TE
@@ -52,7 +50,6 @@ import Database.PostgreSQL.Simple.TypeInfo.Types(TypeInfo)
52import Control.Monad.Trans.State.Strict
50import Control.Monad.Trans.State.Strict
53import Control.Monad.Trans.Reader
51import Control.Monad.Trans.Reader
54import Control.Monad.Trans.Class
52import Control.Monad.Trans.Class
55−import GHC.Generics
56import GHC.IO.Exception
53import GHC.IO.Exception
57#if !defined(mingw32_HOST_OS)
54#if !defined(mingw32_HOST_OS)
58import Control.Concurrent(threadWaitRead, threadWaitWrite)
55import Control.Concurrent(threadWaitRead, threadWaitWrite)
@@ -83,40 +80,18 @@ data Connection = Connection {
83instance Eq Connection where
80instance Eq Connection where
84 x == y = connectionHandle x == connectionHandle y
81 x == y = connectionHandle x == connectionHandle y
85
82
86−-- | Superclass for postgresql exceptions
87−data SomePostgreSqlException = forall e. Exception e => SomePostgreSqlException e
88− deriving Typeable
89−
90−postgresqlExceptionToException :: Exception e => e -> SomeException
91−postgresqlExceptionToException = toException . SomePostgreSqlException
92−
93−postgresqlExceptionFromException :: Exception e => SomeException -> Maybe e
94−postgresqlExceptionFromException x = do
95− SomePostgreSqlException a <- fromException x
96− cast a
97−
98−instance Show SomePostgreSqlException where
99− showsPrec :: Int -> SomePostgreSqlException -> ShowS
100− showsPrec p (SomePostgreSqlException e) = showsPrec p e
101−
102−instance Exception SomePostgreSqlException where
103− displayException (SomePostgreSqlException e) = displayException e
104−
105data SqlError = SqlError {
83data SqlError = SqlError {
106 sqlState :: ByteString
84 sqlState :: ByteString
107 , sqlExecStatus :: ExecStatus
85 , sqlExecStatus :: ExecStatus
108 , sqlErrorMsg :: ByteString
86 , sqlErrorMsg :: ByteString
109 , sqlErrorDetail :: ByteString
87 , sqlErrorDetail :: ByteString
110 , sqlErrorHint :: ByteString
88 , sqlErrorHint :: ByteString
111− } deriving (Eq, Show, Typeable)
89+ } deriving (Show, Typeable)
112
90
113fatalError :: ByteString -> SqlError
91fatalError :: ByteString -> SqlError
114fatalError msg = SqlError "" FatalError msg "" ""
92fatalError msg = SqlError "" FatalError msg "" ""
115
93
116−instance Exception SqlError where
94+instance Exception SqlError
117− toException = postgresqlExceptionToException
118− fromException = postgresqlExceptionFromException
119−
120
95
121-- | Exception thrown if 'query' is used to perform an @INSERT@-like
96-- | Exception thrown if 'query' is used to perform an @INSERT@-like
122-- operation, or 'execute' is used to perform a @SELECT@-like operation.
97-- operation, or 'execute' is used to perform a @SELECT@-like operation.
@@ -125,9 +100,7 @@ data QueryError = QueryError {
125 , qeQuery :: Query
100 , qeQuery :: Query
126 } deriving (Eq, Show, Typeable)
101 } deriving (Eq, Show, Typeable)
127
102
128−instance Exception QueryError where
103+instance Exception QueryError
129− toException = postgresqlExceptionToException
130− fromException = postgresqlExceptionFromException
131
104
132-- | Exception thrown if a 'Query' could not be formatted correctly.
105-- | Exception thrown if a 'Query' could not be formatted correctly.
133-- This may occur if the number of \'@?@\' characters in the query
106-- This may occur if the number of \'@?@\' characters in the query
@@ -138,9 +111,7 @@ data FormatError = FormatError {
138 , fmtParams :: [ByteString]
111 , fmtParams :: [ByteString]
139 } deriving (Eq, Show, Typeable)
112 } deriving (Eq, Show, Typeable)
140
113
141−instance Exception FormatError where
114+instance Exception FormatError
142− toException = postgresqlExceptionToException
143− fromException = postgresqlExceptionFromException
144
115
145data ConnectInfo = ConnectInfo {
116data ConnectInfo = ConnectInfo {
146 connectHost :: String
117 connectHost :: String
@@ -148,7 +119,7 @@ data ConnectInfo = ConnectInfo {
148 , connectUser :: String
119 , connectUser :: String
149 , connectPassword :: String
120 , connectPassword :: String
150 , connectDatabase :: String
121 , connectDatabase :: String
151− } deriving (Generic,Eq,Read,Show,Typeable)
122+ } deriving (Eq,Read,Show,Typeable)
152
123
153-- | Default information for setting up a connection.
124-- | Default information for setting up a connection.
154--
125--
@@ -182,12 +153,6 @@ defaultConnectInfo = ConnectInfo {
182connect :: ConnectInfo -> IO Connection
153connect :: ConnectInfo -> IO Connection
183connect = connectPostgreSQL . postgreSQLConnectionString
154connect = connectPostgreSQL . postgreSQLConnectionString
184
155
185−-- | Memory bracket around 'connect' and 'close'.
186−--
187−-- @since 0.6.5
188−withConnect :: ConnectInfo -> (Connection -> IO c) -> IO c
189−withConnect connInfo = bracket (connect connInfo) close
190−
191-- | Attempt to make a connection based on a libpq connection string.
156-- | Attempt to make a connection based on a libpq connection string.
192-- See <https://www.postgresql.org/docs/9.5/static/libpq-connect.html#LIBPQ-CONNSTRING>
157-- See <https://www.postgresql.org/docs/9.5/static/libpq-connect.html#LIBPQ-CONNSTRING>
193-- for more information. Also note that environment variables also affect
158-- for more information. Also note that environment variables also affect
@@ -223,8 +188,7 @@ withConnect connInfo = bracket (connect connInfo) close
223--
188--
224-- Omitting @password@ will default to an appropriate password found
189-- Omitting @password@ will default to an appropriate password found
225-- in the @pgpass@ file, or no password at all if a matching line is
190-- in the @pgpass@ file, or no password at all if a matching line is
226−-- not found. The path of the @pgpass@ file may be specified by setting
191+-- not found. See
227−-- the @PGPASSFILE@ environment variable. See
228-- <https://www.postgresql.org/docs/9.5/static/libpq-pgpass.html> for
192-- <https://www.postgresql.org/docs/9.5/static/libpq-pgpass.html> for
229-- more information regarding this file.
193-- more information regarding this file.
230--
194--
@@ -323,7 +287,7 @@ postgreSQLConnectionString connectInfo = fromString connstr
323
287
324 str name field
288 str name field
325 | null value = id
289 | null value = id
326− | otherwise = showString name . addQuotes value . space
290+ | otherwise = showString name . quote value . space
327 where value = field connectInfo
291 where value = field connectInfo
328
292
329 num name field
293 num name field
@@ -331,7 +295,7 @@ postgreSQLConnectionString connectInfo = fromString connstr
331 | otherwise = showString name . shows value . space
295 | otherwise = showString name . shows value . space
332 where value = field connectInfo
296 where value = field connectInfo
333
297
334− addQuotes s rest = '\'' : foldr delta ('\'' : rest) s
298+ quote str rest = '\'' : foldr delta ('\'' : rest) str
335 where
299 where
336 delta c cs = case c of
300 delta c cs = case c of
337 '\\' -> '\\' : '\\' : cs
301 '\\' -> '\\' : '\\' : cs
@@ -387,7 +351,6 @@ exec conn sql =
387 Just res -> do
351 Just res -> do
388 status <- PQ.resultStatus res
352 status <- PQ.resultStatus res
389 case status of
353 case status of
390− -- FIXME: handle PQ.CopyBoth and PQ.SingleTuple
391 PQ.EmptyQuery -> getResult h mres'
354 PQ.EmptyQuery -> getResult h mres'
392 PQ.CommandOk -> getResult h mres'
355 PQ.CommandOk -> getResult h mres'
393 PQ.TuplesOk -> getResult h mres'
356 PQ.TuplesOk -> getResult h mres'
@@ -408,7 +371,6 @@ finishExecute :: Connection -> Query -> PQ.Result -> IO Int64
408finishExecute _conn q result = do
371finishExecute _conn q result = do
409 status <- PQ.resultStatus result
372 status <- PQ.resultStatus result
410 case status of
373 case status of
411− -- FIXME: handle PQ.CopyBoth and PQ.SingleTuple
412 PQ.EmptyQuery -> throwIO $ QueryError "execute: Empty query" q
374 PQ.EmptyQuery -> throwIO $ QueryError "execute: Empty query" q
413 PQ.CommandOk -> do
375 PQ.CommandOk -> do
414 ncols <- PQ.nfields result
376 ncols <- PQ.nfields result
@@ -419,7 +381,7 @@ finishExecute _conn q result = do
419 nstr <- PQ.cmdTuples result
381 nstr <- PQ.cmdTuples result
420 return $ case nstr of
382 return $ case nstr of
421 Nothing -> 0 -- is this appropriate?
383 Nothing -> 0 -- is this appropriate?
422− Just str -> mkInteger str
384+ Just str -> toInteger str
423 PQ.TuplesOk -> do
385 PQ.TuplesOk -> do
424 ncols <- PQ.nfields result
386 ncols <- PQ.nfields result
425 throwIO $ QueryError ("execute resulted in " ++ show ncols ++
387 throwIO $ QueryError ("execute resulted in " ++ show ncols ++
@@ -432,7 +394,7 @@ finishExecute _conn q result = do
432 PQ.NonfatalError -> throwResultError "execute" result status
394 PQ.NonfatalError -> throwResultError "execute" result status
433 PQ.FatalError -> throwResultError "execute" result status
395 PQ.FatalError -> throwResultError "execute" result status
434 where
396 where
435− mkInteger str = B8.foldl' delta 0 str
397+ toInteger str = B8.foldl' delta 0 str
436 where
398 where
437 delta acc c =
399 delta acc c =
438 if '0' <= c && c <= '9'
400 if '0' <= c && c <= '9'
@@ -447,8 +409,8 @@ throwResultError _ result status = do
447 PQ.resultErrorField result PQ.DiagMessageDetail
409 PQ.resultErrorField result PQ.DiagMessageDetail
448 hint <- fromMaybe "" <$>
410 hint <- fromMaybe "" <$>
449 PQ.resultErrorField result PQ.DiagMessageHint
411 PQ.resultErrorField result PQ.DiagMessageHint
450− state' <- maybe "" id <$> PQ.resultErrorField result PQ.DiagSqlstate
412+ state <- maybe "" id <$> PQ.resultErrorField result PQ.DiagSqlstate
451− throwIO $ SqlError { sqlState = state'
413+ throwIO $ SqlError { sqlState = state
452 , sqlExecStatus = status
414 , sqlExecStatus = status
453 , sqlErrorMsg = errormsg
415 , sqlErrorMsg = errormsg
454 , sqlErrorDetail = detail
416 , sqlErrorDetail = detail
@@ -517,6 +479,9 @@ instance Alternative Conversion where
517 Errors _ -> (oka <|>) <$> runConversion mb conn
479 Errors _ -> (oka <|>) <$> runConversion mb conn
518
480
519instance Monad Conversion where
481instance Monad Conversion where
482+#if !(MIN_VERSION_base(4,8,0))
483+ return = pure
484+#endif
520 m >>= f = Conversion $ \conn -> do
485 m >>= f = Conversion $ \conn -> do
521 oka <- runConversion m conn
486 oka <- runConversion m conn
522 case oka of
487 case oka of
@@ -531,7 +496,7 @@ conversionMap :: (Ok a -> Ok b) -> Conversion a -> Conversion b
531conversionMap f m = Conversion $ \conn -> f <$> runConversion m conn
496conversionMap f m = Conversion $ \conn -> f <$> runConversion m conn
532
497
533conversionError :: Exception err => err -> Conversion a
498conversionError :: Exception err => err -> Conversion a
534−conversionError err = Conversion $ \_ -> return (Errors [toException err])
499+conversionError err = Conversion $ \_ -> return (Errors [SomeException err])
535
500
536newTempName :: Connection -> IO Query
501newTempName :: Connection -> IO Query
537newTempName Connection{..} = do
502newTempName Connection{..} = do
@@ -619,19 +584,3 @@ escapeIdentifier = escapeWrap PQ.escapeIdentifier
619
584
620escapeByteaConn :: Connection -> ByteString -> IO (Either ByteString ByteString)
585escapeByteaConn :: Connection -> ByteString -> IO (Either ByteString ByteString)
621escapeByteaConn = escapeWrap PQ.escapeByteaConn
586escapeByteaConn = escapeWrap PQ.escapeByteaConn
622−
623−breakOnSingleQuestionMark :: ByteString -> (ByteString, ByteString)
624−breakOnSingleQuestionMark b = go (B8.empty, b)
625− where go (x,bs) = (x `B8.append` x',bs')
626− -- seperate from first QM
627− where tup@(noQ, restWithQ) = B8.break (=='?') bs
628− -- if end of query, just return
629− -- else check for second QM in 'go2'
630− (x', bs') = maybe tup go2 $
631− -- drop found QM and peek at next char
632− B8.uncons restWithQ >>= B8.uncons . snd
633− -- another QM after the first means:
634− -- take literal QM and keep going.
635− go2 ('?', t2) = go (noQ `B8.snoc` '?',t2)
636− -- Anything else means
637− go2 _ = tup
src/Database/PostgreSQL/Simple/Internal/PQResultUtils.hsdeleted−123
@@ -1,123 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−
3−------------------------------------------------------------------------------
4−-- |
5−-- Module: Database.PostgreSQL.Simple.Internal.PQResultUtils
6−-- Copyright: (c) 2011 MailRank, Inc.
7−-- (c) 2011-2012 Leon P Smith
8−-- License: BSD3
9−-- Maintainer: Leon P Smith <leon@melding-monads.com>
10−-- Stability: experimental
11−--
12−------------------------------------------------------------------------------
13−
14−
15−module Database.PostgreSQL.Simple.Internal.PQResultUtils
16− ( finishQueryWith
17− , finishQueryWithV
18− , finishQueryWithVU
19− , getRowWith
20− ) where
21−
22−import Control.Exception as E
23−import Data.ByteString (ByteString)
24−import Data.Foldable (for_)
25−import Database.PostgreSQL.Simple.FromField (ResultError(..))
26−import Database.PostgreSQL.Simple.Ok
27−import Database.PostgreSQL.Simple.Types (Query(..))
28−import Database.PostgreSQL.Simple.Internal as Base hiding (result, row)
29−import Database.PostgreSQL.Simple.TypeInfo
30−import qualified Database.PostgreSQL.LibPQ as PQ
31−import 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
36−import Control.Monad.Trans.Reader
37−import Control.Monad.Trans.State.Strict
38−
39−finishQueryWith :: RowParser r -> Connection -> Query -> PQ.Result -> IO [r]
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
72− status <- PQ.resultStatus result
73− case status of
74− PQ.TuplesOk -> k
75− PQ.EmptyQuery -> queryErr "query: Empty query"
76− PQ.CommandOk -> queryErr "query resulted in a command response (did you mean to use `execute` or forget a RETURNING?)"
77− PQ.CopyOut -> queryErr "query: COPY TO is not supported"
78− PQ.CopyIn -> queryErr "query: COPY FROM is not supported"
79− PQ.CopyBoth -> queryErr "query: COPY BOTH is not supported"
80− PQ.SingleTuple -> queryErr "query: single-row mode is not supported"
81− PQ.BadResponse -> throwResultError "query" result status
82− PQ.NonfatalError -> throwResultError "query" result status
83− PQ.FatalError -> throwResultError "query" result status
84− where
85− queryErr msg = throwIO $ QueryError msg q
86−
87−getRowWith :: RowParser r -> PQ.Row -> PQ.Column -> Connection -> PQ.Result -> IO r
88−getRowWith parser row ncols conn result = do
89− let rw = Row row result
90− let unCol (PQ.Col x) = fromIntegral x :: Int
91− okvc <- runConversion (runStateT (runReaderT (unRP parser) rw) 0) conn
92− case okvc of
93− Ok (val,col) | col == ncols -> return val
94− | otherwise -> do
95− vals <- forM' 0 (ncols-1) $ \c -> do
96− tinfo <- getTypeInfo conn =<< PQ.ftype result c
97− v <- PQ.getvalue result row c
98− return ( tinfo
99− , fmap ellipsis v )
100− throw (ConversionFailed
101− (show (unCol ncols) ++ " values: " ++ show vals)
102− Nothing
103− ""
104− (show (unCol col) ++ " slots in target type")
105− "mismatch between number of columns to convert and number in target type")
106− Errors [] -> throwIO $ ConversionFailed "" Nothing "" "" "unknown error"
107− Errors [x] -> throwIO x
108− Errors xs -> throwIO $ ManyErrors xs
109−
110−ellipsis :: ByteString -> ByteString
111−ellipsis bs
112− | B.length bs > 15 = B.take 10 bs `B.append` "[...]"
113− | otherwise = bs
114−
115−forM' :: (Ord n, Num n) => n -> n -> (n -> IO a) -> IO [a]
116−forM' lo hi m = loop hi []
117− where
118− loop !n !as
119− | n < lo = return as
120− | otherwise = do
121− a <- m n
122− loop (n-1) (a:as)
123−{-# INLINE forM' #-}
src/Database/PostgreSQL/Simple/LargeObjects.hs+1−1
@@ -7,7 +7,7 @@
7-- Maintainer : leon@melding-monads.com
7-- Maintainer : leon@melding-monads.com
8--
8--
9-- Support for PostgreSQL's Large Objects; see
9-- Support for PostgreSQL's Large Objects; see
10−-- <https://www.postgresql.org/docs/9.5/static/largeobjects.html> for more
10+-- <http://www.postgresql.org/docs/9.1/static/largeobjects.html> for more
11-- information.
11-- information.
12--
12--
13-- Note that Large Object File Descriptors are only valid within a single
13-- Note that Large Object File Descriptors are only valid within a single
src/Database/PostgreSQL/Simple/Newtypes.hsdeleted−49
@@ -1,49 +0,0 @@
1−{-# LANGUAGE DeriveFunctor #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
3−-- | Module with newtypes suitable to usage with @DerivingVia@ or standalone.
4−--
5−-- The newtypes are named after packages they wrap.
6−module Database.PostgreSQL.Simple.Newtypes (
7− Aeson (..), getAeson,
8−) where
9−
10−import Data.Typeable (Typeable)
11−import Database.PostgreSQL.Simple.ToField (ToField (..))
12−import Database.PostgreSQL.Simple.FromField (FromField (..), fromJSONField)
13−
14−import qualified Data.Aeson as Aeson
15−
16−-------------------------------------------------------------------------------
17−-- aeson
18−-------------------------------------------------------------------------------
19−
20−-- | A newtype wrapper with 'ToField' and 'FromField' instances
21−-- based on 'Aeson.ToJSON' and 'Aeson.FromJSON' type classes from @aeson@.
22−--
23−-- Example using @DerivingVia@:
24−--
25−-- @
26−-- data Foo = Foo Int String
27−-- deriving stock (Eq, Show, Generic) -- GHC built int
28−-- deriving anyclass ('Aeson.FromJSON', 'Aeson.ToJSON') -- Derived using GHC Generics
29−-- deriving ('ToField', 'FromField') via 'Aeson' Foo -- DerivingVia
30−-- @
31−--
32−-- Example using 'Aeson' newtype directly, for more ad-hoc queries
33−--
34−-- @
35−-- execute conn "INSERT INTO tbl (fld) VALUES (?)" (Only ('Aeson' x))
36−-- @
37−--
38−-- @since 0.6.3
39−newtype Aeson a = Aeson a
40− deriving (Eq, Show, Read, Typeable, Functor)
41−
42−getAeson :: Aeson a -> a
43−getAeson (Aeson a) = a
44−
45−instance Aeson.ToJSON a => ToField (Aeson a) where
46− toField = toField . Aeson.encode . getAeson
47−
48−instance (Aeson.FromJSON a, Typeable a) => FromField (Aeson a) where
49− fromField f bs = fmap Aeson (fromJSONField f bs)
src/Database/PostgreSQL/Simple/Notification.hs+20−3
@@ -14,7 +14,7 @@
14--
14--
15-- Support for receiving asynchronous notifications via PostgreSQL's
15-- Support for receiving asynchronous notifications via PostgreSQL's
16-- Listen/Notify mechanism. See
16-- Listen/Notify mechanism. See
17−-- <https://www.postgresql.org/docs/9.5/static/sql-notify.html> for more
17+-- <http://www.postgresql.org/docs/9.1/static/sql-notify.html> for more
18-- information.
18-- information.
19--
19--
20-- Note that on Windows, @getNotification@ currently uses a polling loop
20-- Note that on Windows, @getNotification@ currently uses a polling loop
@@ -25,7 +25,7 @@
25-- Notifications do not create any extra work for the backend, and are
25-- Notifications do not create any extra work for the backend, and are
26-- likely cheaper on the client side as well.
26-- likely cheaper on the client side as well.
27--
27--
28−-- <https://hackage.haskell.org/trac/ghc/ticket/7353>
28+-- <http://hackage.haskell.org/trac/ghc/ticket/7353>
29--
29--
30-----------------------------------------------------------------------------
30-----------------------------------------------------------------------------
31
31
@@ -47,6 +47,8 @@ import GHC.IO.Exception ( ioe_location )
47
47
48#if defined(mingw32_HOST_OS)
48#if defined(mingw32_HOST_OS)
49import Control.Concurrent ( threadDelay )
49import Control.Concurrent ( threadDelay )
50+#elif !MIN_VERSION_base(4,7,0)
51+import Control.Concurrent ( threadWaitRead )
50#else
52#else
51import GHC.Conc ( atomically )
53import GHC.Conc ( atomically )
52import Control.Concurrent ( threadWaitReadSTM )
54import Control.Concurrent ( threadWaitReadSTM )
@@ -56,7 +58,7 @@ data Notification = Notification
56 { notificationPid :: {-# UNPACK #-} !CPid
58 { notificationPid :: {-# UNPACK #-} !CPid
57 , notificationChannel :: {-# UNPACK #-} !B.ByteString
59 , notificationChannel :: {-# UNPACK #-} !B.ByteString
58 , notificationData :: {-# UNPACK #-} !B.ByteString
60 , notificationData :: {-# UNPACK #-} !B.ByteString
59− } deriving (Show, Eq)
61+ }
60
62
61convertNotice :: PQ.Notify -> Notification
63convertNotice :: PQ.Notify -> Notification
62convertNotice PQ.Notify{..}
64convertNotice PQ.Notify{..}
@@ -92,6 +94,21 @@ getNotification conn = join $ withConnection conn fetch
92 -- with async exceptions, whereas threadDelay can.
94 -- with async exceptions, whereas threadDelay can.
93 Just _fd -> do
95 Just _fd -> do
94 return (threadDelay 1000000 >> loop)
96 return (threadDelay 1000000 >> loop)
97+#elif !MIN_VERSION_base(4,7,0)
98+ -- Technically there's a race condition that is usually benign.
99+ -- If the connection is closed or reset after we drop the
100+ -- lock, and then the fd index is reallocated to a new
101+ -- descriptor before we call threadWaitRead, then
102+ -- we could end up waiting on the wrong descriptor.
103+ --
104+ -- Now, if the descriptor becomes readable promptly, then
105+ -- it's no big deal as we'll wake up and notice the change
106+ -- on the next iteration of the loop. But if are very
107+ -- unlucky, then we could end up waiting a long time.
108+ Just fd -> do
109+ return $ do
110+ threadWaitRead fd `catch` (throwIO . setIOErrorLocation)
111+ loop
95#else
112#else
96 -- This case fixes the race condition above. By registering
113 -- This case fixes the race condition above. By registering
97 -- our interest in the descriptor before we drop the lock,
114 -- our interest in the descriptor before we drop the lock,
src/Database/PostgreSQL/Simple/Ok.hs+4−7
@@ -37,8 +37,6 @@ import Control.Exception
37import Control.Monad(MonadPlus(..))
37import Control.Monad(MonadPlus(..))
38import Data.Typeable
38import Data.Typeable
39
39
40−import qualified Control.Monad.Fail as Fail
41−
42-- FIXME: [SomeException] should probably be something else, maybe
40-- FIXME: [SomeException] should probably be something else, maybe
43-- a difference list (or a tree?)
41-- a difference list (or a tree?)
44
42
@@ -72,14 +70,13 @@ instance MonadPlus Ok where
72 mplus = (<|>)
70 mplus = (<|>)
73
71
74instance Monad Ok where
72instance Monad Ok where
73+#if !(MIN_VERSION_base(4,8,0))
74+ return = pure
75+#endif
76+
75 Errors es >>= _ = Errors es
77 Errors es >>= _ = Errors es
76 Ok a >>= f = f a
78 Ok a >>= f = f a
77
79
78−#if !(MIN_VERSION_base(4,13,0))
79− fail = Fail.fail
80−#endif
81−
82−instance Fail.MonadFail Ok where
83 fail str = Errors [SomeException (ErrorCall str)]
80 fail str = Errors [SomeException (ErrorCall str)]
84
81
85-- | a way to reify a list of exceptions into a single exception
82-- | a way to reify a list of exceptions into a single exception
src/Database/PostgreSQL/Simple/Range.hs+10−14
@@ -19,7 +19,6 @@ module Database.PostgreSQL.Simple.Range
19 , empty
19 , empty
20 , isEmpty, isEmptyBy
20 , isEmpty, isEmptyBy
21 , contains, containsBy
21 , contains, containsBy
22− , fromFieldRange
23 ) where
22 ) where
24
23
25import Control.Applicative hiding (empty)
24import Control.Applicative hiding (empty)
@@ -38,7 +37,7 @@ import Data.Monoid (mempty)
38import Data.Scientific (Scientific)
37import Data.Scientific (Scientific)
39import qualified Data.Text.Lazy.Builder as LT
38import qualified Data.Text.Lazy.Builder as LT
40import qualified Data.Text.Lazy.Encoding as LT
39import qualified Data.Text.Lazy.Encoding as LT
41−import Data.Time.Compat (Day, LocalTime,
40+import Data.Time (Day, LocalTime,
42 NominalDiffTime,
41 NominalDiffTime,
43 TimeOfDay, UTCTime,
42 TimeOfDay, UTCTime,
44 ZonedTime,
43 ZonedTime,
@@ -110,19 +109,19 @@ containsBy cmp rng x =
110 PGRange _lb NegInfinity -> False
109 PGRange _lb NegInfinity -> False
111 PGRange lb ub -> checkLB lb x && checkUB ub x
110 PGRange lb ub -> checkLB lb x && checkUB ub x
112 where
111 where
113− checkLB lb y =
112+ checkLB lb x =
114 case lb of
113 case lb of
115 NegInfinity -> True
114 NegInfinity -> True
116 PosInfinity -> False
115 PosInfinity -> False
117− Inclusive a -> cmp a y /= GT
116+ Inclusive a -> cmp a x /= GT
118− Exclusive a -> cmp a y == LT
117+ Exclusive a -> cmp a x == LT
119
118
120− checkUB ub y =
119+ checkUB ub x =
121 case ub of
120 case ub of
122 NegInfinity -> False
121 NegInfinity -> False
123 PosInfinity -> True
122 PosInfinity -> True
124− Inclusive z -> cmp y z /= GT
123+ Inclusive z -> cmp x z /= GT
125− Exclusive z -> cmp y z == LT
124+ Exclusive z -> cmp x z == LT
126
125
127lowerBound :: Parser (a -> RangeBound a)
126lowerBound :: Parser (a -> RangeBound a)
128lowerBound = (A.char '(' *> pure Exclusive) <|> (A.char '[' *> pure Inclusive)
127lowerBound = (A.char '(' *> pure Exclusive) <|> (A.char '[' *> pure Inclusive)
@@ -190,10 +189,7 @@ rangeToBuilderBy cmp f x =
190
189
191
190
192instance (FromField a, Typeable a) => FromField (PGRange a) where
191instance (FromField a, Typeable a) => FromField (PGRange a) where
193− fromField = fromFieldRange fromField
192+ fromField f mdat = do
194−
195−fromFieldRange :: Typeable a => FieldParser a -> FieldParser (PGRange a)
196−fromFieldRange fromField' f mdat = do
197 info <- typeInfo f
193 info <- typeInfo f
198 case info of
194 case info of
199 Range{} ->
195 Range{} ->
@@ -203,8 +199,8 @@ fromFieldRange fromField' f mdat = do
203 Just "empty" -> pure $ empty
199 Just "empty" -> pure $ empty
204 Just bs ->
200 Just bs ->
205 let parseIt NegInfinity = pure NegInfinity
201 let parseIt NegInfinity = pure NegInfinity
206− parseIt (Inclusive v) = Inclusive <$> fromField' f' (Just v)
202+ parseIt (Inclusive v) = Inclusive <$> fromField f' (Just v)
207− parseIt (Exclusive v) = Exclusive <$> fromField' f' (Just v)
203+ parseIt (Exclusive v) = Exclusive <$> fromField f' (Just v)
208 parseIt PosInfinity = pure PosInfinity
204 parseIt PosInfinity = pure PosInfinity
209 in case parseOnly pgrange bs of
205 in case parseOnly pgrange bs of
210 Left e -> returnError ConversionFailed f e
206 Left e -> returnError ConversionFailed f e
src/Database/PostgreSQL/Simple/SqlQQ.hs+9−10
@@ -1,9 +1,4 @@
1−{-# LANGUAGE CPP #-}
2−#if __GLASGOW_HASKELL__ >= 800
3−{-# LANGUAGE TemplateHaskellQuotes #-}
4−#else
5{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
6−#endif
7------------------------------------------------------------------------------
2------------------------------------------------------------------------------
8-- |
3-- |
9-- Module: Database.PostgreSQL.Simple.SqlQQ
4-- Module: Database.PostgreSQL.Simple.SqlQQ
@@ -35,7 +30,7 @@ import Data.String
35-- > (beginTime,endTime,string)
30-- > (beginTime,endTime,string)
36--
31--
37-- This quasiquoter returns a literal string expression of type 'Query',
32-- This quasiquoter returns a literal string expression of type 'Query',
38−-- and attempts to minimize whitespace; otherwise the above query would
33+-- and attempts to mimimize whitespace; otherwise the above query would
39-- consist of approximately half whitespace when sent to the database
34-- consist of approximately half whitespace when sent to the database
40-- backend. It also recognizes and strips out standard sql comments "--".
35-- backend. It also recognizes and strips out standard sql comments "--".
41--
36--
@@ -57,10 +52,13 @@ import Data.String
57
52
58sql :: QuasiQuoter
53sql :: QuasiQuoter
59sql = QuasiQuoter
54sql = QuasiQuoter
60− { quotePat = error "Database.PostgreSQL.Simple.SqlQQ.sql: quasiquoter used in pattern context"
55+ { quotePat = error "Database.PostgreSQL.Simple.SqlQQ.sql:\
56+ \ quasiquoter used in pattern context"
61− , quoteType = error "Database.PostgreSQL.Simple.SqlQQ.sql: quasiquoter used in type context"
57+ , quoteType = error "Database.PostgreSQL.Simple.SqlQQ.sql:\
58+ \ quasiquoter used in type context"
62 , quoteExp = sqlExp
59 , quoteExp = sqlExp
63− , quoteDec = error "Database.PostgreSQL.Simple.SqlQQ.sql: quasiquoter used in declaration context"
60+ , quoteDec = error "Database.PostgreSQL.Simple.SqlQQ.sql:\
61+ \ quasiquoter used in declaration context"
64 }
62 }
65
63
66sqlExp :: String -> Q Exp
64sqlExp :: String -> Q Exp
@@ -87,4 +85,5 @@ minimizeSpace = drop 1 . reduceSpace
87 instring ('\'':'\'':xs) = '\'':'\'': instring xs
85 instring ('\'':'\'':xs) = '\'':'\'': instring xs
88 instring ('\'':xs) = '\'': insql xs
86 instring ('\'':xs) = '\'': insql xs
89 instring (x:xs) = x : instring xs
87 instring (x:xs) = x : instring xs
90− instring [] = error "Database.PostgreSQL.Simple.SqlQQ.sql: string literal not terminated"
88+ instring [] = error "Database.PostgreSQL.Simple.SqlQQ.sql:\
89+ \ string literal not terminated"
src/Database/PostgreSQL/Simple/Time.hs+1−3
@@ -11,7 +11,7 @@ infinity, as well as some functions for converting to and from strings.
11Also, this module also contains commentary regarding postgresql's timestamp
11Also, this module also contains commentary regarding postgresql's timestamp
12types, civil timekeeping in general, and how it relates to
12types, civil timekeeping in general, and how it relates to
13postgresql-simple. You can read more about PostgreSQL's date and time types
13postgresql-simple. You can read more about PostgreSQL's date and time types
14−at <https://www.postgresql.org/docs/9.5/static/datatype-datetime.html>,
14+at <http://www.postgresql.org/docs/9.1/static/datatype-datetime.html>,
15and the IANA time zone database at <https://en.wikipedia.org/wiki/Tz_database>.
15and the IANA time zone database at <https://en.wikipedia.org/wiki/Tz_database>.
16
16
17Stack Overflow also has some excellent commentary on time, if it is a
17Stack Overflow also has some excellent commentary on time, if it is a
@@ -227,7 +227,6 @@ module Database.PostgreSQL.Simple.Time
227 , parseUTCTimestamp
227 , parseUTCTimestamp
228 , parseZonedTimestamp
228 , parseZonedTimestamp
229 , parseLocalTimestamp
229 , parseLocalTimestamp
230− , parseCalendarDiffTime
231 , dayToBuilder
230 , dayToBuilder
232 , utcTimeToBuilder
231 , utcTimeToBuilder
233 , zonedTimeToBuilder
232 , zonedTimeToBuilder
@@ -240,7 +239,6 @@ module Database.PostgreSQL.Simple.Time
240 , localTimestampToBuilder
239 , localTimestampToBuilder
241 , unboundedToBuilder
240 , unboundedToBuilder
242 , nominalDiffTimeToBuilder
241 , nominalDiffTimeToBuilder
243− , calendarDiffTimeToBuilder
244 ) where
242 ) where
245
243
246import Database.PostgreSQL.Simple.Time.Implementation
244import Database.PostgreSQL.Simple.Time.Implementation
src/Database/PostgreSQL/Simple/Time/Implementation.hs+1−11
@@ -18,8 +18,7 @@ import Data.ByteString.Builder.Prim(primBounded)
18import Control.Arrow((***))
18import Control.Arrow((***))
19import Control.Applicative
19import Control.Applicative
20import qualified Data.ByteString as B
20import qualified Data.ByteString as B
21−import Data.Time.Compat (LocalTime, UTCTime, ZonedTime, Day, TimeOfDay, TimeZone, NominalDiffTime, utc)
21+import Data.Time hiding (getTimeZone, getZonedTime)
22−import Data.Time.LocalTime.Compat (CalendarDiffTime)
23import Data.Typeable
22import Data.Typeable
24import Data.Maybe (fromMaybe)
23import Data.Maybe (fromMaybe)
25import qualified Data.Attoparsec.ByteString.Char8 as A
24import qualified Data.Attoparsec.ByteString.Char8 as A
@@ -78,9 +77,6 @@ parseLocalTimestamp = A.parseOnly (getLocalTimestamp <* A.endOfInput)
78parseDate :: B.ByteString -> Either String Date
77parseDate :: B.ByteString -> Either String Date
79parseDate = A.parseOnly (getDate <* A.endOfInput)
78parseDate = A.parseOnly (getDate <* A.endOfInput)
80
79
81−parseCalendarDiffTime :: B.ByteString -> Either String CalendarDiffTime
82−parseCalendarDiffTime = A.parseOnly (getCalendarDiffTime <* A.endOfInput)
83−
84getUnbounded :: A.Parser a -> A.Parser (Unbounded a)
80getUnbounded :: A.Parser a -> A.Parser (Unbounded a)
85getUnbounded getFinite
81getUnbounded getFinite
86 = (pure NegInfinity <* A.string "-infinity")
82 = (pure NegInfinity <* A.string "-infinity")
@@ -129,9 +125,6 @@ getUTCTime = TP.utcTime
129getUTCTimestamp :: A.Parser UTCTimestamp
125getUTCTimestamp :: A.Parser UTCTimestamp
130getUTCTimestamp = getUnbounded getUTCTime
126getUTCTimestamp = getUnbounded getUTCTime
131
127
132−getCalendarDiffTime :: A.Parser CalendarDiffTime
133−getCalendarDiffTime = TP.calendarDiffTime
134−
135dayToBuilder :: Day -> Builder
128dayToBuilder :: Day -> Builder
136dayToBuilder = primBounded TPP.day
129dayToBuilder = primBounded TPP.day
137
130
@@ -171,6 +164,3 @@ dateToBuilder = unboundedToBuilder dayToBuilder
171
164
172nominalDiffTimeToBuilder :: NominalDiffTime -> Builder
165nominalDiffTimeToBuilder :: NominalDiffTime -> Builder
173nominalDiffTimeToBuilder = TPP.nominalDiffTime
166nominalDiffTimeToBuilder = TPP.nominalDiffTime
174−
175−calendarDiffTimeToBuilder :: CalendarDiffTime -> Builder
176−calendarDiffTimeToBuilder = TPP.calendarDiffTime
src/Database/PostgreSQL/Simple/Time/Internal/Parser.hs+3−12
@@ -21,24 +21,20 @@ module Database.PostgreSQL.Simple.Time.Internal.Parser
21 , localToUTCTimeOfDayHMS
21 , localToUTCTimeOfDayHMS
22 , utcTime
22 , utcTime
23 , zonedTime
23 , zonedTime
24− , calendarDiffTime
25 ) where
24 ) where
26
25
27import Control.Applicative ((<$>), (<*>), (<*), (*>))
26import Control.Applicative ((<$>), (<*>), (<*), (*>))
28import Database.PostgreSQL.Simple.Compat (toPico)
27import Database.PostgreSQL.Simple.Compat (toPico)
29import Data.Attoparsec.ByteString.Char8 as A
28import Data.Attoparsec.ByteString.Char8 as A
30import Data.Bits ((.&.))
29import Data.Bits ((.&.))
31−import Data.ByteString (ByteString)
32import Data.Char (ord)
30import Data.Char (ord)
33import Data.Fixed (Pico)
31import Data.Fixed (Pico)
34import Data.Int (Int64)
32import Data.Int (Int64)
35import Data.Maybe (fromMaybe)
33import Data.Maybe (fromMaybe)
36−import Data.Time.Calendar.Compat (Day, fromGregorianValid, addDays)
34+import Data.Time.Calendar (Day, fromGregorianValid, addDays)
37−import Data.Time.Clock.Compat (UTCTime(..))
35+import Data.Time.Clock (UTCTime(..))
38−import Data.Time.Format.ISO8601.Compat (iso8601ParseM)
39−import Data.Time.LocalTime.Compat (CalendarDiffTime)
40import qualified Data.ByteString.Char8 as B8
36import qualified Data.ByteString.Char8 as B8
41−import qualified Data.Time.LocalTime.Compat as Local
37+import qualified Data.Time.LocalTime as Local
42
38
43-- | Parse a date of the form @YYYY-MM-DD@.
39-- | Parse a date of the form @YYYY-MM-DD@.
44day :: Parser Day
40day :: Parser Day
@@ -197,8 +193,3 @@ zonedTime = Local.ZonedTime <$> localTime <*> (fromMaybe utc <$> timeZone)
197
193
198utc :: Local.TimeZone
194utc :: Local.TimeZone
199utc = Local.TimeZone 0 False ""
195utc = Local.TimeZone 0 False ""
200−
201−calendarDiffTime :: Parser CalendarDiffTime
202−calendarDiffTime = do
203− contents <- takeByteString
204− iso8601ParseM $ B8.unpack contents
src/Database/PostgreSQL/Simple/Time/Internal/Printer.hs+3−15
@@ -17,23 +17,19 @@ module Database.PostgreSQL.Simple.Time.Internal.Printer
17 , localTime
17 , localTime
18 , zonedTime
18 , zonedTime
19 , nominalDiffTime
19 , nominalDiffTime
20− , calendarDiffTime
21 ) where
20 ) where
22
21
23import Control.Arrow ((>>>))
22import Control.Arrow ((>>>))
24−import Data.ByteString.Builder (Builder, byteString, integerDec)
23+import Data.ByteString.Builder (Builder, integerDec)
25import Data.ByteString.Builder.Prim
24import Data.ByteString.Builder.Prim
26 ( liftFixedToBounded, (>$<), (>*<)
25 ( liftFixedToBounded, (>$<), (>*<)
27 , BoundedPrim, primBounded, condB, emptyB, FixedPrim, char8, int32Dec)
26 , BoundedPrim, primBounded, condB, emptyB, FixedPrim, char8, int32Dec)
28import Data.Char ( chr )
27import Data.Char ( chr )
29import Data.Int ( Int32, Int64 )
28import Data.Int ( Int32, Int64 )
30−import Data.String (fromString)
29+import Data.Time
31−import Data.Time.Compat
32 ( UTCTime(..), ZonedTime(..), LocalTime(..), NominalDiffTime
30 ( UTCTime(..), ZonedTime(..), LocalTime(..), NominalDiffTime
33 , Day, toGregorian, TimeOfDay(..), timeToTimeOfDay
31 , Day, toGregorian, TimeOfDay(..), timeToTimeOfDay
34 , TimeZone, timeZoneMinutes )
32 , TimeZone, timeZoneMinutes )
35−import Data.Time.Format.ISO8601.Compat (iso8601Show)
36−import Data.Time.LocalTime.Compat (CalendarDiffTime)
37import Database.PostgreSQL.Simple.Compat ((<>), fromPico)
33import Database.PostgreSQL.Simple.Compat ((<>), fromPico)
38import Unsafe.Coerce (unsafeCoerce)
34import Unsafe.Coerce (unsafeCoerce)
39
35
@@ -75,7 +71,7 @@ frac = condB (== 0) emptyB ((,) '.' >$< (liftB char8 >*< trunc12))
75
71
76
72
77year :: BoundedPrim Int32
73year :: BoundedPrim Int32
78−year = condB (>= 10000) int32Dec (checkBCE >$< liftB digits4)
74+year = condB (> 10000) int32Dec (checkBCE >$< liftB digits4)
79 where
75 where
80 checkBCE :: Int32 -> Int
76 checkBCE :: Int32 -> Int
81 checkBCE y
77 checkBCE y
@@ -125,11 +121,3 @@ nominalDiffTime :: NominalDiffTime -> Builder
125nominalDiffTime xy = integerDec x <> primBounded frac (abs (fromIntegral y))
121nominalDiffTime xy = integerDec x <> primBounded frac (abs (fromIntegral y))
126 where
122 where
127 (x,y) = fromPico (unsafeCoerce xy) `quotRem` 1000000000000
123 (x,y) = fromPico (unsafeCoerce xy) `quotRem` 1000000000000
128−
129−calendarDiffTime :: CalendarDiffTime -> Builder
130−calendarDiffTime = byteString
131− . fromString
132− -- from the docs: "Beware: fromString truncates multi-byte characters to octets".
133− -- However, I think this is a safe usage, because ISO8601-encoding seems restricted
134− -- to ASCII output.
135− . iso8601Show
src/Database/PostgreSQL/Simple/ToField.hs+11−33
@@ -1,6 +1,5 @@
1{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor #-}
1{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor #-}
2{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
2{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
3−{-# LANGUAGE PolyKinds #-}
4
3
5------------------------------------------------------------------------------
4------------------------------------------------------------------------------
6-- |
5-- |
@@ -23,7 +22,6 @@ module Database.PostgreSQL.Simple.ToField
23 , inQuotes
22 , inQuotes
24 ) where
23 ) where
25
24
26−import Control.Applicative (Const(Const))
27import qualified Data.Aeson as JSON
25import qualified Data.Aeson as JSON
28import Data.ByteString (ByteString)
26import Data.ByteString (ByteString)
29import Data.ByteString.Builder
27import Data.ByteString.Builder
@@ -32,12 +30,10 @@ import Data.ByteString.Builder
32 , wordDec, word8Dec, word16Dec, word32Dec, word64Dec
30 , wordDec, word8Dec, word16Dec, word32Dec, word64Dec
33 , floatDec, doubleDec
31 , floatDec, doubleDec
34 )
32 )
35−import Data.Functor.Identity (Identity(Identity))
36import Data.Int (Int8, Int16, Int32, Int64)
33import Data.Int (Int8, Int16, Int32, Int64)
37import Data.List (intersperse)
34import Data.List (intersperse)
38import Data.Monoid (mappend)
35import Data.Monoid (mappend)
39−import Data.Time.Compat (Day, TimeOfDay, LocalTime, UTCTime, ZonedTime, NominalDiffTime)
36+import Data.Time (Day, TimeOfDay, LocalTime, UTCTime, ZonedTime, NominalDiffTime)
40−import Data.Time.LocalTime.Compat (CalendarDiffTime)
41import Data.Typeable (Typeable)
37import Data.Typeable (Typeable)
42import Data.Word (Word, Word8, Word16, Word32, Word64)
38import Data.Word (Word, Word8, Word16, Word32, Word64)
43import {-# SOURCE #-} Database.PostgreSQL.Simple.ToRow
39import {-# SOURCE #-} Database.PostgreSQL.Simple.ToRow
@@ -46,8 +42,6 @@ import Database.PostgreSQL.Simple.Compat (toByteString)
46
42
47import qualified Data.ByteString as SB
43import qualified Data.ByteString as SB
48import qualified Data.ByteString.Lazy as LB
44import qualified Data.ByteString.Lazy as LB
49−import Data.CaseInsensitive (CI)
50−import qualified Data.CaseInsensitive as CI
51import qualified Data.Text as ST
45import qualified Data.Text as ST
52import qualified Data.Text.Encoding as ST
46import qualified Data.Text.Encoding as ST
53import qualified Data.Text.Lazy as LT
47import qualified Data.Text.Lazy as LT
@@ -59,7 +53,11 @@ import qualified Data.Vector as V
59import qualified Database.PostgreSQL.LibPQ as PQ
53import qualified Database.PostgreSQL.LibPQ as PQ
60import Database.PostgreSQL.Simple.Time
54import Database.PostgreSQL.Simple.Time
61import Data.Scientific (Scientific)
55import Data.Scientific (Scientific)
56+#if MIN_VERSION_scientific(0,3,0)
62import Data.Text.Lazy.Builder.Scientific (scientificBuilder)
57import Data.Text.Lazy.Builder.Scientific (scientificBuilder)
58+#else
59+import Data.Scientific (scientificBuilder)
60+#endif
63import Foreign.C.Types (CUInt(..))
61import Foreign.C.Types (CUInt(..))
64
62
65-- | How to render an element when substituting it into a query.
63-- | How to render an element when substituting it into a query.
@@ -100,14 +98,6 @@ instance ToField Action where
100 toField a = a
98 toField a = a
101 {-# INLINE toField #-}
99 {-# INLINE toField #-}
102
100
103−instance (ToField a) => ToField (Const a b) where
104− toField (Const a) = toField a
105− {-# INLINE toField #-}
106−
107−instance (ToField a) => ToField (Identity a) where
108− toField (Identity a) = toField a
109− {-# INLINE toField #-}
110−
111instance (ToField a) => ToField (Maybe a) where
101instance (ToField a) => ToField (Maybe a) where
112 toField Nothing = renderNull
102 toField Nothing = renderNull
113 toField (Just a) = toField a
103 toField (Just a) = toField a
@@ -240,15 +230,6 @@ instance ToField LT.Text where
240 toField = toField . LT.toStrict
230 toField = toField . LT.toStrict
241 {-# INLINE toField #-}
231 {-# INLINE toField #-}
242
232
243−-- | citext
244−instance ToField (CI ST.Text) where
245− toField = toField . CI.original
246− {-# INLINE toField #-}
247−
248−-- | citext
249−instance ToField (CI LT.Text) where
250− toField = toField . LT.toStrict . CI.original
251− {-# INLINE toField #-}
252
233
253instance ToField UTCTime where
234instance ToField UTCTime where
254 toField = Plain . inQuotes . utcTimeToBuilder
235 toField = Plain . inQuotes . utcTimeToBuilder
@@ -290,10 +271,6 @@ instance ToField NominalDiffTime where
290 toField = Plain . inQuotes . nominalDiffTimeToBuilder
271 toField = Plain . inQuotes . nominalDiffTimeToBuilder
291 {-# INLINE toField #-}
272 {-# INLINE toField #-}
292
273
293−instance ToField CalendarDiffTime where
294− toField = Plain . inQuotes . calendarDiffTimeToBuilder
295− {-# INLINE toField #-}
296−
297instance (ToField a) => ToField (PGArray a) where
274instance (ToField a) => ToField (PGArray a) where
298 toField pgArray =
275 toField pgArray =
299 case fromPGArray pgArray of
276 case fromPGArray pgArray of
@@ -314,13 +291,14 @@ instance ToField UUID where
314instance ToField JSON.Value where
291instance ToField JSON.Value where
315 toField = toField . JSON.encode
292 toField = toField . JSON.encode
316
293
317−-- | Convert a Haskell value to JSON using 'JSON.toEncoding'.
294+-- | Convert a Haskell value to a JSON 'JSON.Value' using
295+-- 'JSON.toJSON' and convert that to a field using 'toField'.
318--
296--
319-- This can be used as the default implementation for the 'toField'
297-- This can be used as the default implementation for the 'toField'
320-- method for Haskell types that have a JSON representation in
298-- method for Haskell types that have a JSON representation in
321-- PostgreSQL.
299-- PostgreSQL.
322toJSONField :: JSON.ToJSON a => a -> Action
300toJSONField :: JSON.ToJSON a => a -> Action
323−toJSONField = toField . JSON.encode
301+toJSONField = toField . JSON.toJSON
324
302
325-- | Surround a string with single-quote characters: \"@'@\"
303-- | Surround a string with single-quote characters: \"@'@\"
326--
304--
@@ -330,7 +308,7 @@ inQuotes b = quote `mappend` b `mappend` quote
330 where quote = char8 '\''
308 where quote = char8 '\''
331
309
332interleaveFoldr :: (a -> [b] -> [b]) -> b -> [b] -> [a] -> [b]
310interleaveFoldr :: (a -> [b] -> [b]) -> b -> [b] -> [a] -> [b]
333−interleaveFoldr f b bs' as = foldr (\a bs -> b : f a bs) bs' as
311+interleaveFoldr f b bs as = foldr (\a bs -> b : f a bs) bs as
334{-# INLINE interleaveFoldr #-}
312{-# INLINE interleaveFoldr #-}
335
313
336instance ToRow a => ToField (Values a) where
314instance ToRow a => ToField (Values a) where
@@ -377,8 +355,8 @@ instance ToRow a => ToField (Values a) where
377
355
378 typedRows :: ToRow a => [a] -> [QualifiedIdentifier] -> [Action] -> [Action]
356 typedRows :: ToRow a => [a] -> [QualifiedIdentifier] -> [Action] -> [Action]
379 typedRows [] _ _ = error funcname
357 typedRows [] _ _ = error funcname
380− typedRows (val:vals) typs rest =
358+ typedRows (val:vals) types rest =
381− typedRow (toRow val) typs (multiRows vals rest)
359+ typedRow (toRow val) types (multiRows vals rest)
382
360
383 untypedRows :: ToRow a => [a] -> [Action] -> [Action]
361 untypedRows :: ToRow a => [a] -> [Action] -> [Action]
384 untypedRows [] _ = error funcname
362 untypedRows [] _ = error funcname
src/Database/PostgreSQL/Simple/ToRow.hs−106
@@ -30,22 +30,6 @@ import GHC.Generics
30--
30--
31-- Instances should use the 'toField' method of the 'ToField' class
31-- Instances should use the 'toField' method of the 'ToField' class
32-- to perform conversion of each element of the collection.
32-- to perform conversion of each element of the collection.
33−--
34−-- You can derive 'ToRow' for your data type using GHC generics, like this:
35−--
36−-- @
37−-- \{-# LANGUAGE DeriveAnyClass \#-}
38−-- \{-# LANGUAGE DeriveGeneric \#-}
39−--
40−-- import "GHC.Generics" ('GHC.Generics.Generic')
41−-- import "Database.PostgreSQL.Simple" ('ToRow')
42−--
43−-- data User = User { name :: String, fileQuota :: Int }
44−-- deriving ('GHC.Generics.Generic', 'ToRow')
45−-- @
46−--
47−-- Note that this only works for product types (e.g. records) and does not
48−-- support sum types or recursive types.
49class ToRow a where
33class ToRow a where
50 toRow :: a -> [Action]
34 toRow :: a -> [Action]
51 default toRow :: (Generic a, GToRow (Rep a)) => a -> [Action]
35 default toRow :: (Generic a, GToRow (Rep a)) => a -> [Action]
@@ -105,96 +89,6 @@ instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
105 [toField a, toField b, toField c, toField d, toField e, toField f,
89 [toField a, toField b, toField c, toField d, toField e, toField f,
106 toField g, toField h, toField i, toField j]
90 toField g, toField h, toField i, toField j]
107
91
108−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
109− ToField g, ToField h, ToField i, ToField j, ToField k)
110− => ToRow (a,b,c,d,e,f,g,h,i,j,k) where
111− toRow (a,b,c,d,e,f,g,h,i,j,k) =
112− [toField a, toField b, toField c, toField d, toField e, toField f,
113− toField g, toField h, toField i, toField j, toField k]
114−
115−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
116− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l)
117− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l) where
118− toRow (a,b,c,d,e,f,g,h,i,j,k,l) =
119− [toField a, toField b, toField c, toField d, toField e, toField f,
120− toField g, toField h, toField i, toField j, toField k, toField l]
121−
122−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
123− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
124− ToField m)
125− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m) where
126− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m) =
127− [toField a, toField b, toField c, toField d, toField e, toField f,
128− toField g, toField h, toField i, toField j, toField k, toField l,
129− toField m]
130−
131−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
132− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
133− ToField m, ToField n)
134− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where
135− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n) =
136− [toField a, toField b, toField c, toField d, toField e, toField f,
137− toField g, toField h, toField i, toField j, toField k, toField l,
138− toField m, toField n]
139−
140−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
141− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
142− ToField m, ToField n, ToField o)
143− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where
144− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) =
145− [toField a, toField b, toField c, toField d, toField e, toField f,
146− toField g, toField h, toField i, toField j, toField k, toField l,
147− toField m, toField n, toField o]
148−
149−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
150− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
151− ToField m, ToField n, ToField o, ToField p)
152− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) where
153− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) =
154− [toField a, toField b, toField c, toField d, toField e, toField f,
155− toField g, toField h, toField i, toField j, toField k, toField l,
156− toField m, toField n, toField o, toField p]
157−
158−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
159− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
160− ToField m, ToField n, ToField o, ToField p, ToField q)
161− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) where
162− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) =
163− [toField a, toField b, toField c, toField d, toField e, toField f,
164− toField g, toField h, toField i, toField j, toField k, toField l,
165− toField m, toField n, toField o, toField p, toField q]
166−
167−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
168− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
169− ToField m, ToField n, ToField o, ToField p, ToField q, ToField r)
170− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) where
171− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) =
172− [toField a, toField b, toField c, toField d, toField e, toField f,
173− toField g, toField h, toField i, toField j, toField k, toField l,
174− toField m, toField n, toField o, toField p, toField q, toField r]
175−
176−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
177− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
178− ToField m, ToField n, ToField o, ToField p, ToField q, ToField r,
179− ToField s)
180− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) where
181− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) =
182− [toField a, toField b, toField c, toField d, toField e, toField f,
183− toField g, toField h, toField i, toField j, toField k, toField l,
184− toField m, toField n, toField o, toField p, toField q, toField r,
185− toField s]
186−
187−instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
188− ToField g, ToField h, ToField i, ToField j, ToField k, ToField l,
189− ToField m, ToField n, ToField o, ToField p, ToField q, ToField r,
190− ToField s, ToField t)
191− => ToRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) where
192− toRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) =
193− [toField a, toField b, toField c, toField d, toField e, toField f,
194− toField g, toField h, toField i, toField j, toField k, toField l,
195− toField m, toField n, toField o, toField p, toField q, toField r,
196− toField s, toField t]
197−
198instance (ToField a) => ToRow [a] where
92instance (ToField a) => ToRow [a] where
199 toRow = map toField
93 toRow = map toField
200
94
src/Database/PostgreSQL/Simple/Transaction.hs+17−35
@@ -1,14 +1,4 @@
1−{-# LANGUAGE RecordWildCards, ScopedTypeVariables #-}
1+{-# LANGUAGE RecordWildCards #-}
2−
3−------------------------------------------------------------------------------
4−-- |
5−-- Module: Database.PostgreSQL.Simple.Transaction
6−-- Copyright: (c) 2011-2013 Leon P Smith
7−-- (c) 2013 Joey Adams
8−-- License: BSD3
9−-- Maintainer: Leon P Smith <leon@melding-monads.com>
10−--
11−------------------------------------------------------------------------------
12
2
13module Database.PostgreSQL.Simple.Transaction
3module Database.PostgreSQL.Simple.Transaction
14 (
4 (
@@ -17,7 +7,6 @@ module Database.PostgreSQL.Simple.Transaction
17 , withTransactionLevel
7 , withTransactionLevel
18 , withTransactionMode
8 , withTransactionMode
19 , withTransactionModeRetry
9 , withTransactionModeRetry
20− , withTransactionModeRetry'
21 , withTransactionSerializable
10 , withTransactionSerializable
22 , TransactionMode(..)
11 , TransactionMode(..)
23 , IsolationLevel(..)
12 , IsolationLevel(..)
@@ -56,7 +45,7 @@ import Database.PostgreSQL.Simple.Compat (mask, (<>))
56
45
57-- | Of the four isolation levels defined by the SQL standard,
46-- | Of the four isolation levels defined by the SQL standard,
58-- these are the three levels distinguished by PostgreSQL as of version 9.0.
47-- these are the three levels distinguished by PostgreSQL as of version 9.0.
59−-- See <https://www.postgresql.org/docs/9.5/static/transaction-iso.html>
48+-- See <http://www.postgresql.org/docs/9.1/static/transaction-iso.html>
60-- for more information. Note that prior to PostgreSQL 9.0, 'RepeatableRead'
49-- for more information. Note that prior to PostgreSQL 9.0, 'RepeatableRead'
61-- was equivalent to 'Serializable'.
50-- was equivalent to 'Serializable'.
62
51
@@ -143,48 +132,41 @@ withTransactionMode :: TransactionMode -> Connection -> IO a -> IO a
143withTransactionMode mode conn act =
132withTransactionMode mode conn act =
144 mask $ \restore -> do
133 mask $ \restore -> do
145 beginMode mode conn
134 beginMode mode conn
146− r <- restore act `E.onException` rollback_ conn
135+ r <- restore act `E.onException` rollback conn
147 commit conn
136 commit conn
148 return r
137 return r
149
138
150−-- | 'withTransactionModeRetry'' but with the exception type pinned to 'SqlError'.
151−withTransactionModeRetry :: TransactionMode -> (SqlError -> Bool) -> Connection -> IO a -> IO a
152−withTransactionModeRetry = withTransactionModeRetry'
153−
154-- | Like 'withTransactionMode', but also takes a custom callback to
139-- | Like 'withTransactionMode', but also takes a custom callback to
155−-- determine if a transaction should be retried if an exception occurs.
140+-- determine if a transaction should be retried if an 'SqlError' occurs.
156−-- If the callback returns 'True', then the transaction will be retried.
141+-- If the callback returns True, then the transaction will be retried.
157−-- If the callback returns 'False', or an exception other than an @e@
142+-- If the callback returns False, or an exception other than an 'SqlError'
158-- occurs then the transaction will be rolled back and the exception rethrown.
143-- occurs then the transaction will be rolled back and the exception rethrown.
159--
144--
160-- This is used to implement 'withTransactionSerializable'.
145-- This is used to implement 'withTransactionSerializable'.
161−withTransactionModeRetry' :: forall a e. E.Exception e => TransactionMode -> (e -> Bool) -> Connection -> IO a -> IO a
146+withTransactionModeRetry :: TransactionMode -> (SqlError -> Bool) -> Connection -> IO a -> IO a
162−withTransactionModeRetry' mode shouldRetry conn act =
147+withTransactionModeRetry mode shouldRetry conn act =
163 mask $ \restore ->
148 mask $ \restore ->
164 retryLoop $ E.try $ do
149 retryLoop $ E.try $ do
165− a <- restore act `E.onException` rollback_ conn
150+ a <- restore act
166 commit conn
151 commit conn
167 return a
152 return a
168 where
153 where
169− retryLoop :: IO (Either e a) -> IO a
154+ retryLoop :: IO (Either E.SomeException a) -> IO a
170 retryLoop act' = do
155 retryLoop act' = do
171 beginMode mode conn
156 beginMode mode conn
172 r <- act'
157 r <- act'
173 case r of
158 case r of
174− Left e ->
159+ Left e -> do
160+ rollback conn
175− case shouldRetry e of
161+ case fmap shouldRetry (E.fromException e) of
176− True -> retryLoop act'
162+ Just True -> retryLoop act'
177− False -> E.throwIO e
163+ _ -> E.throwIO e
178 Right a ->
164 Right a ->
179 return a
165 return a
180
166
181-- | Rollback a transaction.
167-- | Rollback a transaction.
182rollback :: Connection -> IO ()
168rollback :: Connection -> IO ()
183−rollback conn = execute_ conn "ROLLBACK" >> return ()
169+rollback conn = execute_ conn "ABORT" >> return ()
184−
185−-- | Rollback a transaction, ignoring any @IOErrors@
186−rollback_ :: Connection -> IO ()
187−rollback_ conn = rollback conn `E.catch` \(_ :: IOError) -> return ()
188
170
189-- | Commit a transaction.
171-- | Commit a transaction.
190commit :: Connection -> IO ()
172commit :: Connection -> IO ()
@@ -221,7 +203,7 @@ beginMode mode conn = do
221-- be used inside of a transaction, and provides a sort of
203-- be used inside of a transaction, and provides a sort of
222-- \"nested transaction\".
204-- \"nested transaction\".
223--
205--
224−-- See <https://www.postgresql.org/docs/9.5/static/sql-savepoint.html>
206+-- See <http://www.postgresql.org/docs/current/static/sql-savepoint.html>
225withSavepoint :: Connection -> IO a -> IO a
207withSavepoint :: Connection -> IO a -> IO a
226withSavepoint conn body =
208withSavepoint conn body =
227 mask $ \restore -> do
209 mask $ \restore -> do
src/Database/PostgreSQL/Simple/TypeInfo.hs+9−9
@@ -50,21 +50,21 @@ import Database.PostgreSQL.Simple.TypeInfo.Static
50-- in the connections's cache.
50-- in the connections's cache.
51
51
52getTypeInfo :: Connection -> PQ.Oid -> IO TypeInfo
52getTypeInfo :: Connection -> PQ.Oid -> IO TypeInfo
53−getTypeInfo conn@Connection{..} oid' =
53+getTypeInfo conn@Connection{..} oid =
54− case staticTypeInfo oid' of
54+ case staticTypeInfo oid of
55− Just name' -> return name'
55+ Just name -> return name
56− Nothing -> modifyMVar connectionObjects $ getTypeInfo' conn oid'
56+ Nothing -> modifyMVar connectionObjects $ getTypeInfo' conn oid
57
57
58getTypeInfo' :: Connection -> PQ.Oid -> TypeInfoCache
58getTypeInfo' :: Connection -> PQ.Oid -> TypeInfoCache
59 -> IO (TypeInfoCache, TypeInfo)
59 -> IO (TypeInfoCache, TypeInfo)
60−getTypeInfo' conn oid' oidmap =
60+getTypeInfo' conn oid oidmap =
61− case IntMap.lookup (oid2int oid') oidmap of
61+ case IntMap.lookup (oid2int oid) oidmap of
62 Just typeinfo -> return (oidmap, typeinfo)
62 Just typeinfo -> return (oidmap, typeinfo)
63 Nothing -> do
63 Nothing -> do
64 names <- query conn "SELECT oid, typcategory, typdelim, typname,\
64 names <- query conn "SELECT oid, typcategory, typdelim, typname,\
65 \ typelem, typrelid\
65 \ typelem, typrelid\
66 \ FROM pg_type WHERE oid = ?"
66 \ FROM pg_type WHERE oid = ?"
67− (Only oid')
67+ (Only oid)
68 (oidmap', typeInfo) <-
68 (oidmap', typeInfo) <-
69 case names of
69 case names of
70 [] -> return $ throw (fatalError "invalid type oid")
70 [] -> return $ throw (fatalError "invalid type oid")
@@ -78,7 +78,7 @@ getTypeInfo' conn oid' oidmap =
78 rngsubtypeOids <- query conn "SELECT rngsubtype\
78 rngsubtypeOids <- query conn "SELECT rngsubtype\
79 \ FROM pg_range\
79 \ FROM pg_range\
80 \ WHERE rngtypid = ?"
80 \ WHERE rngtypid = ?"
81− (Only oid')
81+ (Only oid)
82 case rngsubtypeOids of
82 case rngsubtypeOids of
83 [Only rngsubtype_] -> do
83 [Only rngsubtype_] -> do
84 (oidmap', rngsubtype) <-
84 (oidmap', rngsubtype) <-
@@ -104,7 +104,7 @@ getTypeInfo' conn oid' oidmap =
104 _ -> fail "typename query returned more than one result"
104 _ -> fail "typename query returned more than one result"
105 -- oid is a primary key, so the query should
105 -- oid is a primary key, so the query should
106 -- never return more than one result
106 -- never return more than one result
107− let !oidmap'' = IntMap.insert (oid2int oid') typeInfo oidmap'
107+ let !oidmap'' = IntMap.insert (oid2int oid) typeInfo oidmap'
108 return $! (oidmap'', typeInfo)
108 return $! (oidmap'', typeInfo)
109
109
110getAttInfos :: Connection -> [(B.ByteString, PQ.Oid)] -> TypeInfoCache
110getAttInfos :: Connection -> [(B.ByteString, PQ.Oid)] -> TypeInfoCache
src/Database/PostgreSQL/Simple/TypeInfo/Macro.hs+3−9
@@ -1,9 +1,4 @@
1−{-# LANGUAGE CPP #-}
2−#if __GLASGOW_HASKELL__ >= 800
3−{-# LANGUAGE TemplateHaskellQuotes #-}
4−#else
5{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
6−#endif
7
2
8------------------------------------------------------------------------------
3------------------------------------------------------------------------------
9-- |
4-- |
@@ -27,12 +22,11 @@ import Database.PostgreSQL.Simple.TypeInfo.Static
27import Database.PostgreSQL.Simple.Types (Oid(..))
22import Database.PostgreSQL.Simple.Types (Oid(..))
28import Language.Haskell.TH
23import Language.Haskell.TH
29
24
25+
30-- | Returns an expression that has type @'Oid' -> 'Bool'@, true if the
26-- | Returns an expression that has type @'Oid' -> 'Bool'@, true if the
31-- oid is equal to any one of the 'typoid's of the given 'TypeInfo's.
27-- oid is equal to any one of the 'typoid's of the given 'TypeInfo's.
32mkCompats :: [TypeInfo] -> ExpQ
28mkCompats :: [TypeInfo] -> ExpQ
33−mkCompats tys = do
34− x <- newName "x"
35− lamE [conP 'Oid [varP x]] $ caseE (varE x) (map alt tys ++ [catchAll])
29+mkCompats tys = [| \(Oid x) -> $(caseE [| x |] (map alt tys ++ [catchAll])) |]
36 where
30 where
37 alt :: TypeInfo -> MatchQ
31 alt :: TypeInfo -> MatchQ
38 alt ty = match (inlineTypoidP ty) (normalB [| True |]) []
32 alt ty = match (inlineTypoidP ty) (normalB [| True |]) []
@@ -44,7 +38,7 @@ mkCompats tys = do
44-- Returns an expression of type 'Oid'. Useful because GHC tends
38-- Returns an expression of type 'Oid'. Useful because GHC tends
45-- not to fold constants.
39-- not to fold constants.
46inlineTypoid :: TypeInfo -> ExpQ
40inlineTypoid :: TypeInfo -> ExpQ
47−inlineTypoid ty = conE 'Oid `appE` litE (getTypoid ty)
41+inlineTypoid ty = [| Oid $(litE (getTypoid ty)) |]
48
42
49inlineTypoidP :: TypeInfo -> PatQ
43inlineTypoidP :: TypeInfo -> PatQ
50inlineTypoidP ty = litP (getTypoid ty)
44inlineTypoidP ty = litP (getTypoid ty)
src/Database/PostgreSQL/Simple/TypeInfo/Static.hs+114−684
@@ -19,233 +19,119 @@ module Database.PostgreSQL.Simple.TypeInfo.Static
19 ( TypeInfo(..)
19 ( TypeInfo(..)
20 , staticTypeInfo
20 , staticTypeInfo
21 , bool
21 , bool
22− , boolOid
23 , bytea
22 , bytea
24− , byteaOid
25 , char
23 , char
26− , charOid
27 , name
24 , name
28− , nameOid
29 , int8
25 , int8
30− , int8Oid
31 , int2
26 , int2
32− , int2Oid
33 , int4
27 , int4
34− , int4Oid
35 , regproc
28 , regproc
36− , regprocOid
37 , text
29 , text
38− , textOid
39 , oid
30 , oid
40− , oidOid
41 , tid
31 , tid
42− , tidOid
43 , xid
32 , xid
44− , xidOid
45 , cid
33 , cid
46− , cidOid
47 , xml
34 , xml
48− , xmlOid
49 , point
35 , point
50− , pointOid
51 , lseg
36 , lseg
52− , lsegOid
53 , path
37 , path
54− , pathOid
55 , box
38 , box
56− , boxOid
57 , polygon
39 , polygon
58− , polygonOid
59 , line
40 , line
60− , lineOid
61 , cidr
41 , cidr
62− , cidrOid
63 , float4
42 , float4
64− , float4Oid
65 , float8
43 , float8
66− , float8Oid
67 , unknown
44 , unknown
68− , unknownOid
69 , circle
45 , circle
70− , circleOid
71 , money
46 , money
72− , moneyOid
73 , macaddr
47 , macaddr
74− , macaddrOid
75 , inet
48 , inet
76− , inetOid
77 , bpchar
49 , bpchar
78− , bpcharOid
79 , varchar
50 , varchar
80− , varcharOid
81 , date
51 , date
82− , dateOid
83 , time
52 , time
84− , timeOid
85 , timestamp
53 , timestamp
86− , timestampOid
87 , timestamptz
54 , timestamptz
88− , timestamptzOid
89 , interval
55 , interval
90− , intervalOid
91 , timetz
56 , timetz
92− , timetzOid
93 , bit
57 , bit
94− , bitOid
95 , varbit
58 , varbit
96− , varbitOid
97 , numeric
59 , numeric
98− , numericOid
99 , refcursor
60 , refcursor
100− , refcursorOid
101 , record
61 , record
102− , recordOid
103 , void
62 , void
104− , voidOid
105 , array_record
63 , array_record
106− , array_recordOid
107 , regprocedure
64 , regprocedure
108− , regprocedureOid
109 , regoper
65 , regoper
110− , regoperOid
111 , regoperator
66 , regoperator
112− , regoperatorOid
113 , regclass
67 , regclass
114− , regclassOid
115 , regtype
68 , regtype
116− , regtypeOid
117 , uuid
69 , uuid
118− , uuidOid
119 , json
70 , json
120− , jsonOid
121 , jsonb
71 , jsonb
122− , jsonbOid
123 , int2vector
72 , int2vector
124− , int2vectorOid
125 , oidvector
73 , oidvector
126− , oidvectorOid
127 , array_xml
74 , array_xml
128− , array_xmlOid
129 , array_json
75 , array_json
130− , array_jsonOid
131 , array_line
76 , array_line
132− , array_lineOid
133 , array_cidr
77 , array_cidr
134− , array_cidrOid
135 , array_circle
78 , array_circle
136− , array_circleOid
137 , array_money
79 , array_money
138− , array_moneyOid
139 , array_bool
80 , array_bool
140− , array_boolOid
141 , array_bytea
81 , array_bytea
142− , array_byteaOid
143 , array_char
82 , array_char
144− , array_charOid
145 , array_name
83 , array_name
146− , array_nameOid
147 , array_int2
84 , array_int2
148− , array_int2Oid
149 , array_int2vector
85 , array_int2vector
150− , array_int2vectorOid
151 , array_int4
86 , array_int4
152− , array_int4Oid
153 , array_regproc
87 , array_regproc
154− , array_regprocOid
155 , array_text
88 , array_text
156− , array_textOid
157 , array_tid
89 , array_tid
158− , array_tidOid
159 , array_xid
90 , array_xid
160− , array_xidOid
161 , array_cid
91 , array_cid
162− , array_cidOid
163 , array_oidvector
92 , array_oidvector
164− , array_oidvectorOid
165 , array_bpchar
93 , array_bpchar
166− , array_bpcharOid
167 , array_varchar
94 , array_varchar
168− , array_varcharOid
169 , array_int8
95 , array_int8
170− , array_int8Oid
171 , array_point
96 , array_point
172− , array_pointOid
173 , array_lseg
97 , array_lseg
174− , array_lsegOid
175 , array_path
98 , array_path
176− , array_pathOid
177 , array_box
99 , array_box
178− , array_boxOid
179 , array_float4
100 , array_float4
180− , array_float4Oid
181 , array_float8
101 , array_float8
182− , array_float8Oid
183 , array_polygon
102 , array_polygon
184− , array_polygonOid
185 , array_oid
103 , array_oid
186− , array_oidOid
187 , array_macaddr
104 , array_macaddr
188− , array_macaddrOid
189 , array_inet
105 , array_inet
190− , array_inetOid
191 , array_timestamp
106 , array_timestamp
192− , array_timestampOid
193 , array_date
107 , array_date
194− , array_dateOid
195 , array_time
108 , array_time
196− , array_timeOid
197 , array_timestamptz
109 , array_timestamptz
198− , array_timestamptzOid
199 , array_interval
110 , array_interval
200− , array_intervalOid
201 , array_numeric
111 , array_numeric
202− , array_numericOid
203 , array_timetz
112 , array_timetz
204− , array_timetzOid
205 , array_bit
113 , array_bit
206− , array_bitOid
207 , array_varbit
114 , array_varbit
208− , array_varbitOid
209 , array_refcursor
115 , array_refcursor
210− , array_refcursorOid
211 , array_regprocedure
116 , array_regprocedure
212− , array_regprocedureOid
213 , array_regoper
117 , array_regoper
214− , array_regoperOid
215 , array_regoperator
118 , array_regoperator
216− , array_regoperatorOid
217 , array_regclass
119 , array_regclass
218− , array_regclassOid
219 , array_regtype
120 , array_regtype
220− , array_regtypeOid
221 , array_uuid
121 , array_uuid
222− , array_uuidOid
223 , array_jsonb
122 , array_jsonb
224− , array_jsonbOid
225 , int4range
123 , int4range
226− , int4rangeOid
227 , _int4range
124 , _int4range
228− , _int4rangeOid
229 , numrange
125 , numrange
230− , numrangeOid
231 , _numrange
126 , _numrange
232− , _numrangeOid
233 , tsrange
127 , tsrange
234− , tsrangeOid
235 , _tsrange
128 , _tsrange
236− , _tsrangeOid
237 , tstzrange
129 , tstzrange
238− , tstzrangeOid
239 , _tstzrange
130 , _tstzrange
240− , _tstzrangeOid
241 , daterange
131 , daterange
242− , daterangeOid
243 , _daterange
132 , _daterange
244− , _daterangeOid
245 , int8range
133 , int8range
246− , int8rangeOid
247 , _int8range
134 , _int8range
248− , _int8rangeOid
249 ) where
135 ) where
250
136
251import Database.PostgreSQL.LibPQ (Oid(..))
137import Database.PostgreSQL.LibPQ (Oid(..))
@@ -371,1432 +257,976 @@ staticTypeInfo (Oid x) = case x of
371
257
372bool :: TypeInfo
258bool :: TypeInfo
373bool = Basic {
259bool = Basic {
374− typoid = boolOid,
260+ typoid = Oid 16,
375 typcategory = 'B',
261 typcategory = 'B',
376 typdelim = ',',
262 typdelim = ',',
377 typname = "bool"
263 typname = "bool"
378 }
264 }
379
265
380−boolOid :: Oid
381−boolOid = Oid 16
382−{-# INLINE boolOid #-}
383−
384bytea :: TypeInfo
266bytea :: TypeInfo
385bytea = Basic {
267bytea = Basic {
386− typoid = byteaOid,
268+ typoid = Oid 17,
387 typcategory = 'U',
269 typcategory = 'U',
388 typdelim = ',',
270 typdelim = ',',
389 typname = "bytea"
271 typname = "bytea"
390 }
272 }
391
273
392−byteaOid :: Oid
393−byteaOid = Oid 17
394−{-# INLINE byteaOid #-}
395−
396char :: TypeInfo
274char :: TypeInfo
397char = Basic {
275char = Basic {
398− typoid = charOid,
276+ typoid = Oid 18,
399 typcategory = 'S',
277 typcategory = 'S',
400 typdelim = ',',
278 typdelim = ',',
401 typname = "char"
279 typname = "char"
402 }
280 }
403
281
404−charOid :: Oid
405−charOid = Oid 18
406−{-# INLINE charOid #-}
407−
408name :: TypeInfo
282name :: TypeInfo
409name = Basic {
283name = Basic {
410− typoid = nameOid,
284+ typoid = Oid 19,
411 typcategory = 'S',
285 typcategory = 'S',
412 typdelim = ',',
286 typdelim = ',',
413 typname = "name"
287 typname = "name"
414 }
288 }
415
289
416−nameOid :: Oid
417−nameOid = Oid 19
418−{-# INLINE nameOid #-}
419−
420int8 :: TypeInfo
290int8 :: TypeInfo
421int8 = Basic {
291int8 = Basic {
422− typoid = int8Oid,
292+ typoid = Oid 20,
423 typcategory = 'N',
293 typcategory = 'N',
424 typdelim = ',',
294 typdelim = ',',
425 typname = "int8"
295 typname = "int8"
426 }
296 }
427
297
428−int8Oid :: Oid
429−int8Oid = Oid 20
430−{-# INLINE int8Oid #-}
431−
432int2 :: TypeInfo
298int2 :: TypeInfo
433int2 = Basic {
299int2 = Basic {
434− typoid = int2Oid,
300+ typoid = Oid 21,
435 typcategory = 'N',
301 typcategory = 'N',
436 typdelim = ',',
302 typdelim = ',',
437 typname = "int2"
303 typname = "int2"
438 }
304 }
439
305
440−int2Oid :: Oid
441−int2Oid = Oid 21
442−{-# INLINE int2Oid #-}
443−
444int4 :: TypeInfo
306int4 :: TypeInfo
445int4 = Basic {
307int4 = Basic {
446− typoid = int4Oid,
308+ typoid = Oid 23,
447 typcategory = 'N',
309 typcategory = 'N',
448 typdelim = ',',
310 typdelim = ',',
449 typname = "int4"
311 typname = "int4"
450 }
312 }
451
313
452−int4Oid :: Oid
453−int4Oid = Oid 23
454−{-# INLINE int4Oid #-}
455−
456regproc :: TypeInfo
314regproc :: TypeInfo
457regproc = Basic {
315regproc = Basic {
458− typoid = regprocOid,
316+ typoid = Oid 24,
459 typcategory = 'N',
317 typcategory = 'N',
460 typdelim = ',',
318 typdelim = ',',
461 typname = "regproc"
319 typname = "regproc"
462 }
320 }
463
321
464−regprocOid :: Oid
465−regprocOid = Oid 24
466−{-# INLINE regprocOid #-}
467−
468text :: TypeInfo
322text :: TypeInfo
469text = Basic {
323text = Basic {
470− typoid = textOid,
324+ typoid = Oid 25,
471 typcategory = 'S',
325 typcategory = 'S',
472 typdelim = ',',
326 typdelim = ',',
473 typname = "text"
327 typname = "text"
474 }
328 }
475
329
476−textOid :: Oid
477−textOid = Oid 25
478−{-# INLINE textOid #-}
479−
480oid :: TypeInfo
330oid :: TypeInfo
481oid = Basic {
331oid = Basic {
482− typoid = oidOid,
332+ typoid = Oid 26,
483 typcategory = 'N',
333 typcategory = 'N',
484 typdelim = ',',
334 typdelim = ',',
485 typname = "oid"
335 typname = "oid"
486 }
336 }
487
337
488−oidOid :: Oid
489−oidOid = Oid 26
490−{-# INLINE oidOid #-}
491−
492tid :: TypeInfo
338tid :: TypeInfo
493tid = Basic {
339tid = Basic {
494− typoid = tidOid,
340+ typoid = Oid 27,
495 typcategory = 'U',
341 typcategory = 'U',
496 typdelim = ',',
342 typdelim = ',',
497 typname = "tid"
343 typname = "tid"
498 }
344 }
499
345
500−tidOid :: Oid
501−tidOid = Oid 27
502−{-# INLINE tidOid #-}
503−
504xid :: TypeInfo
346xid :: TypeInfo
505xid = Basic {
347xid = Basic {
506− typoid = xidOid,
348+ typoid = Oid 28,
507 typcategory = 'U',
349 typcategory = 'U',
508 typdelim = ',',
350 typdelim = ',',
509 typname = "xid"
351 typname = "xid"
510 }
352 }
511
353
512−xidOid :: Oid
513−xidOid = Oid 28
514−{-# INLINE xidOid #-}
515−
516cid :: TypeInfo
354cid :: TypeInfo
517cid = Basic {
355cid = Basic {
518− typoid = cidOid,
356+ typoid = Oid 29,
519 typcategory = 'U',
357 typcategory = 'U',
520 typdelim = ',',
358 typdelim = ',',
521 typname = "cid"
359 typname = "cid"
522 }
360 }
523
361
524−cidOid :: Oid
525−cidOid = Oid 29
526−{-# INLINE cidOid #-}
527−
528xml :: TypeInfo
362xml :: TypeInfo
529xml = Basic {
363xml = Basic {
530− typoid = xmlOid,
364+ typoid = Oid 142,
531 typcategory = 'U',
365 typcategory = 'U',
532 typdelim = ',',
366 typdelim = ',',
533 typname = "xml"
367 typname = "xml"
534 }
368 }
535
369
536−xmlOid :: Oid
537−xmlOid = Oid 142
538−{-# INLINE xmlOid #-}
539−
540point :: TypeInfo
370point :: TypeInfo
541point = Basic {
371point = Basic {
542− typoid = pointOid,
372+ typoid = Oid 600,
543 typcategory = 'G',
373 typcategory = 'G',
544 typdelim = ',',
374 typdelim = ',',
545 typname = "point"
375 typname = "point"
546 }
376 }
547
377
548−pointOid :: Oid
549−pointOid = Oid 600
550−{-# INLINE pointOid #-}
551−
552lseg :: TypeInfo
378lseg :: TypeInfo
553lseg = Basic {
379lseg = Basic {
554− typoid = lsegOid,
380+ typoid = Oid 601,
555 typcategory = 'G',
381 typcategory = 'G',
556 typdelim = ',',
382 typdelim = ',',
557 typname = "lseg"
383 typname = "lseg"
558 }
384 }
559
385
560−lsegOid :: Oid
561−lsegOid = Oid 601
562−{-# INLINE lsegOid #-}
563−
564path :: TypeInfo
386path :: TypeInfo
565path = Basic {
387path = Basic {
566− typoid = pathOid,
388+ typoid = Oid 602,
567 typcategory = 'G',
389 typcategory = 'G',
568 typdelim = ',',
390 typdelim = ',',
569 typname = "path"
391 typname = "path"
570 }
392 }
571
393
572−pathOid :: Oid
573−pathOid = Oid 602
574−{-# INLINE pathOid #-}
575−
576box :: TypeInfo
394box :: TypeInfo
577box = Basic {
395box = Basic {
578− typoid = boxOid,
396+ typoid = Oid 603,
579 typcategory = 'G',
397 typcategory = 'G',
580 typdelim = ';',
398 typdelim = ';',
581 typname = "box"
399 typname = "box"
582 }
400 }
583
401
584−boxOid :: Oid
585−boxOid = Oid 603
586−{-# INLINE boxOid #-}
587−
588polygon :: TypeInfo
402polygon :: TypeInfo
589polygon = Basic {
403polygon = Basic {
590− typoid = polygonOid,
404+ typoid = Oid 604,
591 typcategory = 'G',
405 typcategory = 'G',
592 typdelim = ',',
406 typdelim = ',',
593 typname = "polygon"
407 typname = "polygon"
594 }
408 }
595
409
596−polygonOid :: Oid
597−polygonOid = Oid 604
598−{-# INLINE polygonOid #-}
599−
600line :: TypeInfo
410line :: TypeInfo
601line = Basic {
411line = Basic {
602− typoid = lineOid,
412+ typoid = Oid 628,
603 typcategory = 'G',
413 typcategory = 'G',
604 typdelim = ',',
414 typdelim = ',',
605 typname = "line"
415 typname = "line"
606 }
416 }
607
417
608−lineOid :: Oid
609−lineOid = Oid 628
610−{-# INLINE lineOid #-}
611−
612cidr :: TypeInfo
418cidr :: TypeInfo
613cidr = Basic {
419cidr = Basic {
614− typoid = cidrOid,
420+ typoid = Oid 650,
615 typcategory = 'I',
421 typcategory = 'I',
616 typdelim = ',',
422 typdelim = ',',
617 typname = "cidr"
423 typname = "cidr"
618 }
424 }
619
425
620−cidrOid :: Oid
621−cidrOid = Oid 650
622−{-# INLINE cidrOid #-}
623−
624float4 :: TypeInfo
426float4 :: TypeInfo
625float4 = Basic {
427float4 = Basic {
626− typoid = float4Oid,
428+ typoid = Oid 700,
627 typcategory = 'N',
429 typcategory = 'N',
628 typdelim = ',',
430 typdelim = ',',
629 typname = "float4"
431 typname = "float4"
630 }
432 }
631
433
632−float4Oid :: Oid
633−float4Oid = Oid 700
634−{-# INLINE float4Oid #-}
635−
636float8 :: TypeInfo
434float8 :: TypeInfo
637float8 = Basic {
435float8 = Basic {
638− typoid = float8Oid,
436+ typoid = Oid 701,
639 typcategory = 'N',
437 typcategory = 'N',
640 typdelim = ',',
438 typdelim = ',',
641 typname = "float8"
439 typname = "float8"
642 }
440 }
643
441
644−float8Oid :: Oid
645−float8Oid = Oid 701
646−{-# INLINE float8Oid #-}
647−
648unknown :: TypeInfo
442unknown :: TypeInfo
649unknown = Basic {
443unknown = Basic {
650− typoid = unknownOid,
444+ typoid = Oid 705,
651 typcategory = 'X',
445 typcategory = 'X',
652 typdelim = ',',
446 typdelim = ',',
653 typname = "unknown"
447 typname = "unknown"
654 }
448 }
655
449
656−unknownOid :: Oid
657−unknownOid = Oid 705
658−{-# INLINE unknownOid #-}
659−
660circle :: TypeInfo
450circle :: TypeInfo
661circle = Basic {
451circle = Basic {
662− typoid = circleOid,
452+ typoid = Oid 718,
663 typcategory = 'G',
453 typcategory = 'G',
664 typdelim = ',',
454 typdelim = ',',
665 typname = "circle"
455 typname = "circle"
666 }
456 }
667
457
668−circleOid :: Oid
669−circleOid = Oid 718
670−{-# INLINE circleOid #-}
671−
672money :: TypeInfo
458money :: TypeInfo
673money = Basic {
459money = Basic {
674− typoid = moneyOid,
460+ typoid = Oid 790,
675 typcategory = 'N',
461 typcategory = 'N',
676 typdelim = ',',
462 typdelim = ',',
677 typname = "money"
463 typname = "money"
678 }
464 }
679
465
680−moneyOid :: Oid
681−moneyOid = Oid 790
682−{-# INLINE moneyOid #-}
683−
684macaddr :: TypeInfo
466macaddr :: TypeInfo
685macaddr = Basic {
467macaddr = Basic {
686− typoid = macaddrOid,
468+ typoid = Oid 829,
687 typcategory = 'U',
469 typcategory = 'U',
688 typdelim = ',',
470 typdelim = ',',
689 typname = "macaddr"
471 typname = "macaddr"
690 }
472 }
691
473
692−macaddrOid :: Oid
693−macaddrOid = Oid 829
694−{-# INLINE macaddrOid #-}
695−
696inet :: TypeInfo
474inet :: TypeInfo
697inet = Basic {
475inet = Basic {
698− typoid = inetOid,
476+ typoid = Oid 869,
699 typcategory = 'I',
477 typcategory = 'I',
700 typdelim = ',',
478 typdelim = ',',
701 typname = "inet"
479 typname = "inet"
702 }
480 }
703
481
704−inetOid :: Oid
705−inetOid = Oid 869
706−{-# INLINE inetOid #-}
707−
708bpchar :: TypeInfo
482bpchar :: TypeInfo
709bpchar = Basic {
483bpchar = Basic {
710− typoid = bpcharOid,
484+ typoid = Oid 1042,
711 typcategory = 'S',
485 typcategory = 'S',
712 typdelim = ',',
486 typdelim = ',',
713 typname = "bpchar"
487 typname = "bpchar"
714 }
488 }
715
489
716−bpcharOid :: Oid
717−bpcharOid = Oid 1042
718−{-# INLINE bpcharOid #-}
719−
720varchar :: TypeInfo
490varchar :: TypeInfo
721varchar = Basic {
491varchar = Basic {
722− typoid = varcharOid,
492+ typoid = Oid 1043,
723 typcategory = 'S',
493 typcategory = 'S',
724 typdelim = ',',
494 typdelim = ',',
725 typname = "varchar"
495 typname = "varchar"
726 }
496 }
727
497
728−varcharOid :: Oid
729−varcharOid = Oid 1043
730−{-# INLINE varcharOid #-}
731−
732date :: TypeInfo
498date :: TypeInfo
733date = Basic {
499date = Basic {
734− typoid = dateOid,
500+ typoid = Oid 1082,
735 typcategory = 'D',
501 typcategory = 'D',
736 typdelim = ',',
502 typdelim = ',',
737 typname = "date"
503 typname = "date"
738 }
504 }
739
505
740−dateOid :: Oid
741−dateOid = Oid 1082
742−{-# INLINE dateOid #-}
743−
744time :: TypeInfo
506time :: TypeInfo
745time = Basic {
507time = Basic {
746− typoid = timeOid,
508+ typoid = Oid 1083,
747 typcategory = 'D',
509 typcategory = 'D',
748 typdelim = ',',
510 typdelim = ',',
749 typname = "time"
511 typname = "time"
750 }
512 }
751
513
752−timeOid :: Oid
753−timeOid = Oid 1083
754−{-# INLINE timeOid #-}
755−
756timestamp :: TypeInfo
514timestamp :: TypeInfo
757timestamp = Basic {
515timestamp = Basic {
758− typoid = timestampOid,
516+ typoid = Oid 1114,
759 typcategory = 'D',
517 typcategory = 'D',
760 typdelim = ',',
518 typdelim = ',',
761 typname = "timestamp"
519 typname = "timestamp"
762 }
520 }
763
521
764−timestampOid :: Oid
765−timestampOid = Oid 1114
766−{-# INLINE timestampOid #-}
767−
768timestamptz :: TypeInfo
522timestamptz :: TypeInfo
769timestamptz = Basic {
523timestamptz = Basic {
770− typoid = timestamptzOid,
524+ typoid = Oid 1184,
771 typcategory = 'D',
525 typcategory = 'D',
772 typdelim = ',',
526 typdelim = ',',
773 typname = "timestamptz"
527 typname = "timestamptz"
774 }
528 }
775
529
776−timestamptzOid :: Oid
777−timestamptzOid = Oid 1184
778−{-# INLINE timestamptzOid #-}
779−
780interval :: TypeInfo
530interval :: TypeInfo
781interval = Basic {
531interval = Basic {
782− typoid = intervalOid,
532+ typoid = Oid 1186,
783 typcategory = 'T',
533 typcategory = 'T',
784 typdelim = ',',
534 typdelim = ',',
785 typname = "interval"
535 typname = "interval"
786 }
536 }
787
537
788−intervalOid :: Oid
789−intervalOid = Oid 1186
790−{-# INLINE intervalOid #-}
791−
792timetz :: TypeInfo
538timetz :: TypeInfo
793timetz = Basic {
539timetz = Basic {
794− typoid = timetzOid,
540+ typoid = Oid 1266,
795 typcategory = 'D',
541 typcategory = 'D',
796 typdelim = ',',
542 typdelim = ',',
797 typname = "timetz"
543 typname = "timetz"
798 }
544 }
799
545
800−timetzOid :: Oid
801−timetzOid = Oid 1266
802−{-# INLINE timetzOid #-}
803−
804bit :: TypeInfo
546bit :: TypeInfo
805bit = Basic {
547bit = Basic {
806− typoid = bitOid,
548+ typoid = Oid 1560,
807 typcategory = 'V',
549 typcategory = 'V',
808 typdelim = ',',
550 typdelim = ',',
809 typname = "bit"
551 typname = "bit"
810 }
552 }
811
553
812−bitOid :: Oid
813−bitOid = Oid 1560
814−{-# INLINE bitOid #-}
815−
816varbit :: TypeInfo
554varbit :: TypeInfo
817varbit = Basic {
555varbit = Basic {
818− typoid = varbitOid,
556+ typoid = Oid 1562,
819 typcategory = 'V',
557 typcategory = 'V',
820 typdelim = ',',
558 typdelim = ',',
821 typname = "varbit"
559 typname = "varbit"
822 }
560 }
823
561
824−varbitOid :: Oid
825−varbitOid = Oid 1562
826−{-# INLINE varbitOid #-}
827−
828numeric :: TypeInfo
562numeric :: TypeInfo
829numeric = Basic {
563numeric = Basic {
830− typoid = numericOid,
564+ typoid = Oid 1700,
831 typcategory = 'N',
565 typcategory = 'N',
832 typdelim = ',',
566 typdelim = ',',
833 typname = "numeric"
567 typname = "numeric"
834 }
568 }
835
569
836−numericOid :: Oid
837−numericOid = Oid 1700
838−{-# INLINE numericOid #-}
839−
840refcursor :: TypeInfo
570refcursor :: TypeInfo
841refcursor = Basic {
571refcursor = Basic {
842− typoid = refcursorOid,
572+ typoid = Oid 1790,
843 typcategory = 'U',
573 typcategory = 'U',
844 typdelim = ',',
574 typdelim = ',',
845 typname = "refcursor"
575 typname = "refcursor"
846 }
576 }
847
577
848−refcursorOid :: Oid
849−refcursorOid = Oid 1790
850−{-# INLINE refcursorOid #-}
851−
852record :: TypeInfo
578record :: TypeInfo
853record = Basic {
579record = Basic {
854− typoid = recordOid,
580+ typoid = Oid 2249,
855 typcategory = 'P',
581 typcategory = 'P',
856 typdelim = ',',
582 typdelim = ',',
857 typname = "record"
583 typname = "record"
858 }
584 }
859
585
860−recordOid :: Oid
861−recordOid = Oid 2249
862−{-# INLINE recordOid #-}
863−
864void :: TypeInfo
586void :: TypeInfo
865void = Basic {
587void = Basic {
866− typoid = voidOid,
588+ typoid = Oid 2278,
867 typcategory = 'P',
589 typcategory = 'P',
868 typdelim = ',',
590 typdelim = ',',
869 typname = "void"
591 typname = "void"
870 }
592 }
871
593
872−voidOid :: Oid
873−voidOid = Oid 2278
874−{-# INLINE voidOid #-}
875−
876array_record :: TypeInfo
594array_record :: TypeInfo
877array_record = Array {
595array_record = Array {
878− typoid = array_recordOid,
596+ typoid = Oid 2287,
879 typcategory = 'P',
597 typcategory = 'P',
880 typdelim = ',',
598 typdelim = ',',
881 typname = "_record",
599 typname = "_record",
882 typelem = record
600 typelem = record
883 }
601 }
884
602
885−array_recordOid :: Oid
886−array_recordOid = Oid 2287
887−{-# INLINE array_recordOid #-}
888−
889regprocedure :: TypeInfo
603regprocedure :: TypeInfo
890regprocedure = Basic {
604regprocedure = Basic {
891− typoid = regprocedureOid,
605+ typoid = Oid 2202,
892 typcategory = 'N',
606 typcategory = 'N',
893 typdelim = ',',
607 typdelim = ',',
894 typname = "regprocedure"
608 typname = "regprocedure"
895 }
609 }
896
610
897−regprocedureOid :: Oid
898−regprocedureOid = Oid 2202
899−{-# INLINE regprocedureOid #-}
900−
901regoper :: TypeInfo
611regoper :: TypeInfo
902regoper = Basic {
612regoper = Basic {
903− typoid = regoperOid,
613+ typoid = Oid 2203,
904 typcategory = 'N',
614 typcategory = 'N',
905 typdelim = ',',
615 typdelim = ',',
906 typname = "regoper"
616 typname = "regoper"
907 }
617 }
908
618
909−regoperOid :: Oid
910−regoperOid = Oid 2203
911−{-# INLINE regoperOid #-}
912−
913regoperator :: TypeInfo
619regoperator :: TypeInfo
914regoperator = Basic {
620regoperator = Basic {
915− typoid = regoperatorOid,
621+ typoid = Oid 2204,
916 typcategory = 'N',
622 typcategory = 'N',
917 typdelim = ',',
623 typdelim = ',',
918 typname = "regoperator"
624 typname = "regoperator"
919 }
625 }
920
626
921−regoperatorOid :: Oid
922−regoperatorOid = Oid 2204
923−{-# INLINE regoperatorOid #-}
924−
925regclass :: TypeInfo
627regclass :: TypeInfo
926regclass = Basic {
628regclass = Basic {
927− typoid = regclassOid,
629+ typoid = Oid 2205,
928 typcategory = 'N',
630 typcategory = 'N',
929 typdelim = ',',
631 typdelim = ',',
930 typname = "regclass"
632 typname = "regclass"
931 }
633 }
932
634
933−regclassOid :: Oid
934−regclassOid = Oid 2205
935−{-# INLINE regclassOid #-}
936−
937regtype :: TypeInfo
635regtype :: TypeInfo
938regtype = Basic {
636regtype = Basic {
939− typoid = regtypeOid,
637+ typoid = Oid 2206,
940 typcategory = 'N',
638 typcategory = 'N',
941 typdelim = ',',
639 typdelim = ',',
942 typname = "regtype"
640 typname = "regtype"
943 }
641 }
944
642
945−regtypeOid :: Oid
946−regtypeOid = Oid 2206
947−{-# INLINE regtypeOid #-}
948−
949uuid :: TypeInfo
643uuid :: TypeInfo
950uuid = Basic {
644uuid = Basic {
951− typoid = uuidOid,
645+ typoid = Oid 2950,
952 typcategory = 'U',
646 typcategory = 'U',
953 typdelim = ',',
647 typdelim = ',',
954 typname = "uuid"
648 typname = "uuid"
955 }
649 }
956
650
957−uuidOid :: Oid
958−uuidOid = Oid 2950
959−{-# INLINE uuidOid #-}
960−
961json :: TypeInfo
651json :: TypeInfo
962json = Basic {
652json = Basic {
963− typoid = jsonOid,
653+ typoid = Oid 114,
964 typcategory = 'U',
654 typcategory = 'U',
965 typdelim = ',',
655 typdelim = ',',
966 typname = "json"
656 typname = "json"
967 }
657 }
968
658
969−jsonOid :: Oid
970−jsonOid = Oid 114
971−{-# INLINE jsonOid #-}
972−
973jsonb :: TypeInfo
659jsonb :: TypeInfo
974jsonb = Basic {
660jsonb = Basic {
975− typoid = jsonbOid,
661+ typoid = Oid 3802,
976 typcategory = 'U',
662 typcategory = 'U',
977 typdelim = ',',
663 typdelim = ',',
978 typname = "jsonb"
664 typname = "jsonb"
979 }
665 }
980
666
981−jsonbOid :: Oid
982−jsonbOid = Oid 3802
983−{-# INLINE jsonbOid #-}
984−
985int2vector :: TypeInfo
667int2vector :: TypeInfo
986int2vector = Array {
668int2vector = Array {
987− typoid = int2vectorOid,
669+ typoid = Oid 22,
988 typcategory = 'A',
670 typcategory = 'A',
989 typdelim = ',',
671 typdelim = ',',
990 typname = "int2vector",
672 typname = "int2vector",
991 typelem = int2
673 typelem = int2
992 }
674 }
993
675
994−int2vectorOid :: Oid
995−int2vectorOid = Oid 22
996−{-# INLINE int2vectorOid #-}
997−
998oidvector :: TypeInfo
676oidvector :: TypeInfo
999oidvector = Array {
677oidvector = Array {
1000− typoid = oidvectorOid,
678+ typoid = Oid 30,
1001 typcategory = 'A',
679 typcategory = 'A',
1002 typdelim = ',',
680 typdelim = ',',
1003 typname = "oidvector",
681 typname = "oidvector",
1004 typelem = oid
682 typelem = oid
1005 }
683 }
1006
684
1007−oidvectorOid :: Oid
1008−oidvectorOid = Oid 30
1009−{-# INLINE oidvectorOid #-}
1010−
1011array_xml :: TypeInfo
685array_xml :: TypeInfo
1012array_xml = Array {
686array_xml = Array {
1013− typoid = array_xmlOid,
687+ typoid = Oid 143,
1014 typcategory = 'A',
688 typcategory = 'A',
1015 typdelim = ',',
689 typdelim = ',',
1016 typname = "_xml",
690 typname = "_xml",
1017 typelem = xml
691 typelem = xml
1018 }
692 }
1019
693
1020−array_xmlOid :: Oid
1021−array_xmlOid = Oid 143
1022−{-# INLINE array_xmlOid #-}
1023−
1024array_json :: TypeInfo
694array_json :: TypeInfo
1025array_json = Array {
695array_json = Array {
1026− typoid = array_jsonOid,
696+ typoid = Oid 199,
1027 typcategory = 'A',
697 typcategory = 'A',
1028 typdelim = ',',
698 typdelim = ',',
1029 typname = "_json",
699 typname = "_json",
1030 typelem = json
700 typelem = json
1031 }
701 }
1032
702
1033−array_jsonOid :: Oid
1034−array_jsonOid = Oid 199
1035−{-# INLINE array_jsonOid #-}
1036−
1037array_line :: TypeInfo
703array_line :: TypeInfo
1038array_line = Array {
704array_line = Array {
1039− typoid = array_lineOid,
705+ typoid = Oid 629,
1040 typcategory = 'A',
706 typcategory = 'A',
1041 typdelim = ',',
707 typdelim = ',',
1042 typname = "_line",
708 typname = "_line",
1043 typelem = line
709 typelem = line
1044 }
710 }
1045
711
1046−array_lineOid :: Oid
1047−array_lineOid = Oid 629
1048−{-# INLINE array_lineOid #-}
1049−
1050array_cidr :: TypeInfo
712array_cidr :: TypeInfo
1051array_cidr = Array {
713array_cidr = Array {
1052− typoid = array_cidrOid,
714+ typoid = Oid 651,
1053 typcategory = 'A',
715 typcategory = 'A',
1054 typdelim = ',',
716 typdelim = ',',
1055 typname = "_cidr",
717 typname = "_cidr",
1056 typelem = cidr
718 typelem = cidr
1057 }
719 }
1058
720
1059−array_cidrOid :: Oid
1060−array_cidrOid = Oid 651
1061−{-# INLINE array_cidrOid #-}
1062−
1063array_circle :: TypeInfo
721array_circle :: TypeInfo
1064array_circle = Array {
722array_circle = Array {
1065− typoid = array_circleOid,
723+ typoid = Oid 719,
1066 typcategory = 'A',
724 typcategory = 'A',
1067 typdelim = ',',
725 typdelim = ',',
1068 typname = "_circle",
726 typname = "_circle",
1069 typelem = circle
727 typelem = circle
1070 }
728 }
1071
729
1072−array_circleOid :: Oid
1073−array_circleOid = Oid 719
1074−{-# INLINE array_circleOid #-}
1075−
1076array_money :: TypeInfo
730array_money :: TypeInfo
1077array_money = Array {
731array_money = Array {
1078− typoid = array_moneyOid,
732+ typoid = Oid 791,
1079 typcategory = 'A',
733 typcategory = 'A',
1080 typdelim = ',',
734 typdelim = ',',
1081 typname = "_money",
735 typname = "_money",
1082 typelem = money
736 typelem = money
1083 }
737 }
1084
738
1085−array_moneyOid :: Oid
1086−array_moneyOid = Oid 791
1087−{-# INLINE array_moneyOid #-}
1088−
1089array_bool :: TypeInfo
739array_bool :: TypeInfo
1090array_bool = Array {
740array_bool = Array {
1091− typoid = array_boolOid,
741+ typoid = Oid 1000,
1092 typcategory = 'A',
742 typcategory = 'A',
1093 typdelim = ',',
743 typdelim = ',',
1094 typname = "_bool",
744 typname = "_bool",
1095 typelem = bool
745 typelem = bool
1096 }
746 }
1097
747
1098−array_boolOid :: Oid
1099−array_boolOid = Oid 1000
1100−{-# INLINE array_boolOid #-}
1101−
1102array_bytea :: TypeInfo
748array_bytea :: TypeInfo
1103array_bytea = Array {
749array_bytea = Array {
1104− typoid = array_byteaOid,
750+ typoid = Oid 1001,
1105 typcategory = 'A',
751 typcategory = 'A',
1106 typdelim = ',',
752 typdelim = ',',
1107 typname = "_bytea",
753 typname = "_bytea",
1108 typelem = bytea
754 typelem = bytea
1109 }
755 }
1110
756
1111−array_byteaOid :: Oid
1112−array_byteaOid = Oid 1001
1113−{-# INLINE array_byteaOid #-}
1114−
1115array_char :: TypeInfo
757array_char :: TypeInfo
1116array_char = Array {
758array_char = Array {
1117− typoid = array_charOid,
759+ typoid = Oid 1002,
1118 typcategory = 'A',
760 typcategory = 'A',
1119 typdelim = ',',
761 typdelim = ',',
1120 typname = "_char",
762 typname = "_char",
1121 typelem = char
763 typelem = char
1122 }
764 }
1123
765
1124−array_charOid :: Oid
1125−array_charOid = Oid 1002
1126−{-# INLINE array_charOid #-}
1127−
1128array_name :: TypeInfo
766array_name :: TypeInfo
1129array_name = Array {
767array_name = Array {
1130− typoid = array_nameOid,
768+ typoid = Oid 1003,
1131 typcategory = 'A',
769 typcategory = 'A',
1132 typdelim = ',',
770 typdelim = ',',
1133 typname = "_name",
771 typname = "_name",
1134 typelem = name
772 typelem = name
1135 }
773 }
1136
774
1137−array_nameOid :: Oid
1138−array_nameOid = Oid 1003
1139−{-# INLINE array_nameOid #-}
1140−
1141array_int2 :: TypeInfo
775array_int2 :: TypeInfo
1142array_int2 = Array {
776array_int2 = Array {
1143− typoid = array_int2Oid,
777+ typoid = Oid 1005,
1144 typcategory = 'A',
778 typcategory = 'A',
1145 typdelim = ',',
779 typdelim = ',',
1146 typname = "_int2",
780 typname = "_int2",
1147 typelem = int2
781 typelem = int2
1148 }
782 }
1149
783
1150−array_int2Oid :: Oid
1151−array_int2Oid = Oid 1005
1152−{-# INLINE array_int2Oid #-}
1153−
1154array_int2vector :: TypeInfo
784array_int2vector :: TypeInfo
1155array_int2vector = Array {
785array_int2vector = Array {
1156− typoid = array_int2vectorOid,
786+ typoid = Oid 1006,
1157 typcategory = 'A',
787 typcategory = 'A',
1158 typdelim = ',',
788 typdelim = ',',
1159 typname = "_int2vector",
789 typname = "_int2vector",
1160 typelem = int2vector
790 typelem = int2vector
1161 }
791 }
1162
792
1163−array_int2vectorOid :: Oid
1164−array_int2vectorOid = Oid 1006
1165−{-# INLINE array_int2vectorOid #-}
1166−
1167array_int4 :: TypeInfo
793array_int4 :: TypeInfo
1168array_int4 = Array {
794array_int4 = Array {
1169− typoid = array_int4Oid,
795+ typoid = Oid 1007,
1170 typcategory = 'A',
796 typcategory = 'A',
1171 typdelim = ',',
797 typdelim = ',',
1172 typname = "_int4",
798 typname = "_int4",
1173 typelem = int4
799 typelem = int4
1174 }
800 }
1175
801
1176−array_int4Oid :: Oid
1177−array_int4Oid = Oid 1007
1178−{-# INLINE array_int4Oid #-}
1179−
1180array_regproc :: TypeInfo
802array_regproc :: TypeInfo
1181array_regproc = Array {
803array_regproc = Array {
1182− typoid = array_regprocOid,
804+ typoid = Oid 1008,
1183 typcategory = 'A',
805 typcategory = 'A',
1184 typdelim = ',',
806 typdelim = ',',
1185 typname = "_regproc",
807 typname = "_regproc",
1186 typelem = regproc
808 typelem = regproc
1187 }
809 }
1188
810
1189−array_regprocOid :: Oid
1190−array_regprocOid = Oid 1008
1191−{-# INLINE array_regprocOid #-}
1192−
1193array_text :: TypeInfo
811array_text :: TypeInfo
1194array_text = Array {
812array_text = Array {
1195− typoid = array_textOid,
813+ typoid = Oid 1009,
1196 typcategory = 'A',
814 typcategory = 'A',
1197 typdelim = ',',
815 typdelim = ',',
1198 typname = "_text",
816 typname = "_text",
1199 typelem = text
817 typelem = text
1200 }
818 }
1201
819
1202−array_textOid :: Oid
1203−array_textOid = Oid 1009
1204−{-# INLINE array_textOid #-}
1205−
1206array_tid :: TypeInfo
820array_tid :: TypeInfo
1207array_tid = Array {
821array_tid = Array {
1208− typoid = array_tidOid,
822+ typoid = Oid 1010,
1209 typcategory = 'A',
823 typcategory = 'A',
1210 typdelim = ',',
824 typdelim = ',',
1211 typname = "_tid",
825 typname = "_tid",
1212 typelem = tid
826 typelem = tid
1213 }
827 }
1214
828
1215−array_tidOid :: Oid
1216−array_tidOid = Oid 1010
1217−{-# INLINE array_tidOid #-}
1218−
1219array_xid :: TypeInfo
829array_xid :: TypeInfo
1220array_xid = Array {
830array_xid = Array {
1221− typoid = array_xidOid,
831+ typoid = Oid 1011,
1222 typcategory = 'A',
832 typcategory = 'A',
1223 typdelim = ',',
833 typdelim = ',',
1224 typname = "_xid",
834 typname = "_xid",
1225 typelem = xid
835 typelem = xid
1226 }
836 }
1227
837
1228−array_xidOid :: Oid
1229−array_xidOid = Oid 1011
1230−{-# INLINE array_xidOid #-}
1231−
1232array_cid :: TypeInfo
838array_cid :: TypeInfo
1233array_cid = Array {
839array_cid = Array {
1234− typoid = array_cidOid,
840+ typoid = Oid 1012,
1235 typcategory = 'A',
841 typcategory = 'A',
1236 typdelim = ',',
842 typdelim = ',',
1237 typname = "_cid",
843 typname = "_cid",
1238 typelem = cid
844 typelem = cid
1239 }
845 }
1240
846
1241−array_cidOid :: Oid
1242−array_cidOid = Oid 1012
1243−{-# INLINE array_cidOid #-}
1244−
1245array_oidvector :: TypeInfo
847array_oidvector :: TypeInfo
1246array_oidvector = Array {
848array_oidvector = Array {
1247− typoid = array_oidvectorOid,
849+ typoid = Oid 1013,
1248 typcategory = 'A',
850 typcategory = 'A',
1249 typdelim = ',',
851 typdelim = ',',
1250 typname = "_oidvector",
852 typname = "_oidvector",
1251 typelem = oidvector
853 typelem = oidvector
1252 }
854 }
1253
855
1254−array_oidvectorOid :: Oid
1255−array_oidvectorOid = Oid 1013
1256−{-# INLINE array_oidvectorOid #-}
1257−
1258array_bpchar :: TypeInfo
856array_bpchar :: TypeInfo
1259array_bpchar = Array {
857array_bpchar = Array {
1260− typoid = array_bpcharOid,
858+ typoid = Oid 1014,
1261 typcategory = 'A',
859 typcategory = 'A',
1262 typdelim = ',',
860 typdelim = ',',
1263 typname = "_bpchar",
861 typname = "_bpchar",
1264 typelem = bpchar
862 typelem = bpchar
1265 }
863 }
1266
864
1267−array_bpcharOid :: Oid
1268−array_bpcharOid = Oid 1014
1269−{-# INLINE array_bpcharOid #-}
1270−
1271array_varchar :: TypeInfo
865array_varchar :: TypeInfo
1272array_varchar = Array {
866array_varchar = Array {
1273− typoid = array_varcharOid,
867+ typoid = Oid 1015,
1274 typcategory = 'A',
868 typcategory = 'A',
1275 typdelim = ',',
869 typdelim = ',',
1276 typname = "_varchar",
870 typname = "_varchar",
1277 typelem = varchar
871 typelem = varchar
1278 }
872 }
1279
873
1280−array_varcharOid :: Oid
1281−array_varcharOid = Oid 1015
1282−{-# INLINE array_varcharOid #-}
1283−
1284array_int8 :: TypeInfo
874array_int8 :: TypeInfo
1285array_int8 = Array {
875array_int8 = Array {
1286− typoid = array_int8Oid,
876+ typoid = Oid 1016,
1287 typcategory = 'A',
877 typcategory = 'A',
1288 typdelim = ',',
878 typdelim = ',',
1289 typname = "_int8",
879 typname = "_int8",
1290 typelem = int8
880 typelem = int8
1291 }
881 }
1292
882
1293−array_int8Oid :: Oid
1294−array_int8Oid = Oid 1016
1295−{-# INLINE array_int8Oid #-}
1296−
1297array_point :: TypeInfo
883array_point :: TypeInfo
1298array_point = Array {
884array_point = Array {
1299− typoid = array_pointOid,
885+ typoid = Oid 1017,
1300 typcategory = 'A',
886 typcategory = 'A',
1301 typdelim = ',',
887 typdelim = ',',
1302 typname = "_point",
888 typname = "_point",
1303 typelem = point
889 typelem = point
1304 }
890 }
1305
891
1306−array_pointOid :: Oid
1307−array_pointOid = Oid 1017
1308−{-# INLINE array_pointOid #-}
1309−
1310array_lseg :: TypeInfo
892array_lseg :: TypeInfo
1311array_lseg = Array {
893array_lseg = Array {
1312− typoid = array_lsegOid,
894+ typoid = Oid 1018,
1313 typcategory = 'A',
895 typcategory = 'A',
1314 typdelim = ',',
896 typdelim = ',',
1315 typname = "_lseg",
897 typname = "_lseg",
1316 typelem = lseg
898 typelem = lseg
1317 }
899 }
1318
900
1319−array_lsegOid :: Oid
1320−array_lsegOid = Oid 1018
1321−{-# INLINE array_lsegOid #-}
1322−
1323array_path :: TypeInfo
901array_path :: TypeInfo
1324array_path = Array {
902array_path = Array {
1325− typoid = array_pathOid,
903+ typoid = Oid 1019,
1326 typcategory = 'A',
904 typcategory = 'A',
1327 typdelim = ',',
905 typdelim = ',',
1328 typname = "_path",
906 typname = "_path",
1329 typelem = path
907 typelem = path
1330 }
908 }
1331
909
1332−array_pathOid :: Oid
1333−array_pathOid = Oid 1019
1334−{-# INLINE array_pathOid #-}
1335−
1336array_box :: TypeInfo
910array_box :: TypeInfo
1337array_box = Array {
911array_box = Array {
1338− typoid = array_boxOid,
912+ typoid = Oid 1020,
1339 typcategory = 'A',
913 typcategory = 'A',
1340 typdelim = ';',
914 typdelim = ';',
1341 typname = "_box",
915 typname = "_box",
1342 typelem = box
916 typelem = box
1343 }
917 }
1344
918
1345−array_boxOid :: Oid
1346−array_boxOid = Oid 1020
1347−{-# INLINE array_boxOid #-}
1348−
1349array_float4 :: TypeInfo
919array_float4 :: TypeInfo
1350array_float4 = Array {
920array_float4 = Array {
1351− typoid = array_float4Oid,
921+ typoid = Oid 1021,
1352 typcategory = 'A',
922 typcategory = 'A',
1353 typdelim = ',',
923 typdelim = ',',
1354 typname = "_float4",
924 typname = "_float4",
1355 typelem = float4
925 typelem = float4
1356 }
926 }
1357
927
1358−array_float4Oid :: Oid
1359−array_float4Oid = Oid 1021
1360−{-# INLINE array_float4Oid #-}
1361−
1362array_float8 :: TypeInfo
928array_float8 :: TypeInfo
1363array_float8 = Array {
929array_float8 = Array {
1364− typoid = array_float8Oid,
930+ typoid = Oid 1022,
1365 typcategory = 'A',
931 typcategory = 'A',
1366 typdelim = ',',
932 typdelim = ',',
1367 typname = "_float8",
933 typname = "_float8",
1368 typelem = float8
934 typelem = float8
1369 }
935 }
1370
936
1371−array_float8Oid :: Oid
1372−array_float8Oid = Oid 1022
1373−{-# INLINE array_float8Oid #-}
1374−
1375array_polygon :: TypeInfo
937array_polygon :: TypeInfo
1376array_polygon = Array {
938array_polygon = Array {
1377− typoid = array_polygonOid,
939+ typoid = Oid 1027,
1378 typcategory = 'A',
940 typcategory = 'A',
1379 typdelim = ',',
941 typdelim = ',',
1380 typname = "_polygon",
942 typname = "_polygon",
1381 typelem = polygon
943 typelem = polygon
1382 }
944 }
1383
945
1384−array_polygonOid :: Oid
1385−array_polygonOid = Oid 1027
1386−{-# INLINE array_polygonOid #-}
1387−
1388array_oid :: TypeInfo
946array_oid :: TypeInfo
1389array_oid = Array {
947array_oid = Array {
1390− typoid = array_oidOid,
948+ typoid = Oid 1028,
1391 typcategory = 'A',
949 typcategory = 'A',
1392 typdelim = ',',
950 typdelim = ',',
1393 typname = "_oid",
951 typname = "_oid",
1394 typelem = oid
952 typelem = oid
1395 }
953 }
1396
954
1397−array_oidOid :: Oid
1398−array_oidOid = Oid 1028
1399−{-# INLINE array_oidOid #-}
1400−
1401array_macaddr :: TypeInfo
955array_macaddr :: TypeInfo
1402array_macaddr = Array {
956array_macaddr = Array {
1403− typoid = array_macaddrOid,
957+ typoid = Oid 1040,
1404 typcategory = 'A',
958 typcategory = 'A',
1405 typdelim = ',',
959 typdelim = ',',
1406 typname = "_macaddr",
960 typname = "_macaddr",
1407 typelem = macaddr
961 typelem = macaddr
1408 }
962 }
1409
963
1410−array_macaddrOid :: Oid
1411−array_macaddrOid = Oid 1040
1412−{-# INLINE array_macaddrOid #-}
1413−
1414array_inet :: TypeInfo
964array_inet :: TypeInfo
1415array_inet = Array {
965array_inet = Array {
1416− typoid = array_inetOid,
966+ typoid = Oid 1041,
1417 typcategory = 'A',
967 typcategory = 'A',
1418 typdelim = ',',
968 typdelim = ',',
1419 typname = "_inet",
969 typname = "_inet",
1420 typelem = inet
970 typelem = inet
1421 }
971 }
1422
972
1423−array_inetOid :: Oid
1424−array_inetOid = Oid 1041
1425−{-# INLINE array_inetOid #-}
1426−
1427array_timestamp :: TypeInfo
973array_timestamp :: TypeInfo
1428array_timestamp = Array {
974array_timestamp = Array {
1429− typoid = array_timestampOid,
975+ typoid = Oid 1115,
1430 typcategory = 'A',
976 typcategory = 'A',
1431 typdelim = ',',
977 typdelim = ',',
1432 typname = "_timestamp",
978 typname = "_timestamp",
1433 typelem = timestamp
979 typelem = timestamp
1434 }
980 }
1435
981
1436−array_timestampOid :: Oid
1437−array_timestampOid = Oid 1115
1438−{-# INLINE array_timestampOid #-}
1439−
1440array_date :: TypeInfo
982array_date :: TypeInfo
1441array_date = Array {
983array_date = Array {
1442− typoid = array_dateOid,
984+ typoid = Oid 1182,
1443 typcategory = 'A',
985 typcategory = 'A',
1444 typdelim = ',',
986 typdelim = ',',
1445 typname = "_date",
987 typname = "_date",
1446 typelem = date
988 typelem = date
1447 }
989 }
1448
990
1449−array_dateOid :: Oid
1450−array_dateOid = Oid 1182
1451−{-# INLINE array_dateOid #-}
1452−
1453array_time :: TypeInfo
991array_time :: TypeInfo
1454array_time = Array {
992array_time = Array {
1455− typoid = array_timeOid,
993+ typoid = Oid 1183,
1456 typcategory = 'A',
994 typcategory = 'A',
1457 typdelim = ',',
995 typdelim = ',',
1458 typname = "_time",
996 typname = "_time",
1459 typelem = time
997 typelem = time
1460 }
998 }
1461
999
1462−array_timeOid :: Oid
1463−array_timeOid = Oid 1183
1464−{-# INLINE array_timeOid #-}
1465−
1466array_timestamptz :: TypeInfo
1000array_timestamptz :: TypeInfo
1467array_timestamptz = Array {
1001array_timestamptz = Array {
1468− typoid = array_timestamptzOid,
1002+ typoid = Oid 1185,
1469 typcategory = 'A',
1003 typcategory = 'A',
1470 typdelim = ',',
1004 typdelim = ',',
1471 typname = "_timestamptz",
1005 typname = "_timestamptz",
1472 typelem = timestamptz
1006 typelem = timestamptz
1473 }
1007 }
1474
1008
1475−array_timestamptzOid :: Oid
1476−array_timestamptzOid = Oid 1185
1477−{-# INLINE array_timestamptzOid #-}
1478−
1479array_interval :: TypeInfo
1009array_interval :: TypeInfo
1480array_interval = Array {
1010array_interval = Array {
1481− typoid = array_intervalOid,
1011+ typoid = Oid 1187,
1482 typcategory = 'A',
1012 typcategory = 'A',
1483 typdelim = ',',
1013 typdelim = ',',
1484 typname = "_interval",
1014 typname = "_interval",
1485 typelem = interval
1015 typelem = interval
1486 }
1016 }
1487
1017
1488−array_intervalOid :: Oid
1489−array_intervalOid = Oid 1187
1490−{-# INLINE array_intervalOid #-}
1491−
1492array_numeric :: TypeInfo
1018array_numeric :: TypeInfo
1493array_numeric = Array {
1019array_numeric = Array {
1494− typoid = array_numericOid,
1020+ typoid = Oid 1231,
1495 typcategory = 'A',
1021 typcategory = 'A',
1496 typdelim = ',',
1022 typdelim = ',',
1497 typname = "_numeric",
1023 typname = "_numeric",
1498 typelem = numeric
1024 typelem = numeric
1499 }
1025 }
1500
1026
1501−array_numericOid :: Oid
1502−array_numericOid = Oid 1231
1503−{-# INLINE array_numericOid #-}
1504−
1505array_timetz :: TypeInfo
1027array_timetz :: TypeInfo
1506array_timetz = Array {
1028array_timetz = Array {
1507− typoid = array_timetzOid,
1029+ typoid = Oid 1270,
1508 typcategory = 'A',
1030 typcategory = 'A',
1509 typdelim = ',',
1031 typdelim = ',',
1510 typname = "_timetz",
1032 typname = "_timetz",
1511 typelem = timetz
1033 typelem = timetz
1512 }
1034 }
1513
1035
1514−array_timetzOid :: Oid
1515−array_timetzOid = Oid 1270
1516−{-# INLINE array_timetzOid #-}
1517−
1518array_bit :: TypeInfo
1036array_bit :: TypeInfo
1519array_bit = Array {
1037array_bit = Array {
1520− typoid = array_bitOid,
1038+ typoid = Oid 1561,
1521 typcategory = 'A',
1039 typcategory = 'A',
1522 typdelim = ',',
1040 typdelim = ',',
1523 typname = "_bit",
1041 typname = "_bit",
1524 typelem = bit
1042 typelem = bit
1525 }
1043 }
1526
1044
1527−array_bitOid :: Oid
1528−array_bitOid = Oid 1561
1529−{-# INLINE array_bitOid #-}
1530−
1531array_varbit :: TypeInfo
1045array_varbit :: TypeInfo
1532array_varbit = Array {
1046array_varbit = Array {
1533− typoid = array_varbitOid,
1047+ typoid = Oid 1563,
1534 typcategory = 'A',
1048 typcategory = 'A',
1535 typdelim = ',',
1049 typdelim = ',',
1536 typname = "_varbit",
1050 typname = "_varbit",
1537 typelem = varbit
1051 typelem = varbit
1538 }
1052 }
1539
1053
1540−array_varbitOid :: Oid
1541−array_varbitOid = Oid 1563
1542−{-# INLINE array_varbitOid #-}
1543−
1544array_refcursor :: TypeInfo
1054array_refcursor :: TypeInfo
1545array_refcursor = Array {
1055array_refcursor = Array {
1546− typoid = array_refcursorOid,
1056+ typoid = Oid 2201,
1547 typcategory = 'A',
1057 typcategory = 'A',
1548 typdelim = ',',
1058 typdelim = ',',
1549 typname = "_refcursor",
1059 typname = "_refcursor",
1550 typelem = refcursor
1060 typelem = refcursor
1551 }
1061 }
1552
1062
1553−array_refcursorOid :: Oid
1554−array_refcursorOid = Oid 2201
1555−{-# INLINE array_refcursorOid #-}
1556−
1557array_regprocedure :: TypeInfo
1063array_regprocedure :: TypeInfo
1558array_regprocedure = Array {
1064array_regprocedure = Array {
1559− typoid = array_regprocedureOid,
1065+ typoid = Oid 2207,
1560 typcategory = 'A',
1066 typcategory = 'A',
1561 typdelim = ',',
1067 typdelim = ',',
1562 typname = "_regprocedure",
1068 typname = "_regprocedure",
1563 typelem = regprocedure
1069 typelem = regprocedure
1564 }
1070 }
1565
1071
1566−array_regprocedureOid :: Oid
1567−array_regprocedureOid = Oid 2207
1568−{-# INLINE array_regprocedureOid #-}
1569−
1570array_regoper :: TypeInfo
1072array_regoper :: TypeInfo
1571array_regoper = Array {
1073array_regoper = Array {
1572− typoid = array_regoperOid,
1074+ typoid = Oid 2208,
1573 typcategory = 'A',
1075 typcategory = 'A',
1574 typdelim = ',',
1076 typdelim = ',',
1575 typname = "_regoper",
1077 typname = "_regoper",
1576 typelem = regoper
1078 typelem = regoper
1577 }
1079 }
1578
1080
1579−array_regoperOid :: Oid
1580−array_regoperOid = Oid 2208
1581−{-# INLINE array_regoperOid #-}
1582−
1583array_regoperator :: TypeInfo
1081array_regoperator :: TypeInfo
1584array_regoperator = Array {
1082array_regoperator = Array {
1585− typoid = array_regoperatorOid,
1083+ typoid = Oid 2209,
1586 typcategory = 'A',
1084 typcategory = 'A',
1587 typdelim = ',',
1085 typdelim = ',',
1588 typname = "_regoperator",
1086 typname = "_regoperator",
1589 typelem = regoperator
1087 typelem = regoperator
1590 }
1088 }
1591
1089
1592−array_regoperatorOid :: Oid
1593−array_regoperatorOid = Oid 2209
1594−{-# INLINE array_regoperatorOid #-}
1595−
1596array_regclass :: TypeInfo
1090array_regclass :: TypeInfo
1597array_regclass = Array {
1091array_regclass = Array {
1598− typoid = array_regclassOid,
1092+ typoid = Oid 2210,
1599 typcategory = 'A',
1093 typcategory = 'A',
1600 typdelim = ',',
1094 typdelim = ',',
1601 typname = "_regclass",
1095 typname = "_regclass",
1602 typelem = regclass
1096 typelem = regclass
1603 }
1097 }
1604
1098
1605−array_regclassOid :: Oid
1606−array_regclassOid = Oid 2210
1607−{-# INLINE array_regclassOid #-}
1608−
1609array_regtype :: TypeInfo
1099array_regtype :: TypeInfo
1610array_regtype = Array {
1100array_regtype = Array {
1611− typoid = array_regtypeOid,
1101+ typoid = Oid 2211,
1612 typcategory = 'A',
1102 typcategory = 'A',
1613 typdelim = ',',
1103 typdelim = ',',
1614 typname = "_regtype",
1104 typname = "_regtype",
1615 typelem = regtype
1105 typelem = regtype
1616 }
1106 }
1617
1107
1618−array_regtypeOid :: Oid
1619−array_regtypeOid = Oid 2211
1620−{-# INLINE array_regtypeOid #-}
1621−
1622array_uuid :: TypeInfo
1108array_uuid :: TypeInfo
1623array_uuid = Array {
1109array_uuid = Array {
1624− typoid = array_uuidOid,
1110+ typoid = Oid 2951,
1625 typcategory = 'A',
1111 typcategory = 'A',
1626 typdelim = ',',
1112 typdelim = ',',
1627 typname = "_uuid",
1113 typname = "_uuid",
1628 typelem = uuid
1114 typelem = uuid
1629 }
1115 }
1630
1116
1631−array_uuidOid :: Oid
1632−array_uuidOid = Oid 2951
1633−{-# INLINE array_uuidOid #-}
1634−
1635array_jsonb :: TypeInfo
1117array_jsonb :: TypeInfo
1636array_jsonb = Array {
1118array_jsonb = Array {
1637− typoid = array_jsonbOid,
1119+ typoid = Oid 3807,
1638 typcategory = 'A',
1120 typcategory = 'A',
1639 typdelim = ',',
1121 typdelim = ',',
1640 typname = "_jsonb",
1122 typname = "_jsonb",
1641 typelem = jsonb
1123 typelem = jsonb
1642 }
1124 }
1643
1125
1644−array_jsonbOid :: Oid
1645−array_jsonbOid = Oid 3807
1646−{-# INLINE array_jsonbOid #-}
1647−
1648int4range :: TypeInfo
1126int4range :: TypeInfo
1649int4range = Range {
1127int4range = Range {
1650− typoid = int4rangeOid,
1128+ typoid = Oid 3904,
1651 typcategory = 'R',
1129 typcategory = 'R',
1652 typdelim = ',',
1130 typdelim = ',',
1653 typname = "int4range",
1131 typname = "int4range",
1654 rngsubtype = int4
1132 rngsubtype = int4
1655 }
1133 }
1656
1134
1657−int4rangeOid :: Oid
1658−int4rangeOid = Oid 3904
1659−{-# INLINE int4rangeOid #-}
1660−
1661_int4range :: TypeInfo
1135_int4range :: TypeInfo
1662_int4range = Array {
1136_int4range = Array {
1663− typoid = _int4rangeOid,
1137+ typoid = Oid 3905,
1664 typcategory = 'A',
1138 typcategory = 'A',
1665 typdelim = ',',
1139 typdelim = ',',
1666 typname = "_int4range",
1140 typname = "_int4range",
1667 typelem = int4range
1141 typelem = int4range
1668 }
1142 }
1669
1143
1670−_int4rangeOid :: Oid
1671−_int4rangeOid = Oid 3905
1672−{-# INLINE _int4rangeOid #-}
1673−
1674numrange :: TypeInfo
1144numrange :: TypeInfo
1675numrange = Range {
1145numrange = Range {
1676− typoid = numrangeOid,
1146+ typoid = Oid 3906,
1677 typcategory = 'R',
1147 typcategory = 'R',
1678 typdelim = ',',
1148 typdelim = ',',
1679 typname = "numrange",
1149 typname = "numrange",
1680 rngsubtype = numeric
1150 rngsubtype = numeric
1681 }
1151 }
1682
1152
1683−numrangeOid :: Oid
1684−numrangeOid = Oid 3906
1685−{-# INLINE numrangeOid #-}
1686−
1687_numrange :: TypeInfo
1153_numrange :: TypeInfo
1688_numrange = Array {
1154_numrange = Array {
1689− typoid = _numrangeOid,
1155+ typoid = Oid 3907,
1690 typcategory = 'A',
1156 typcategory = 'A',
1691 typdelim = ',',
1157 typdelim = ',',
1692 typname = "_numrange",
1158 typname = "_numrange",
1693 typelem = numrange
1159 typelem = numrange
1694 }
1160 }
1695
1161
1696−_numrangeOid :: Oid
1697−_numrangeOid = Oid 3907
1698−{-# INLINE _numrangeOid #-}
1699−
1700tsrange :: TypeInfo
1162tsrange :: TypeInfo
1701tsrange = Range {
1163tsrange = Range {
1702− typoid = tsrangeOid,
1164+ typoid = Oid 3908,
1703 typcategory = 'R',
1165 typcategory = 'R',
1704 typdelim = ',',
1166 typdelim = ',',
1705 typname = "tsrange",
1167 typname = "tsrange",
1706 rngsubtype = timestamp
1168 rngsubtype = timestamp
1707 }
1169 }
1708
1170
1709−tsrangeOid :: Oid
1710−tsrangeOid = Oid 3908
1711−{-# INLINE tsrangeOid #-}
1712−
1713_tsrange :: TypeInfo
1171_tsrange :: TypeInfo
1714_tsrange = Array {
1172_tsrange = Array {
1715− typoid = _tsrangeOid,
1173+ typoid = Oid 3909,
1716 typcategory = 'A',
1174 typcategory = 'A',
1717 typdelim = ',',
1175 typdelim = ',',
1718 typname = "_tsrange",
1176 typname = "_tsrange",
1719 typelem = tsrange
1177 typelem = tsrange
1720 }
1178 }
1721
1179
1722−_tsrangeOid :: Oid
1723−_tsrangeOid = Oid 3909
1724−{-# INLINE _tsrangeOid #-}
1725−
1726tstzrange :: TypeInfo
1180tstzrange :: TypeInfo
1727tstzrange = Range {
1181tstzrange = Range {
1728− typoid = tstzrangeOid,
1182+ typoid = Oid 3910,
1729 typcategory = 'R',
1183 typcategory = 'R',
1730 typdelim = ',',
1184 typdelim = ',',
1731 typname = "tstzrange",
1185 typname = "tstzrange",
1732 rngsubtype = timestamptz
1186 rngsubtype = timestamptz
1733 }
1187 }
1734
1188
1735−tstzrangeOid :: Oid
1736−tstzrangeOid = Oid 3910
1737−{-# INLINE tstzrangeOid #-}
1738−
1739_tstzrange :: TypeInfo
1189_tstzrange :: TypeInfo
1740_tstzrange = Array {
1190_tstzrange = Array {
1741− typoid = _tstzrangeOid,
1191+ typoid = Oid 3911,
1742 typcategory = 'A',
1192 typcategory = 'A',
1743 typdelim = ',',
1193 typdelim = ',',
1744 typname = "_tstzrange",
1194 typname = "_tstzrange",
1745 typelem = tstzrange
1195 typelem = tstzrange
1746 }
1196 }
1747
1197
1748−_tstzrangeOid :: Oid
1749−_tstzrangeOid = Oid 3911
1750−{-# INLINE _tstzrangeOid #-}
1751−
1752daterange :: TypeInfo
1198daterange :: TypeInfo
1753daterange = Range {
1199daterange = Range {
1754− typoid = daterangeOid,
1200+ typoid = Oid 3912,
1755 typcategory = 'R',
1201 typcategory = 'R',
1756 typdelim = ',',
1202 typdelim = ',',
1757 typname = "daterange",
1203 typname = "daterange",
1758 rngsubtype = date
1204 rngsubtype = date
1759 }
1205 }
1760
1206
1761−daterangeOid :: Oid
1762−daterangeOid = Oid 3912
1763−{-# INLINE daterangeOid #-}
1764−
1765_daterange :: TypeInfo
1207_daterange :: TypeInfo
1766_daterange = Array {
1208_daterange = Array {
1767− typoid = _daterangeOid,
1209+ typoid = Oid 3913,
1768 typcategory = 'A',
1210 typcategory = 'A',
1769 typdelim = ',',
1211 typdelim = ',',
1770 typname = "_daterange",
1212 typname = "_daterange",
1771 typelem = daterange
1213 typelem = daterange
1772 }
1214 }
1773
1215
1774−_daterangeOid :: Oid
1775−_daterangeOid = Oid 3913
1776−{-# INLINE _daterangeOid #-}
1777−
1778int8range :: TypeInfo
1216int8range :: TypeInfo
1779int8range = Range {
1217int8range = Range {
1780− typoid = int8rangeOid,
1218+ typoid = Oid 3926,
1781 typcategory = 'R',
1219 typcategory = 'R',
1782 typdelim = ',',
1220 typdelim = ',',
1783 typname = "int8range",
1221 typname = "int8range",
1784 rngsubtype = int8
1222 rngsubtype = int8
1785 }
1223 }
1786
1224
1787−int8rangeOid :: Oid
1788−int8rangeOid = Oid 3926
1789−{-# INLINE int8rangeOid #-}
1790−
1791_int8range :: TypeInfo
1225_int8range :: TypeInfo
1792_int8range = Array {
1226_int8range = Array {
1793− typoid = _int8rangeOid,
1227+ typoid = Oid 3927,
1794 typcategory = 'A',
1228 typcategory = 'A',
1795 typdelim = ',',
1229 typdelim = ',',
1796 typname = "_int8range",
1230 typname = "_int8range",
1797 typelem = int8range
1231 typelem = int8range
1798 }
1232 }
1799−
1800−_int8rangeOid :: Oid
1801−_int8rangeOid = Oid 3927
1802−{-# INLINE _int8rangeOid #-}
src/Database/PostgreSQL/Simple/Types.hs+26−10
@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor, GeneralizedNewtypeDeriving #-}
1+{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, GeneralizedNewtypeDeriving #-}
2
2
3------------------------------------------------------------------------------
3------------------------------------------------------------------------------
4-- |
4-- |
@@ -33,16 +33,13 @@ module Database.PostgreSQL.Simple.Types
33import Control.Arrow (first)
33import Control.Arrow (first)
34import Data.ByteString (ByteString)
34import Data.ByteString (ByteString)
35import Data.Hashable (Hashable(hashWithSalt))
35import Data.Hashable (Hashable(hashWithSalt))
36−import Data.Foldable (toList)
37import Data.Monoid (Monoid(..))
36import Data.Monoid (Monoid(..))
38−import Data.Semigroup
39import Data.String (IsString(..))
37import Data.String (IsString(..))
40import Data.Typeable (Typeable)
38import Data.Typeable (Typeable)
41import Data.ByteString.Builder ( stringUtf8 )
39import Data.ByteString.Builder ( stringUtf8 )
42import qualified Data.ByteString as B
40import qualified Data.ByteString as B
43import Data.Text (Text)
41import Data.Text (Text)
44import qualified Data.Text as T
42import qualified Data.Text as T
45−import Data.Tuple.Only (Only(..))
46import Database.PostgreSQL.LibPQ (Oid(..))
43import Database.PostgreSQL.LibPQ (Oid(..))
47import Database.PostgreSQL.Simple.Compat (toByteString)
44import Database.PostgreSQL.Simple.Compat (toByteString)
48
45
@@ -50,6 +47,10 @@ import Database.PostgreSQL.Simple.Compat (toByteString)
50data Null = Null
47data Null = Null
51 deriving (Read, Show, Typeable)
48 deriving (Read, Show, Typeable)
52
49
50+instance Eq Null where
51+ _ == _ = False
52+ _ /= _ = False
53+
53-- | A placeholder for the PostgreSQL @DEFAULT@ value.
54-- | A placeholder for the PostgreSQL @DEFAULT@ value.
54data Default = Default
55data Default = Default
55 deriving (Read, Show, Typeable)
56 deriving (Read, Show, Typeable)
@@ -86,13 +87,28 @@ instance Read Query where
86instance IsString Query where
87instance IsString Query where
87 fromString = Query . toByteString . stringUtf8
88 fromString = Query . toByteString . stringUtf8
88
89
89−instance Semigroup Query where
90− Query a <> Query b = Query (B.append a b)
91− {-# INLINE (<>) #-}
92− sconcat xs = Query (B.concat $ map fromQuery $ toList xs)
93−
94instance Monoid Query where
90instance Monoid Query where
95 mempty = Query B.empty
91 mempty = Query B.empty
92+ mappend (Query a) (Query b) = Query (B.append a b)
93+ {-# INLINE mappend #-}
94+ mconcat xs = Query (B.concat (map fromQuery xs))
95+
96+-- | A single-value \"collection\".
97+--
98+-- This is useful if you need to supply a single parameter to a SQL
99+-- query, or extract a single column from a SQL result.
100+--
101+-- Parameter example:
102+--
103+-- @query c \"select x from scores where x > ?\" ('Only' (42::Int))@
104+--
105+-- Result example:
106+--
107+-- @xs <- query_ c \"select id from users\"
108+--forM_ xs $ \\('Only' id) -> {- ... -}@
109+newtype Only a = Only {
110+ fromOnly :: a
111+ } deriving (Eq, Ord, Read, Show, Typeable, Functor)
96
112
97-- | Wrap a list of values for use in an @IN@ clause. Replaces a
113-- | Wrap a list of values for use in an @IN@ clause. Replaces a
98-- single \"@?@\" character with a parenthesized list of rendered
114-- single \"@?@\" character with a parenthesized list of rendered
@@ -252,7 +268,7 @@ newtype Savepoint = Savepoint Query
252-- without issuing the query. In the second case, the postgres server
268-- without issuing the query. In the second case, the postgres server
253-- will return an error which will be turned into a @SqlError@ exception.
269-- will return an error which will be turned into a @SqlError@ exception.
254--
270--
255−-- See <https://www.postgresql.org/docs/9.5/static/sql-values.html> for
271+-- See <http://www.postgresql.org/docs/9.3/static/sql-values.html> for
256-- more information.
272-- more information.
257data Values a = Values [QualifiedIdentifier] [a]
273data Values a = Values [QualifiedIdentifier] [a]
258 deriving (Eq, Ord, Show, Read, Typeable)
274 deriving (Eq, Ord, Show, Read, Typeable)
src/Database/PostgreSQL/Simple/Vector.hsdeleted−45
@@ -1,45 +0,0 @@
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.hsdeleted−44
@@ -1,44 +0,0 @@
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
test/Exception.hsdeleted−70
@@ -1,70 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−
5−module Exception (testExceptions) where
6−
7−import Database.PostgreSQL.Simple
8−import Test.Tasty.HUnit (Assertion, assertBool)
9−import Common (TestEnv)
10−import Control.Exception (Exception (..), SomeException)
11−import Data.Maybe (isJust)
12−import Data.Either (isLeft)
13−import Control.Exception (throwIO, try)
14−
15−testExceptions :: TestEnv -> Assertion
16−testExceptions _ = do
17− let sqlError = SqlError
18− { sqlState = ""
19− , sqlExecStatus = FatalError
20− , sqlErrorMsg = ""
21− , sqlErrorDetail = ""
22− , sqlErrorHint = ""
23− }
24− let sqlEx :: SomeException = toException sqlError
25− assertBool "SqlError is SomePostgreSqlException" $ isJust (fromException sqlEx :: Maybe SomePostgreSqlException)
26− assertBool "SqlError is SqlError" $ isJust (fromException sqlEx :: Maybe SqlError)
27− eSqlError :: Either SqlError () <- try $ throwIO sqlEx
28− assertBool "Can catch SqlError" $ isLeft eSqlError
29− eSqlPostgreSqlEx :: Either SomePostgreSqlException () <- try $ throwIO sqlEx
30− assertBool "Can catch SomePostgreSqlException from SqlError" $ isLeft eSqlPostgreSqlEx
31−
32− let formatError = FormatError
33− { fmtMessage = ""
34− , fmtQuery = ""
35− , fmtParams = []
36− }
37− let formatEx :: SomeException = toException formatError
38− assertBool "FormatError is SomePostgreSqlException" $ isJust (fromException formatEx :: Maybe SomePostgreSqlException)
39− assertBool "FormatError is FormatError" $ isJust (fromException formatEx :: Maybe FormatError)
40− eFormatError :: Either FormatError () <- try $ throwIO formatEx
41− assertBool "Can catch FormatError" $ isLeft eFormatError
42− eFormatPostreSqlEx :: Either SomePostgreSqlException () <- try $ throwIO formatEx
43− assertBool "Can catch SomePostgreSqlException from FormatError" $ isLeft eFormatPostreSqlEx
44−
45− let queryError = QueryError
46− { qeMessage = ""
47− , qeQuery = ""
48− }
49− let queryEx :: SomeException = toException queryError
50− assertBool "QueryError is SomePostgreSqlException" $ isJust (fromException queryEx :: Maybe SomePostgreSqlException)
51− assertBool "QueryError is QueryError" $ isJust (fromException queryEx :: Maybe QueryError)
52− eQueryError :: Either QueryError () <- try $ throwIO queryEx
53− assertBool "Can catch QueryError" $ isLeft eQueryError
54− eQueryPostgreSqlEx :: Either SomePostgreSqlException () <- try $ throwIO queryEx
55− assertBool "Can catch SomePostgreSqlException from QueryError" $ isLeft eQueryPostgreSqlEx
56−
57− let resultError = Incompatible
58− { errSQLType = ""
59− , errSQLTableOid = Nothing
60− , errSQLField = ""
61− , errHaskellType = ""
62− , errMessage = ""
63− }
64− let resultEx :: SomeException = toException resultError
65− assertBool "ResultError is SomePostgreSqlException" $ isJust (fromException resultEx :: Maybe SomePostgreSqlException)
66− assertBool "ResultError is ResultError" $ isJust (fromException resultEx :: Maybe ResultError)
67− eResultEx :: Either ResultError () <- try $ throwIO resultEx
68− assertBool "Can catch ResultError" $ isLeft eResultEx
69− eResultPostgreSqlEx :: Either SomePostgreSqlException () <- try $ throwIO resultEx
70− assertBool "Can catch SomePostgreSqlException from ResultError" $ isLeft eResultPostgreSqlEx
test/Inspection.hsdeleted−79
@@ -1,79 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE TemplateHaskell #-}
3−{-# OPTIONS_GHC -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-module-prefixes -dsuppress-type-signatures #-}
4−-- {-# OPTIONS_GHC -dsuppress-uniques #-}
5−{-# OPTIONS_GHC -fplugin=Test.Inspection.Plugin #-}
6−module Main where
7−
8−import Test.Inspection
9−import Test.Tasty
10−import Test.Tasty.HUnit
11−
12−import qualified Database.PostgreSQL.LibPQ as PQ
13−import Database.PostgreSQL.Simple.FromField
14−import Database.PostgreSQL.Simple.TypeInfo as TI
15−import Database.PostgreSQL.Simple.TypeInfo.Macro
16−import qualified Database.PostgreSQL.Simple.TypeInfo.Static as TI
17−
18−-------------------------------------------------------------------------------
19−-- Inspection tests
20−-------------------------------------------------------------------------------
21−
22−-- # doesn't work :(
23−#define TH_MKCOMPATS3(a,b,c) $(mkCompats [TI.a,TI.b,TI.c])
24−#define IN_MKCOMPATS3(a,b,c) (eq TI.a \/ eq TI.b \/ eq TI.c)
25−
26−#define TH_INLINETYPOID(n) eq $(inlineTypoid TI.n)
27−#define IN_INLINETYPOID(n) eq TI.n
28−
29−-- eta-expansion is required
30−lhs01, rhs01 :: PQ.Oid -> Bool
31−lhs01 = TH_MKCOMPATS3(name,text,char)
32−rhs01 = IN_MKCOMPATS3(nameOid,textOid,charOid)
33−
34−lhs02, rhs02 :: PQ.Oid -> Bool
35−lhs02 = TH_INLINETYPOID(name)
36−rhs02 = IN_INLINETYPOID(nameOid)
37−
38−eq :: PQ.Oid -> PQ.Oid -> Bool
39−eq = (==)
40−{-# INLINE eq #-}
41−
42−infixr 2 \/
43−(\/) :: (PQ.Oid -> Bool)
44− -> (PQ.Oid -> Bool)
45− -> (PQ.Oid -> Bool)
46−f \/ g = \x -> f x || g x
47−{-# INLINE (\/) #-}
48−
49−inspectionTests :: TestTree
50−inspectionTests = testGroup "inspection"
51− [ testCase "mkCompats" $
52− assertSuccess $(inspectTest $ 'lhs01 === 'rhs01)
53−
54− -- byteaOid isn't inlined?
55− , testCase "inlineTypoid" $
56−#if __GLASGOW_HASKELL__ >= 808
57− assertSuccess
58−#else
59− assertFailure'
60−#endif
61− $(inspectTest $ 'lhs02 ==- 'rhs02)
62− ]
63−
64−assertSuccess :: Result -> IO ()
65−assertSuccess (Success _) = return ()
66−assertSuccess (Failure err) = assertFailure err
67−
68−assertFailure' :: Result -> IO ()
69−assertFailure' (Success err) = assertFailure err
70−assertFailure' (Failure _) = return ()
71−
72−-------------------------------------------------------------------------------
73−-- Main
74−-------------------------------------------------------------------------------
75−
76−main :: IO ()
77−main = defaultMain $ testGroup "tests"
78− [ inspectionTests
79− ]
test/Interval.hsdeleted−176
@@ -1,176 +0,0 @@
1−{-# LANGUAGE QuasiQuotes #-}
2−
3−{-
4−
5−Testing strategies:
6−
7−fromString . toString == id ** Todo?
8−
9−toString . fromString == almost id ** Todo?
10−
11−postgresql -> haskell -> postgresql * Done
12−
13−haskell -> postgresql -> haskell ** Todo?
14−
15−But still, what we really want to establish is that the two values
16−correspond; for example, a conversion that consistently added hour
17−when printed to a string and subtracted an hour when parsed from string
18−would still pass these tests.
19−
20−
21−Right now, we are checking that 1400+ timestamps in the range of 1860 to
22−2060 round trip from postgresql to haskell and back in 5 different timezones.
23−In addition to UTC, the four timezones were selected so that 2 have a positive
24−offset, and 2 have a negative offset, and that 2 have an offset of a
25−whole number of hours, while the other two do not.
26−
27−It may be worth adding a few more timezones to ensure better test coverage.
28−
29−We are checking a handful of selected timestamps to ensure we hit
30−various corner-cases in the code, in addition to 1400 timestamps randomly
31−generated with granularity of seconds down to microseconds in powers of ten.
32−
33−-}
34−
35−module Interval (testInterval) where
36−
37−import Common
38−import Control.Monad(forM_, replicateM_)
39−import Data.Time.Compat
40−import Data.Time.LocalTime.Compat (CalendarDiffTime(..))
41−import Data.ByteString(ByteString)
42−import Database.PostgreSQL.Simple.SqlQQ
43−
44−data IntervalTestCase = IntervalTestCase
45− { label :: String
46− , inputMonths :: Integer
47− , inputSeconds :: NominalDiffTime
48− , asText :: String
49− }
50− deriving (Eq, Show)
51−
52−testInterval :: TestEnv -> Assertion
53−testInterval env@TestEnv{..} = do
54−
55− initializeTable env
56−
57− let milliseconds = 0.001
58− seconds = 1
59− minutes = 60 * seconds
60− hours = 60 * minutes
61− days = 24 * hours
62− weeks = 7 * days
63− months = 1
64− years = 12 * months
65−
66− mapM (checkRoundTrip env)
67− [ IntervalTestCase
68− { label = "zero"
69− , inputMonths = 0
70− , inputSeconds = 0
71− , asText = "PT0"
72− }
73− , IntervalTestCase
74− { label = "1 year"
75− , inputMonths = 1 * years
76− , inputSeconds = 0
77− , asText = "P1Y"
78− }
79− , IntervalTestCase
80− { label = "2 months"
81− , inputMonths = 2 * months
82− , inputSeconds = 0
83− , asText = "P2M"
84− }
85− , IntervalTestCase
86− { label = "3 weeks"
87− , inputMonths = 0
88− , inputSeconds = 3 * weeks
89− , asText = "P3W"
90− }
91− , IntervalTestCase
92− { label = "4 days"
93− , inputMonths = 0
94− , inputSeconds = 4 * days
95− , asText = "P4D"
96− }
97− , IntervalTestCase
98− { label = "5 hours"
99− , inputMonths = 0
100− , inputSeconds = 5 * hours
101− , asText = "PT5H"
102− }
103− , IntervalTestCase
104− { label = "6 minutes"
105− , inputMonths = 0
106− , inputSeconds = 6 * minutes
107− , asText = "PT6M"
108− }
109− , IntervalTestCase
110− { label = "7 seconds"
111− , inputMonths = 0
112− , inputSeconds = 7 * seconds
113− , asText = "PT7S"
114− }
115− , IntervalTestCase
116− { label = "8 milliseconds"
117− , inputMonths = 0
118− , inputSeconds = 8 * milliseconds
119− , asText = "PT0.008S"
120− }
121− , IntervalTestCase
122− { label = "combination of intervals (day-size or bigger)"
123− , inputMonths = 2 * years + 4 * months
124− , inputSeconds = 3 * weeks + 5 * days
125− , asText = "P2Y4M3W5D"
126− }
127− , IntervalTestCase
128− { label = "combination of intervals (smaller than day-size)"
129− , inputMonths = 0
130− , inputSeconds = 18 * hours + 56 * minutes + 23 * seconds + 563 * milliseconds
131− , asText = "PT18H56M23.563S"
132− }
133− , IntervalTestCase
134− { label = "full combination of intervals"
135− , inputMonths = 2 * years + 4 * months
136− , inputSeconds = 3 * weeks + 5 * days + 18 * hours + 56 * minutes + 23 * seconds + 563 * milliseconds
137− , asText = "P2Y4M3W5DT18H56M23.563S"
138− }
139− ]
140−
141− return ()
142−
143−initializeTable :: TestEnv -> IO ()
144−initializeTable TestEnv{..} = withTransaction conn $ do
145− execute_ conn
146− [sql| CREATE TEMPORARY TABLE testinterval
147− ( id serial, sample interval, PRIMARY KEY(id) ) |]
148−
149− return ()
150−
151−checkRoundTrip :: TestEnv -> IntervalTestCase -> IO ()
152−checkRoundTrip TestEnv{..} IntervalTestCase{..} = do
153−
154− let input = CalendarDiffTime
155− { ctMonths = inputMonths
156− , ctTime = inputSeconds
157− }
158−
159− [(returnedId :: Int, output :: CalendarDiffTime)] <- query conn [sql|
160− INSERT INTO testinterval (sample)
161− VALUES (?)
162− RETURNING id, sample
163− |] (Only input)
164−
165− assertBool ("CalendarDiffTime did not round-trip from Haskell to SQL and back (" ++ label ++ ")") $
166− output == input
167−
168− [(Only isExpectedIso)] <- query conn [sql|
169− SELECT sample = (?)::interval
170− FROM testinterval
171− WHERE id = ?
172− |] (asText, returnedId)
173−
174− assertBool ("CalendarDiffTime inserted did not match ISO8601 equivalent \"" ++ asText ++ "\". (" ++ label ++ ")")
175− isExpectedIso
176−
test/Main.hs+29−237
@@ -1,91 +1,61 @@
1−{-# LANGUAGE CPP #-}
2{-# LANGUAGE DeriveGeneric #-}
1{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveDataTypeable #-}
4{-# LANGUAGE DoAndIfThenElse #-}
3{-# LANGUAGE DoAndIfThenElse #-}
5{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE ScopedTypeVariables #-}
6−#if __GLASGOW_HASKELL__ >= 806
7−{-# LANGUAGE DerivingStrategies #-}
8−{-# LANGUAGE DerivingVia #-}
9−{-# LANGUAGE DeriveAnyClass #-}
10−#endif
11−module Main (main) where
12−
13import Common
5import Common
14−import Database.PostgreSQL.Simple.Copy
15−import Database.PostgreSQL.Simple.ToField (ToField)
16import Database.PostgreSQL.Simple.FromField (FromField)
6import Database.PostgreSQL.Simple.FromField (FromField)
7+import Database.PostgreSQL.Simple.Types(Query(..),Values(..))
17import Database.PostgreSQL.Simple.HStore
8import Database.PostgreSQL.Simple.HStore
18−import Database.PostgreSQL.Simple.Newtypes
9+import Database.PostgreSQL.Simple.Copy
19−import Database.PostgreSQL.Simple.Internal (breakOnSingleQuestionMark)
20−import Database.PostgreSQL.Simple.Types(Query(..),Values(..), PGArray(..))
21import qualified Database.PostgreSQL.Simple.Transaction as ST
10import qualified Database.PostgreSQL.Simple.Transaction as ST
22
11
23import Control.Applicative
12import Control.Applicative
24import Control.Exception as E
13import Control.Exception as E
25import Control.Monad
14import Control.Monad
26import Data.Char
15import Data.Char
27−import Data.Foldable (toList)
16+import Data.List (sort)
28−import Data.List (concat, sort)
29import Data.IORef
17import Data.IORef
30−import Data.Monoid ((<>))
31−import Data.String (fromString)
32import Data.Typeable
18import Data.Typeable
33import GHC.Generics (Generic)
19import GHC.Generics (Generic)
34
20
35import Data.Aeson
21import Data.Aeson
36import Data.ByteString (ByteString)
22import Data.ByteString (ByteString)
37import qualified Data.ByteString as B
23import qualified Data.ByteString as B
38−import qualified Data.ByteString.Char8 as BS8
39import qualified Data.ByteString.Lazy.Char8 as BL
24import qualified Data.ByteString.Lazy.Char8 as BL
40−import Data.CaseInsensitive (CI)
41−import qualified Data.CaseInsensitive as CI
42import Data.Map (Map)
25import Data.Map (Map)
43import qualified Data.Map as Map
26import qualified Data.Map as Map
44import Data.Text(Text)
27import Data.Text(Text)
45import qualified Data.Text.Encoding as T
28import qualified Data.Text.Encoding as T
46import qualified Data.Vector as V
29import qualified Data.Vector as V
47import System.FilePath
30import System.FilePath
48−import System.Timeout(timeout)
49−import Data.Time.Compat (getCurrentTime, diffUTCTime)
50−import System.Environment (getEnvironment)
51
31
52import Test.Tasty
32import Test.Tasty
53import Test.Tasty.Golden
33import Test.Tasty.Golden
54import Notify
34import Notify
55import Serializable
35import Serializable
56import Time
36import Time
57−import Interval
58−import Exception (testExceptions)
59
37
60tests :: TestEnv -> TestTree
38tests :: TestEnv -> TestTree
61tests env = testGroup "tests"
39tests env = testGroup "tests"
62 $ map ($ env)
40 $ map ($ env)
63 [ testBytea
41 [ testBytea
64− , testCase "ExecuteMany" . testExecuteMany
42+ , testCase "ExecuteMany" . testExecuteMany
65− , testCase "Fold" . testFold
43+ , testCase "Fold" . testFold
66− , testCase "Notify" . testNotify
44+ , testCase "Notify" . testNotify
67− , testCase "Serializable" . testSerializable
45+ , testCase "Serializable" . testSerializable
68− , testCase "Time" . testTime
46+ , testCase "Time" . testTime
69− , testCase "Interval" . testInterval
70− , testCase "Array" . testArray
47+ , testCase "Array" . testArray
71− , testCase "Array of nullables" . testNullableArray
72− , testCase "HStore" . testHStore
48+ , testCase "HStore" . testHStore
73− , testCase "citext" . testCIText
74− , testCase "JSON" . testJSON
49+ , testCase "JSON" . testJSON
75− , testCase "Aeson newtype" . testAeson
76− , testCase "DerivingVia" . testDerivingVia
77− , testCase "Question mark escape" . testQM
78− , testCase "Savepoint" . testSavepoint
50+ , testCase "Savepoint" . testSavepoint
79− , testCase "Unicode" . testUnicode
51+ , testCase "Unicode" . testUnicode
80− , testCase "Values" . testValues
52+ , testCase "Values" . testValues
81− , testCase "Copy" . testCopy
53+ , testCase "Copy" . testCopy
82 , testCopyFailures
54 , testCopyFailures
83− , testCase "Double" . testDouble
55+ , testCase "Double" . testDouble
84− , testCase "1-ary generic" . testGeneric1
56+ , testCase "1-ary generic" . testGeneric1
85− , testCase "2-ary generic" . testGeneric2
57+ , testCase "2-ary generic" . testGeneric2
86− , testCase "3-ary generic" . testGeneric3
58+ , testCase "3-ary generic" . testGeneric3
87− , testCase "Timeout" . testTimeout
88− , testCase "Exceptions" . testExceptions
89 ]
59 ]
90
60
91testBytea :: TestEnv -> TestTree
61testBytea :: TestEnv -> TestTree
@@ -139,7 +109,7 @@ testFold TestEnv{..} = do
139 xs <- readIORef ref
109 xs <- readIORef ref
140 writeIORef ref $! (a,b):xs
110 writeIORef ref $! (a,b):xs
141 xs <- readIORef ref
111 xs <- readIORef ref
142− reverse xs @?= [(a,b) | b <- [1..50], a <- [1..100]]
112+ reverse xs @?= [(a,b) | a <- [1..100], b <- [1..50]]
143
113
144 -- Make sure fold propagates our exception.
114 -- Make sure fold propagates our exception.
145 ref <- newIORef []
115 ref <- newIORef []
@@ -207,14 +177,6 @@ testArray TestEnv{..} = do
207 queryFailure conn "SELECT '{1,2,3,4}'::_int4" (undefined :: V.Vector Bool)
177 queryFailure conn "SELECT '{1,2,3,4}'::_int4" (undefined :: V.Vector Bool)
208 queryFailure conn "SELECT '{{1,2},{3,4}}'::_int4" (undefined :: V.Vector Int)
178 queryFailure conn "SELECT '{{1,2},{3,4}}'::_int4" (undefined :: V.Vector Int)
209
179
210−testNullableArray :: TestEnv -> Assertion
211−testNullableArray TestEnv{..} = do
212− xs <- query_ conn "SELECT '{sometext, \"NULL\"}'::_text"
213− xs @?= [Only (V.fromList ["sometext", "NULL" :: Text])]
214− xs <- query_ conn "SELECT '{sometext, NULL}'::_text"
215− xs @?= [Only (V.fromList [Just "sometext", Nothing :: Maybe Text])]
216− queryFailure conn "SELECT '{sometext, NULL}'::_text" (undefined :: V.Vector Text)
217−
218testHStore :: TestEnv -> Assertion
180testHStore :: TestEnv -> Assertion
219testHStore TestEnv{..} = do
181testHStore TestEnv{..} = do
220 execute_ conn "CREATE EXTENSION IF NOT EXISTS hstore"
182 execute_ conn "CREATE EXTENSION IF NOT EXISTS hstore"
@@ -228,19 +190,6 @@ testHStore TestEnv{..} = do
228 m' <- query conn "SELECT ?::hstore" m
190 m' <- query conn "SELECT ?::hstore" m
229 [m] @?= m'
191 [m] @?= m'
230
192
231−testCIText :: TestEnv -> Assertion
232−testCIText TestEnv{..} = do
233− execute_ conn "CREATE EXTENSION IF NOT EXISTS citext"
234− roundTrip (CI.mk "")
235− roundTrip (CI.mk "UPPERCASE")
236− roundTrip (CI.mk "lowercase")
237− where
238− roundTrip :: (CI Text) -> Assertion
239− roundTrip cit = do
240− let toPostgres = Only cit
241− fromPostgres <- query conn "SELECT ?::citext" toPostgres
242− [toPostgres] @?= fromPostgres
243−
244testJSON :: TestEnv -> Assertion
193testJSON :: TestEnv -> Assertion
245testJSON TestEnv{..} = do
194testJSON TestEnv{..} = do
246 roundTrip (Map.fromList [] :: Map Text Text)
195 roundTrip (Map.fromList [] :: Map Text Text)
@@ -256,90 +205,6 @@ testJSON TestEnv{..} = do
256 js' <- query conn "SELECT ?::json" js
205 js' <- query conn "SELECT ?::json" js
257 [js] @?= js'
206 [js] @?= js'
258
207
259−testAeson :: TestEnv -> Assertion
260−testAeson TestEnv{..} = do
261− roundTrip (Map.fromList [] :: Map Text Text)
262− roundTrip (Map.fromList [("foo","bar"),("bar","baz"),("baz","hello")] :: Map Text Text)
263− roundTrip (Map.fromList [("fo\"o","bar"),("b\\ar","baz"),("baz","\"value\\with\"escapes")] :: Map Text Text)
264− roundTrip (V.fromList [1,2,3,4,5::Int])
265− roundTrip ("foo" :: Text)
266− roundTrip (42 :: Int)
267− where
268− roundTrip :: (Eq a, Show a, Typeable a, ToJSON a, FromJSON a)=> a -> Assertion
269− roundTrip x = do
270− y <- query conn "SELECT ?::json" (Only (Aeson x))
271− [Only (Aeson x)] @?= y
272−
273−testDerivingVia :: TestEnv -> Assertion
274−testDerivingVia TestEnv{..} = do
275−#if __GLASGOW_HASKELL__ <806
276− return ()
277−#else
278− roundTrip $ DerivingVia1 42 "Meaning of Life"
279− where
280− roundTrip :: (Eq a, Show a, Typeable a, ToField a, FromField a)=> a -> Assertion
281− roundTrip x = do
282− y <- query conn "SELECT ?::json" (Only x)
283− [Only x] @?= y
284−
285−data DerivingVia1 = DerivingVia1 Int String
286− deriving stock (Eq, Show, Generic)
287− deriving anyclass (FromJSON, ToJSON)
288− deriving (ToField, FromField) via Aeson DerivingVia1
289−
290−#endif
291−
292−
293−testQM :: TestEnv -> Assertion
294−testQM TestEnv{..} = do
295− -- Just test on a single string
296− let testQuery' b = "testing for ?" <> b <> " and making sure "
297− testQueryDoubleQM = testQuery' "?"
298− testQueryRest = "? is substituted"
299− testQuery = fromString $ testQueryDoubleQM <> testQueryRest
300− -- expect the entire first part with double QMs replaced with literal '?'
301− expected = (fromString $ testQuery' "", fromString testQueryRest)
302− tried = breakOnSingleQuestionMark testQuery
303− errMsg = concat
304− [ "Failed to break on single question mark exclusively:\n"
305− , "expected: ", show expected
306− , "result: ", show tried
307− ]
308− assertBool errMsg $ tried == expected
309−
310− -- Let's also test the question mark operators in action
311− -- ? -> Does the string exist as a top-level key within the JSON value?
312− positiveQuery "SELECT ?::jsonb ?? ?" (testObj, "foo" :: Text)
313− negativeQuery "SELECT ?::jsonb ?? ?" (testObj, "baz" :: Text)
314− negativeQuery "SELECT ?::jsonb ?? ?" (toJSON numArray, "1" :: Text)
315− -- ?| -> Do any of these array strings exist as top-level keys?
316− positiveQuery "SELECT ?::jsonb ??| ?" (testObj, PGArray ["nope","bar","6" :: Text])
317− negativeQuery "SELECT ?::jsonb ??| ?" (testObj, PGArray ["nope","6" :: Text])
318− negativeQuery "SELECT ?::jsonb ??| ?" (toJSON numArray, PGArray ["1","2","6" :: Text])
319− -- ?& -> Do all of these array strings exist as top-level keys?
320− positiveQuery "SELECT ?::jsonb ??& ?" (testObj, PGArray ["foo","bar","quux" :: Text])
321− positiveQuery "SELECT ?::jsonb ??& ?" (testObj, PGArray ["foo","bar" :: Text])
322− negativeQuery "SELECT ?::jsonb ??& ?" (testObj, PGArray ["foo","bar","baz" :: Text])
323− negativeQuery "SELECT ?::jsonb ??& ?" (toJSON numArray, PGArray ["1","2","3","4","5" :: Text])
324− -- Format error for 2 question marks, not 4
325− True <- expectError (isFormatError 2) $
326− (query conn "SELECT ?::jsonb ?? ?" $ Only testObj :: IO [Only Bool])
327− return ()
328− where positiveQuery :: ToRow a => Query -> a -> Assertion
329− positiveQuery = boolQuery True
330− negativeQuery :: ToRow a => Query -> a -> Assertion
331− negativeQuery = boolQuery False
332− numArray :: [Int]
333− numArray = [1,2,3,4,5]
334− boolQuery :: ToRow a => Bool -> Query -> a -> Assertion
335− boolQuery b t x = do
336− a <- query conn t x
337− [Only b] @?= a
338− testObj = toJSON (Map.fromList [("foo",toJSON (1 :: Int))
339− ,("bar",String "baz")
340− ,("quux",toJSON [1 :: Int,2,3,4,5])] :: Map Text Value
341− )
342−
343testSavepoint :: TestEnv -> Assertion
208testSavepoint :: TestEnv -> Assertion
344testSavepoint TestEnv{..} = do
209testSavepoint TestEnv{..} = do
345 True <- expectError ST.isNoActiveTransactionError $
210 True <- expectError ST.isNoActiveTransactionError $
@@ -447,14 +312,6 @@ testCopy TestEnv{..} = do
447 -- so that we can issue more queries:
312 -- so that we can issue more queries:
448 [Only (x::Int)] <- query_ conn "SELECT 2 + 2"
313 [Only (x::Int)] <- query_ conn "SELECT 2 + 2"
449 x @?= 4
314 x @?= 4
450− -- foldCopyData
451− copy_ conn "COPY copy_test TO STDOUT (FORMAT CSV)"
452− (acc, count) <- foldCopyData conn
453− (\acc row -> return (row:acc))
454− (\acc count -> return (acc, count))
455− []
456− sort acc @?= sort copyRows
457− count @?= 2
458 where
315 where
459 copyRows = ["1,foo\n"
316 copyRows = ["1,foo\n"
460 ,"2,bar\n"]
317 ,"2,bar\n"]
@@ -468,19 +325,16 @@ testCopy TestEnv{..} = do
468testCopyFailures :: TestEnv -> TestTree
325testCopyFailures :: TestEnv -> TestTree
469testCopyFailures env = testGroup "Copy failures"
326testCopyFailures env = testGroup "Copy failures"
470 $ map ($ env)
327 $ map ($ env)
471− [ testCopyUniqueConstraintError
328+ [ testCopyUniqueConstraintError ]
472− , testCopyMalformedError
473− ]
474
329
475goldenTest :: TestName -> IO BL.ByteString -> TestTree
330goldenTest :: TestName -> IO BL.ByteString -> TestTree
476goldenTest testName =
331goldenTest testName =
477− goldenVsStringDiff testName diff (resultsDir </> fileName<.>"expected")
332+ goldenVsString testName (resultsDir </> fileName<.>"expected")
478 where
333 where
479 resultsDir = "test" </> "results"
334 resultsDir = "test" </> "results"
480 fileName = map normalize testName
335 fileName = map normalize testName
481 normalize c | not (isAlpha c) = '-'
336 normalize c | not (isAlpha c) = '-'
482 | otherwise = c
337 | otherwise = c
483− diff ref new = ["diff", "-u", ref, new]
484
338
485-- | Test that we provide a sensible error message on failure
339-- | Test that we provide a sensible error message on failure
486testCopyUniqueConstraintError :: TestEnv -> TestTree
340testCopyUniqueConstraintError :: TestEnv -> TestTree
@@ -497,36 +351,6 @@ testCopyUniqueConstraintError TestEnv{..} =
497 ,"2,bar\n"
351 ,"2,bar\n"
498 ,"1,baz\n"]
352 ,"1,baz\n"]
499
353
500−testCopyMalformedError :: TestEnv -> TestTree
501−testCopyMalformedError TestEnv{..} =
502− goldenTest "malformed input"
503− $ handle (\(SomeException exc) -> return $ BL.pack $ show exc) $ do
504− execute_ conn "CREATE TEMPORARY TABLE copy_malformed_input_error_test (x int PRIMARY KEY, y text)"
505− copy_ conn "COPY copy_unique_constraint_error_test FROM STDIN (FORMAT CSV)"
506− mapM_ (putCopyData conn) copyRows
507− _n <- putCopyEnd conn
508− return BL.empty
509− where
510− copyRows = ["1,foo\n"
511− ,"2,bar\n"
512− ,"z,baz\n"]
513−
514−testTimeout :: TestEnv -> Assertion
515−testTimeout TestEnv{..} =
516− withConn $ \c -> do
517− start_t <- getCurrentTime
518− res <- timeout 200000 $ do
519− withTransaction c $ do
520− query_ c "SELECT pg_sleep(1)" :: IO [Only ()]
521− end_t <- getCurrentTime
522− assertBool "Timeout did not occur" (res == Nothing)
523−#if !defined(mingw32_HOST_OS)
524−-- At the moment, you cannot timely abandon queries with async exceptions on
525−-- Windows.
526− let d = end_t `diffUTCTime` start_t
527− assertBool "Timeout didn't work in a timely fashion" (0.1 < d && d < 0.6)
528−#endif
529−
530testDouble :: TestEnv -> Assertion
354testDouble :: TestEnv -> Assertion
531testDouble TestEnv{..} = do
355testDouble TestEnv{..} = do
532 [Only (x :: Double)] <- query_ conn "SELECT 'NaN'::float8"
356 [Only (x :: Double)] <- query_ conn "SELECT 'NaN'::float8"
@@ -593,56 +417,24 @@ isUniqueViolation SqlError{..} = sqlState == "23505"
593isSyntaxError :: SqlError -> Bool
417isSyntaxError :: SqlError -> Bool
594isSyntaxError SqlError{..} = sqlState == "42601"
418isSyntaxError SqlError{..} = sqlState == "42601"
595
419
596−isFormatError :: Int -> FormatError -> Bool
597−isFormatError i FormatError{..}
598− | null fmtMessage = False
599− | otherwise = fmtMessage == concat [ show i
600− , " single '?' characters, but "
601− , show (length fmtParams)
602− , " parameters"
603− ]
604------------------------------------------------------------------------
420------------------------------------------------------------------------
605
421
606-- | Action for connecting to the database that will be used for testing.
422-- | Action for connecting to the database that will be used for testing.
607--
423--
608-- Note that some tests, such as Notify, use multiple connections, and assume
424-- Note that some tests, such as Notify, use multiple connections, and assume
609-- that 'testConnect' connects to the same database every time it is called.
425-- that 'testConnect' connects to the same database every time it is called.
610−withTestEnv :: ByteString -> (TestEnv -> IO a) -> IO a
426+testConnect :: IO Connection
611−withTestEnv connstr cb =
427+testConnect = connectPostgreSQL ""
612− withConn $ \conn -> do
613− -- currently required for interval to work.
614− -- we also test that this doesn't interfere with anything else
615− execute_ conn "SET intervalstyle TO 'iso_8601'"
616
428
429+withTestEnv :: (TestEnv -> IO a) -> IO a
430+withTestEnv cb =
431+ withConn $ \conn ->
617 cb TestEnv
432 cb TestEnv
618 { conn = conn
433 { conn = conn
619 , withConn = withConn
434 , withConn = withConn
620 }
435 }
621 where
436 where
622− withConn = bracket (connectPostgreSQL connstr) close
437+ withConn = bracket testConnect close
623
438
624main :: IO ()
439main :: IO ()
625−main = withConnstring $ \connstring -> do
626− withTestEnv connstring (defaultMain . tests)
440+main = withTestEnv $ defaultMain . tests
627−
628−withConnstring :: (BS8.ByteString -> IO ()) -> IO ()
629−withConnstring kont = do
630− env <- getEnvironment
631− case lookup "DATABASE_CONNSTRING" env of
632− Just s -> kont (BS8.pack (special s))
633− Nothing -> case lookup "GITHUB_ACTIONS" env of
634− Just "true" -> kont (BS8.pack gha)
635− _ -> putStrLn "Set DATABASE_CONNSTRING environment variable"
636− where
637− -- https://www.appveyor.com/docs/services-databases/
638− special "appveyor" = "dbname='TestDb' user='postgres' password='Password12!'"
639− special "travis" = ""
640− special s = s
641−
642− gha = unwords
643− [ "dbname='postgres'"
644− , "user='postgres'"
645− , "password='postgres'"
646− , "host='postgres'"
647− , "port=5432"
648− ]
test/Time.hs+1−1
@@ -36,7 +36,7 @@ module Time (testTime) where
36
36
37import Common
37import Common
38import Control.Monad(forM_, replicateM_)
38import Control.Monad(forM_, replicateM_)
39−import Data.Time.Compat
39+import Data.Time
40import Data.ByteString(ByteString)
40import Data.ByteString(ByteString)
41import Database.PostgreSQL.Simple.SqlQQ
41import Database.PostgreSQL.Simple.SqlQQ
42
42
test/results/malformed-input.expecteddeleted−4
@@ -1,4 +0,0 @@
1−user error (Database.PostgreSQL.Simple.Copy.putCopyEnd: failed to parse command status
2−Connection error: ERROR: invalid input syntax for type integer: "z"
3−CONTEXT: COPY copy_unique_constraint_error_test, line 3, column x: "z"
4−)
tools/GenTypeInfo.hs+25−39
@@ -21,9 +21,6 @@
21-- know about. It then constructs a TypeInfo record and stores it in
21-- know about. It then constructs a TypeInfo record and stores it in
22-- a per-connection cache for later use.
22-- a per-connection cache for later use.
23--
23--
24−-- @
25−-- runghc -itools tools/GenTypeInfo.hs
26−-- @
27------------------------------------------------------------------------------
24------------------------------------------------------------------------------
28
25
29{-# LANGUAGE OverloadedStrings, QuasiQuotes, ViewPatterns, RecordWildCards #-}
26{-# LANGUAGE OverloadedStrings, QuasiQuotes, ViewPatterns, RecordWildCards #-}
@@ -41,10 +38,12 @@ import Database.PostgreSQL.Simple.FromRow
41import Database.PostgreSQL.Simple.Ok
38import Database.PostgreSQL.Simple.Ok
42import Database.PostgreSQL.Simple.Types(Oid(..))
39import Database.PostgreSQL.Simple.Types(Oid(..))
43import Database.PostgreSQL.Simple.SqlQQ
40import Database.PostgreSQL.Simple.SqlQQ
44−import qualified Data.ByteString.Char8 as B8
41+import qualified Data.ByteString.Char8 as B
45import Data.ByteString(ByteString)
42import Data.ByteString(ByteString)
46import qualified Data.ByteString.Lazy as L
43import qualified Data.ByteString.Lazy as L
47−import qualified Data.ByteString.Builder as Blaze
44+import qualified Blaze.ByteString.Builder as Blaze
45+import qualified Blaze.ByteString.Builder.ByteString as Blaze
46+import qualified Blaze.ByteString.Builder.Char8 as Blaze
48import Data.String
47import Data.String
49import Data.List ( sort, intersperse )
48import Data.List ( sort, intersperse )
50import qualified Data.Map as Map
49import qualified Data.Map as Map
@@ -70,11 +69,11 @@ data TypeInfo = TypeInfo
70instance FromRow TypeInfo where
69instance FromRow TypeInfo where
71 fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field <*> field
70 fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field <*> field
72
71
73−type NameMap = Map.Map B8.ByteString TypeInfo
72+type NameMap = Map.Map B.ByteString TypeInfo
74
73
75type OidMap = Map.Map Oid TypeInfo
74type OidMap = Map.Map Oid TypeInfo
76
75
77−type TypeName = (B8.ByteString, B8.ByteString)
76+type TypeName = (B.ByteString, B.ByteString)
78
77
79type TypeNames = [TypeName]
78type TypeNames = [TypeName]
80
79
@@ -198,6 +197,9 @@ int8range
198_int8range
197_int8range
199|]
198|]
200
199
200+instance IsString Blaze.Builder where
201+ fromString = Blaze.fromByteString . fromString
202+
201connectionString = "dbname=postgres"
203connectionString = "dbname=postgres"
202
204
203withPostgreSQL = bracket (connectPostgreSQL connectionString) close
205withPostgreSQL = bracket (connectPostgreSQL connectionString) close
@@ -235,7 +237,7 @@ getTypeInfos typnames = withPostgreSQL $ \conn -> do
235
237
236main = do
238main = do
237 (oidmap, namemap) <- getTypeInfos typeNames
239 (oidmap, namemap) <- getTypeInfos typeNames
238− L.writeFile "src/Database/PostgreSQL/Simple/TypeInfo/Static.hs"
240+ L.writeFile "../src/Database/PostgreSQL/Simple/TypeInfo/Static.hs"
239 (Blaze.toLazyByteString (renderFile oidmap namemap typeNames))
241 (Blaze.toLazyByteString (renderFile oidmap namemap typeNames))
240
242
241
243
@@ -244,7 +246,7 @@ showOid (Oid n) = show n
244renderOid :: NameMap -> TypeName -> Blaze.Builder
246renderOid :: NameMap -> TypeName -> Blaze.Builder
245renderOid byName name
247renderOid byName name
246 = case Map.lookup (pg name) byName of
248 = case Map.lookup (pg name) byName of
247− Nothing -> error (B8.unpack (pg name))
249+ Nothing -> error (B.unpack (pg name))
248 Just (showOid . typoid -> n) -> fromString n
250 Just (showOid . typoid -> n) -> fromString n
249 ++ fromString (replicate (4 - length n) ' ')
251 ++ fromString (replicate (4 - length n) ' ')
250
252
@@ -262,25 +264,20 @@ renderTypeInfo byOid info name
262 typelem_hs_name =
264 typelem_hs_name =
263 case lookup (typname typelem_info) typeNames of
265 case lookup (typname typelem_info) typeNames of
264 Nothing -> error ( "type not found: "
266 Nothing -> error ( "type not found: "
265− ++ B8.unpack( typname typelem_info)
267+ ++ B.unpack( typname typelem_info)
266− ++ " (typelem of " ++ B8.unpack (typname info)
268+ ++ " (typelem of " ++ B.unpack (typname info)
267 ++ ")")
269 ++ ")")
268 Just x -> x
270 Just x -> x
269 in concat
271 in concat
270 [ "\n"
272 [ "\n"
271 , bs (hs name), " :: TypeInfo\n"
273 , bs (hs name), " :: TypeInfo\n"
272 , bs (hs name), " = Array {\n"
274 , bs (hs name), " = Array {\n"
273− , " typoid = ", bs (hs name), "Oid,\n"
275+ , " typoid = ", fromString (show (typoid info)), ",\n"
274− , " typcategory = '", bs $ B8.singleton (typcategory info), "',\n"
276+ , " typcategory = '", Blaze.fromChar (typcategory info), "',\n"
275− , " typdelim = '", bs $ B8.singleton (typdelim info), "',\n"
277+ , " typdelim = '", Blaze.fromChar (typdelim info), "',\n"
276 , " typname = \"", bs (typname info), "\",\n"
278 , " typname = \"", bs (typname info), "\",\n"
277 , " typelem = ", bs typelem_hs_name, "\n"
279 , " typelem = ", bs typelem_hs_name, "\n"
278 , " }\n"
280 , " }\n"
279− , "\n"
280− , bs (hs name), "Oid :: Oid\n"
281− , bs (hs name), "Oid = ", fromString (show (typoid info)), "\n"
282− , "{-# INLINE ", bs (hs name), "Oid #-}"
283− , "\n"
284 ]
281 ]
285 | typcategory info == 'R' =
282 | typcategory info == 'R' =
286 let (Just rngsubtype_oid) = rngsubtype info
283 let (Just rngsubtype_oid) = rngsubtype info
@@ -288,41 +285,31 @@ renderTypeInfo byOid info name
288 rngsubtype_hs_name =
285 rngsubtype_hs_name =
289 case lookup (typname rngsubtype_info) typeNames of
286 case lookup (typname rngsubtype_info) typeNames of
290 Nothing -> error ( "type not found: "
287 Nothing -> error ( "type not found: "
291− ++ B8.unpack (typname rngsubtype_info)
288+ ++ B.unpack (typname rngsubtype_info)
292 ++ " (rngsubtype of "
289 ++ " (rngsubtype of "
293− ++ B8.unpack (typname info) ++ ")")
290+ ++ B.unpack (typname info) ++ ")")
294 Just x -> x
291 Just x -> x
295 in concat
292 in concat
296 [ "\n"
293 [ "\n"
297 , bs (hs name), " :: TypeInfo\n"
294 , bs (hs name), " :: TypeInfo\n"
298 , bs (hs name), " = Range {\n"
295 , bs (hs name), " = Range {\n"
299− , " typoid = ", bs (hs name), "Oid,\n"
296+ , " typoid = ", fromString (show (typoid info)), ",\n"
300− , " typcategory = '", bs $ B8.singleton (typcategory info), "',\n"
297+ , " typcategory = '", Blaze.fromChar (typcategory info), "',\n"
301− , " typdelim = '", bs $ B8.singleton (typdelim info), "',\n"
298+ , " typdelim = '", Blaze.fromChar (typdelim info), "',\n"
302 , " typname = \"", bs (typname info), "\",\n"
299 , " typname = \"", bs (typname info), "\",\n"
303 , " rngsubtype = ", bs rngsubtype_hs_name, "\n"
300 , " rngsubtype = ", bs rngsubtype_hs_name, "\n"
304 , " }\n"
301 , " }\n"
305− , "\n"
306− , bs (hs name), "Oid :: Oid\n"
307− , bs (hs name), "Oid = ", fromString (show (typoid info)), "\n"
308− , "{-# INLINE ", bs (hs name), "Oid #-}"
309− , "\n"
310 ]
302 ]
311 | otherwise =
303 | otherwise =
312 concat
304 concat
313 [ "\n"
305 [ "\n"
314 , bs (hs name), " :: TypeInfo\n"
306 , bs (hs name), " :: TypeInfo\n"
315 , bs (hs name), " = Basic {\n"
307 , bs (hs name), " = Basic {\n"
316− , " typoid = ", bs (hs name), "Oid,\n"
308+ , " typoid = ", fromString (show (typoid info)), ",\n"
317− , " typcategory = '", bs $ B8.singleton (typcategory info), "',\n"
309+ , " typcategory = '", Blaze.fromChar (typcategory info), "',\n"
318− , " typdelim = '", bs $ B8.singleton (typdelim info), "',\n"
310+ , " typdelim = '", Blaze.fromChar (typdelim info), "',\n"
319 , " typname = \"", bs (typname info), "\"\n"
311 , " typname = \"", bs (typname info), "\"\n"
320 , " }\n"
312 , " }\n"
321− , "\n"
322− , bs (hs name), "Oid :: Oid\n"
323− , bs (hs name), "Oid = ", fromString (show (typoid info)), "\n"
324− , "{-# INLINE ", bs (hs name), "Oid #-}"
325− , "\n"
326 ]
313 ]
327
314
328-- FIXME: add in any names that we need that we didn't specify, (i.e.
315-- FIXME: add in any names that we need that we didn't specify, (i.e.
@@ -331,7 +318,7 @@ renderTypeInfo byOid info name
331getNames :: NameMap -> TypeNames -> TypeNames
318getNames :: NameMap -> TypeNames -> TypeNames
332getNames _ x = x
319getNames _ x = x
333
320
334−bs = Blaze.byteString
321+bs = Blaze.fromByteString
335
322
336pg = fst
323pg = fst
337
324
@@ -360,7 +347,6 @@ module Database.PostgreSQL.Simple.TypeInfo.Static
360 ( TypeInfo(..)
347 ( TypeInfo(..)
361 , staticTypeInfo
348 , staticTypeInfo
362|] ++ concat [ " , " ++ bs (hs name) ++ "\n"
349|] ++ concat [ " , " ++ bs (hs name) ++ "\n"
363− ++ " , " ++ bs (hs name) ++ "Oid\n"
364 | name <- names ] ++ [longstring|
350 | name <- names ] ++ [longstring|
365 ) where
351 ) where
366
352