Skip to content

Commit 75872bf

Browse files
committed
Introduce on-demand connection acquisition mode
1 parent 203e557 commit 75872bf

File tree

12 files changed

+538
-356
lines changed

12 files changed

+538
-356
lines changed

.github/workflows/haskell-ci.yml

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
#
99
# For more information, see https://github.com/haskell-CI/haskell-ci
1010
#
11-
# version: 0.19.20250216
11+
# version: 0.19.20250821
1212
#
13-
# REGENDATA ("0.19.20250216",["github","--config=cabal.haskell-ci","cabal.project"])
13+
# REGENDATA ("0.19.20250821",["github","--config=cabal.haskell-ci","cabal.project"])
1414
#
1515
name: Haskell-CI
1616
on:
@@ -38,24 +38,29 @@ jobs:
3838
strategy:
3939
matrix:
4040
include:
41-
- compiler: ghc-9.12.1
41+
- compiler: ghc-9.14.0.20250819
4242
compilerKind: ghc
43-
compilerVersion: 9.12.1
43+
compilerVersion: 9.14.0.20250819
44+
setup-method: ghcup-prerelease
45+
allow-failure: false
46+
- compiler: ghc-9.12.2
47+
compilerKind: ghc
48+
compilerVersion: 9.12.2
4449
setup-method: ghcup
4550
allow-failure: false
46-
- compiler: ghc-9.10.1
51+
- compiler: ghc-9.10.2
4752
compilerKind: ghc
48-
compilerVersion: 9.10.1
53+
compilerVersion: 9.10.2
4954
setup-method: ghcup
5055
allow-failure: false
5156
- compiler: ghc-9.8.4
5257
compilerKind: ghc
5358
compilerVersion: 9.8.4
5459
setup-method: ghcup
5560
allow-failure: false
56-
- compiler: ghc-9.6.6
61+
- compiler: ghc-9.6.7
5762
compilerKind: ghc
58-
compilerVersion: 9.6.6
63+
compilerVersion: 9.6.7
5964
setup-method: ghcup
6065
allow-failure: false
6166
- compiler: ghc-9.4.8
@@ -87,12 +92,12 @@ jobs:
8792
- name: Install GHCup
8893
run: |
8994
mkdir -p "$HOME/.ghcup/bin"
90-
curl -sL https://downloads.haskell.org/ghcup/0.1.30.0/x86_64-linux-ghcup-0.1.30.0 > "$HOME/.ghcup/bin/ghcup"
95+
curl -sL https://downloads.haskell.org/ghcup/0.1.50.1/x86_64-linux-ghcup-0.1.50.1 > "$HOME/.ghcup/bin/ghcup"
9196
chmod a+x "$HOME/.ghcup/bin/ghcup"
9297
- name: Install cabal-install
9398
run: |
94-
"$HOME/.ghcup/bin/ghcup" install cabal 3.12.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
95-
echo "CABAL=$HOME/.ghcup/bin/cabal-3.12.1.0 -vnormal+nowrap" >> "$GITHUB_ENV"
99+
"$HOME/.ghcup/bin/ghcup" install cabal 3.16.0.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
100+
echo "CABAL=$HOME/.ghcup/bin/cabal-3.16.0.0 -vnormal+nowrap" >> "$GITHUB_ENV"
96101
- name: Install GHC (GHCup)
97102
if: matrix.setup-method == 'ghcup'
98103
run: |
@@ -107,6 +112,21 @@ jobs:
107112
HCKIND: ${{ matrix.compilerKind }}
108113
HCNAME: ${{ matrix.compiler }}
109114
HCVER: ${{ matrix.compilerVersion }}
115+
- name: Install GHC (GHCup prerelease)
116+
if: matrix.setup-method == 'ghcup-prerelease'
117+
run: |
118+
"$HOME/.ghcup/bin/ghcup" config add-release-channel prereleases
119+
"$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false)
120+
HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER")
121+
HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#')
122+
HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#')
123+
echo "HC=$HC" >> "$GITHUB_ENV"
124+
echo "HCPKG=$HCPKG" >> "$GITHUB_ENV"
125+
echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV"
126+
env:
127+
HCKIND: ${{ matrix.compilerKind }}
128+
HCNAME: ${{ matrix.compiler }}
129+
HCVER: ${{ matrix.compilerVersion }}
110130
- name: Set PATH and environment variables
111131
run: |
112132
echo "$HOME/.cabal/bin" >> $GITHUB_PATH
@@ -117,7 +137,7 @@ jobs:
117137
echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV"
118138
echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV"
119139
echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV"
120-
echo "HEADHACKAGE=false" >> "$GITHUB_ENV"
140+
if [ $((HCNUMVER >= 91400)) -ne 0 ] ; then echo "HEADHACKAGE=true" >> "$GITHUB_ENV" ; else echo "HEADHACKAGE=false" >> "$GITHUB_ENV" ; fi
121141
echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV"
122142
env:
123143
HCKIND: ${{ matrix.compilerKind }}
@@ -145,6 +165,18 @@ jobs:
145165
repository hackage.haskell.org
146166
url: http://hackage.haskell.org/
147167
EOF
168+
if $HEADHACKAGE; then
169+
cat >> $CABAL_CONFIG <<EOF
170+
repository head.hackage.ghc.haskell.org
171+
url: https://ghc.gitlab.haskell.org/head.hackage/
172+
secure: True
173+
root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d
174+
26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329
175+
f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89
176+
key-threshold: 3
177+
active-repositories: hackage.haskell.org, head.hackage.ghc.haskell.org:override
178+
EOF
179+
fi
148180
cat >> $CABAL_CONFIG <<EOF
149181
program-default-options
150182
ghc-options: $GHCJOBS +RTS -M3G -RTS
@@ -193,12 +225,19 @@ jobs:
193225
touch cabal.project.local
194226
echo "packages: ${PKGDIR_hpqtypes}" >> cabal.project
195227
echo "package hpqtypes" >> cabal.project
196-
echo " ghc-options: -Werror=missing-methods" >> cabal.project
228+
echo " ghc-options: -Werror=missing-methods -Werror=missing-fields" >> cabal.project
229+
if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo "package hpqtypes" >> cabal.project ; fi
230+
if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo " ghc-options: -Werror=unused-packages" >> cabal.project ; fi
231+
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then echo "package hpqtypes" >> cabal.project ; fi
232+
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then echo " ghc-options: -Werror=incomplete-patterns -Werror=incomplete-uni-patterns" >> cabal.project ; fi
197233
cat >> cabal.project <<EOF
198234
allow-newer: *:base
199235
allow-newer: *:ghc-prim
200236
allow-newer: *:template-haskell
201237
EOF
238+
if $HEADHACKAGE; then
239+
echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1,/g')" >> cabal.project
240+
fi
202241
$HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(hpqtypes)$/; }' >> cabal.project.local
203242
cat cabal.project
204243
cat cabal.project.local

hpqtypes.cabal

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ author: Scrive AB
2121
maintainer: Andrzej Rybczak <[email protected]>
2222
copyright: Scrive AB
2323
category: Database
24-
tested-with: GHC == { 8.10.7, 9.0.2, 9.2.8, 9.4.8, 9.6.6, 9.8.4, 9.10.1, 9.12.1 }
24+
tested-with: GHC == { 8.10.7, 9.0.2, 9.2.8, 9.4.8, 9.6.7, 9.8.4, 9.10.2, 9.12.2, 9.14.1 }
2525

2626
extra-source-files: README.md
2727
, CHANGELOG.md
@@ -171,6 +171,9 @@ library
171171
other-extensions: AllowAmbiguousTypes
172172
, CPP
173173

174+
if impl(ghc >= 9)
175+
default-extensions: DeepSubsumption
176+
174177
test-suite hpqtypes-tests
175178
type: exitcode-stdio-1.0
176179
ghc-options: -Wall -Wprepositive-qualified-module -threaded

src/Database/PostgreSQL/PQTypes/Class.hs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,34 @@ class (Applicative m, Monad m) => MonadDB m where
3030
-- given name.
3131
runPreparedQuery :: (HasCallStack, IsSQL sql) => QueryName -> sql -> m Int
3232

33-
-- | Get last SQL query that was executed.
34-
getLastQuery :: m SomeSQL
33+
-- | Get last SQL query that was executed and ID of the server process
34+
-- attached to the session that executed it.
35+
getLastQuery :: m (BackendPid, SomeSQL)
3536

3637
-- | Subsequent queries in the callback do not alter the result of
3738
-- 'getLastQuery'.
3839
withFrozenLastQuery :: m a -> m a
3940

40-
-- | Get ID of the server process attached to the current session.
41-
getBackendPid :: m BackendPid
42-
4341
-- | Get current connection statistics.
44-
getConnectionStats :: HasCallStack => m ConnectionStats
42+
getConnectionStats :: m ConnectionStats
4543

4644
-- | Get current query result.
4745
getQueryResult :: FromRow row => m (Maybe (QueryResult row))
4846

4947
-- | Clear current query result.
5048
clearQueryResult :: m ()
5149

52-
-- | Get current transaction settings.
53-
getTransactionSettings :: m TransactionSettings
50+
-- | Get current connection acquisition mode.
51+
getConnectionAcquisitionMode :: HasCallStack => m ConnectionAcquisitionMode
52+
53+
-- | Acquire and hold a connection with a given isolation level and
54+
-- permissions. If the connection is already held, nothing happens.
55+
acquireAndHoldConnection :: HasCallStack => IsolationLevel -> Permissions -> m ()
5456

55-
-- | Set transaction settings to supplied ones. Note that it
56-
-- won't change any properties of currently running transaction,
57-
-- only the subsequent ones.
58-
setTransactionSettings :: TransactionSettings -> m ()
57+
-- | Unsafely switch to the 'AcquireOnDemand' mode. This function is unsafe
58+
-- because if a connection is already held, the transaction in progress is
59+
-- commited, so atomicity guarantee is lost.
60+
unsafeAcquireOnDemandConnection :: HasCallStack => m ()
5961

6062
-- | Attempt to receive a notification from the server. This
6163
-- function waits until a notification arrives or specified
@@ -72,15 +74,15 @@ class (Applicative m, Monad m) => MonadDB m where
7274
-- for further info), therefore calling this function within
7375
-- a transaction block will return 'Just' only if notifications
7476
-- were received before the transaction began.
75-
getNotification :: Int -> m (Maybe Notification)
77+
getNotification :: HasCallStack => Int -> m (Maybe Notification)
7678

7779
-- | Execute supplied monadic action with new connection
7880
-- using current connection source and transaction settings.
7981
--
8082
-- Particularly useful when you want to spawn a new thread, but
8183
-- do not want the connection in child thread to be shared with
8284
-- the parent one.
83-
withNewConnection :: m a -> m a
85+
withNewConnection :: HasCallStack => m a -> m a
8486

8587
-- | Generic, overlappable instance.
8688
instance
@@ -97,11 +99,11 @@ instance
9799
runPreparedQuery name = withFrozenCallStack $ lift . runPreparedQuery name
98100
getLastQuery = lift getLastQuery
99101
withFrozenLastQuery m = controlT $ \run -> withFrozenLastQuery (run m)
100-
getBackendPid = lift getBackendPid
101-
getConnectionStats = withFrozenCallStack $ lift getConnectionStats
102+
getConnectionStats = lift getConnectionStats
102103
getQueryResult = lift getQueryResult
103104
clearQueryResult = lift clearQueryResult
104-
getTransactionSettings = lift getTransactionSettings
105-
setTransactionSettings = lift . setTransactionSettings
105+
getConnectionAcquisitionMode = lift getConnectionAcquisitionMode
106+
acquireAndHoldConnection isoLevel = lift . acquireAndHoldConnection isoLevel
107+
unsafeAcquireOnDemandConnection = lift unsafeAcquireOnDemandConnection
106108
getNotification = lift . getNotification
107109
withNewConnection m = controlT $ \run -> withNewConnection (run m)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
module Database.PostgreSQL.PQTypes.Internal.BackendPid
22
( BackendPid (..)
3+
, noBackendPid
34
) where
45

56
-- | Process ID of the server process attached to the current session.
67
newtype BackendPid = BackendPid Int
78
deriving newtype (Eq, Ord, Show)
9+
10+
noBackendPid :: BackendPid
11+
noBackendPid = BackendPid 0

0 commit comments

Comments
 (0)