1
- {-# LANGUAGE DeriveAnyClass #-}
2
- {-# LANGUAGE DeriveGeneric #-}
3
1
{-# LANGUAGE DerivingStrategies #-}
4
2
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5
3
{-# LANGUAGE RecordWildCards #-}
6
4
{-# LANGUAGE ScopedTypeVariables #-}
7
5
{-# LANGUAGE ViewPatterns #-}
8
6
9
7
module Database.Oracle.Simple.Transaction
10
- ( beginTransaction ,
8
+ (
9
+ DPIXid (.. ),
10
+ beginTransaction ,
11
11
commitTransaction ,
12
12
prepareCommit ,
13
13
withTransaction ,
@@ -19,12 +19,11 @@ import Control.Exception (catch, throw)
19
19
import Control.Monad (replicateM , void , when , (<=<) )
20
20
import Data.UUID (UUID , toString )
21
21
import Data.UUID.V4 (nextRandom )
22
- import Foreign (alloca , peek , poke , withForeignPtr )
22
+ import Foreign (alloca , withForeignPtr )
23
23
import Foreign.C.String (CString , withCStringLen )
24
24
import Foreign.C.Types (CInt (CInt ), CLong , CUInt (CUInt ))
25
- import Foreign.Ptr (Ptr )
26
- import Foreign.Storable.Generic (GStorable )
27
- import GHC.Generics (Generic )
25
+ import Foreign.Ptr (Ptr ,castPtr )
26
+ import Foreign.Storable (Storable (.. ))
28
27
import System.Random (getStdRandom , uniformR )
29
28
30
29
import Database.Oracle.Simple.Execute (execute_ )
@@ -141,8 +140,86 @@ data DPIXid = DPIXid
141
140
, dpixBranchQualifier :: CString
142
141
, dpixBranchQualifierLength :: CUInt
143
142
}
144
- deriving (Generic , Show )
145
- deriving anyclass (GStorable )
143
+ deriving (Show , Eq )
144
+
145
+ instance Storable DPIXid where
146
+ sizeOf _ =
147
+ let
148
+ -- Sizes of fields
149
+ sizeFormatId = sizeOf (undefined :: CLong )
150
+ sizeTransactionId = sizeOf (undefined :: CString )
151
+ sizeTransactionIdLength = sizeOf (undefined :: CUInt )
152
+ sizeQualifier = sizeOf (undefined :: CString )
153
+ sizeQualifierLength = sizeOf (undefined :: CUInt )
154
+
155
+ -- Alignments of fields
156
+ alignFormatId = alignment (undefined :: CLong )
157
+ alignTransactionId = alignment (undefined :: CString )
158
+ alignTransactionIdLength = alignment (undefined :: CUInt )
159
+ alignQualifier = alignment (undefined :: CString )
160
+ alignQualifierLength = alignment (undefined :: CUInt )
161
+
162
+ -- Padding for each field
163
+ paddingTransactionId = padding sizeFormatId alignTransactionId
164
+ paddingTransactionIdLength = padding (sizeTransactionId + paddingTransactionId) alignTransactionIdLength
165
+ paddingQualifier = padding (sizeTransactionIdLength + paddingTransactionIdLength) alignQualifier
166
+ paddingQualifierLength = padding (sizeQualifier + paddingQualifier) alignQualifierLength
167
+ in
168
+ sizeFormatId +
169
+ paddingTransactionId + sizeTransactionId +
170
+ paddingTransactionIdLength + sizeTransactionIdLength +
171
+ paddingQualifier + sizeQualifier +
172
+ paddingQualifierLength + sizeQualifierLength +
173
+ -- Final padding to align the structure itself
174
+ padding (sizeFormatId +
175
+ paddingTransactionId + sizeTransactionId +
176
+ paddingTransactionIdLength + sizeTransactionIdLength +
177
+ paddingQualifier + sizeQualifier +
178
+ paddingQualifierLength + sizeQualifierLength) alignFormatId
179
+
180
+ alignment _ = alignment (undefined :: CLong )
181
+
182
+ peek p = do
183
+ let basePtr = castPtr p
184
+ formatId <- peekByteOff basePtr 0
185
+
186
+ let offsetTransactionId = alignedOffset 0 (sizeOf (undefined :: CLong )) (alignment (undefined :: CString ))
187
+ transactionId <- peekByteOff basePtr offsetTransactionId
188
+
189
+ let offsetTransactionIdLength = offsetTransactionId + sizeOf (undefined :: CString )
190
+ transactionIdLength <- peekByteOff basePtr offsetTransactionIdLength
191
+
192
+ let offsetQualifier = alignedOffset offsetTransactionIdLength (sizeOf (undefined :: CUInt )) (alignment (undefined :: CString ))
193
+ qualifier <- peekByteOff basePtr offsetQualifier
194
+
195
+ let offsetQualifierLength = offsetQualifier + sizeOf (undefined :: CString )
196
+ qualifierLength <- peekByteOff basePtr offsetQualifierLength
197
+
198
+ return $ DPIXid formatId transactionId transactionIdLength qualifier qualifierLength
199
+
200
+ poke p (DPIXid formatId transactionId transactionIdLength qualifier qualifierLength) = do
201
+ let basePtr = castPtr p
202
+ pokeByteOff basePtr 0 formatId
203
+
204
+ let offsetTransactionId = alignedOffset 0 (sizeOf (undefined :: CLong )) (alignment (undefined :: CString ))
205
+ pokeByteOff basePtr offsetTransactionId transactionId
206
+
207
+ let offsetTransactionIdLength = offsetTransactionId + sizeOf (undefined :: CString )
208
+ pokeByteOff basePtr offsetTransactionIdLength transactionIdLength
209
+
210
+ let offsetQualifier = alignedOffset offsetTransactionIdLength (sizeOf (undefined :: CUInt )) (alignment (undefined :: CString ))
211
+ pokeByteOff basePtr offsetQualifier qualifier
212
+
213
+ let offsetQualifierLength = offsetQualifier + sizeOf (undefined :: CString )
214
+ pokeByteOff basePtr offsetQualifierLength qualifierLength
215
+
216
+ -- Helper to calculate padding between fields
217
+ padding :: Int -> Int -> Int
218
+ padding size align = (align - size `mod` align) `mod` align
219
+
220
+ -- Helper to calculate aligned offsets
221
+ alignedOffset :: Int -> Int -> Int -> Int
222
+ alignedOffset base size align = base + size + padding (base + size) align
146
223
147
224
withDPIXid :: Transaction -> (Ptr DPIXid -> IO a ) -> IO a
148
225
withDPIXid Transaction {.. } action =
0 commit comments