Skip to content

Commit 51b1e96

Browse files
committed
Added functions for object type for advance queuing
1 parent b496537 commit 51b1e96

File tree

5 files changed

+179
-19
lines changed

5 files changed

+179
-19
lines changed

src/Database/Oracle/Simple/FromField.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
{-# LANGUAGE RecordWildCards #-}
33
{-# LANGUAGE ScopedTypeVariables #-}
44
{-# LANGUAGE TypeApplications #-}
5+
{-# LANGUAGE RankNTypes #-}
56

67
module Database.Oracle.Simple.FromField
78
( FieldParser (..),
89
FromField (..),
910
ReadDPIBuffer,
1011
dpiTimeStampToUTCTime,
12+
getInt64,
13+
getFloat,
14+
getDouble,
15+
getString,
16+
getBool,
17+
getTimestamp,
1118
)
1219
where
1320

src/Database/Oracle/Simple/Internal.hs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,13 @@ module Database.Oracle.Simple.Internal
4545
ErrorInfo (..),
4646
VersionInfo (..),
4747
DPIJson (..),
48+
DPIObjectType (..),
49+
DPIObject (..),
4850
genJSON,
51+
genObject,
52+
getObjectType,
4953
renderErrorInfo,
54+
releaseObject,
5055
ping,
5156
fetch,
5257
close,
@@ -78,6 +83,7 @@ module Database.Oracle.Simple.Internal
7883
dpiData_getTimestamp,
7984
dpiConn_close_finalizer,
8085
dpiConn_release_finalizer,
86+
dpiNativeTypeToUInt,
8187
)
8288
where
8389

@@ -125,6 +131,14 @@ newtype DPIJson = DPIJson (Ptr DPIJson)
125131
deriving (Show, Eq)
126132
deriving newtype (Storable)
127133

134+
newtype DPIObjectType = DPIObjectType (Ptr DPIObjectType)
135+
deriving (Show, Eq)
136+
deriving newtype (Storable)
137+
138+
newtype DPIObject = DPIObject (Ptr DPIObject)
139+
deriving (Show, Eq)
140+
deriving newtype (Storable)
141+
128142
data AdditionalConnectionParams = AdditionalConnectionParams
129143
{ minSessions :: Natural
130144
, maxSessions :: Natural
@@ -1773,3 +1787,48 @@ foreign import ccall unsafe "dpiConn_newJson"
17731787
-- | dpiJSON **
17741788
Ptr DPIJson ->
17751789
IO CInt
1790+
1791+
getObjectType :: Connection -> String -> IO DPIObjectType
1792+
getObjectType (Connection fptr) objectName = do
1793+
withForeignPtr fptr $ \conn -> do
1794+
withCStringLen objectName $ \(objectNameC, fromIntegral -> objectNameLen) -> do
1795+
alloca $ \objectTypePtr -> do
1796+
throwOracleError =<< dpiConn_getObjectType conn objectNameC objectNameLen objectTypePtr
1797+
peek objectTypePtr
1798+
1799+
foreign import ccall unsafe "dpiConn_getObjectType"
1800+
dpiConn_getObjectType ::
1801+
-- | dpiConn *
1802+
Ptr DPIConn ->
1803+
-- | char * name
1804+
CString ->
1805+
-- | cuint32_t nameLength
1806+
CUInt ->
1807+
-- | dpiObjectType ** objType
1808+
Ptr DPIObjectType ->
1809+
IO CInt
1810+
1811+
genObject :: DPIObjectType -> IO DPIObject
1812+
genObject objType = do
1813+
alloca $ \objectPtr -> do
1814+
throwOracleError =<< dpiObjectType_createObject objType objectPtr
1815+
peek objectPtr
1816+
1817+
foreign import ccall unsafe "dpiObjectType_createObject"
1818+
dpiObjectType_createObject ::
1819+
-- | dpiObjectType *
1820+
DPIObjectType ->
1821+
-- | dpiObject ** obj
1822+
Ptr DPIObject ->
1823+
IO CInt
1824+
1825+
releaseObject :: DPIObject -> IO ()
1826+
releaseObject obj = do
1827+
throwOracleError =<< dpiObject_release obj
1828+
1829+
foreign import ccall unsafe "dpiObject_release"
1830+
dpiObject_release ::
1831+
-- | dpiObject *
1832+
DPIObject ->
1833+
IO CInt
1834+

src/Database/Oracle/Simple/JSON.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
{-# LANGUAGE UndecidableInstances #-}
1010
{-# OPTIONS_GHC -Wno-missed-specialisations #-} -- suppressing fromFloatDigits warning
1111

12-
module Database.Oracle.Simple.JSON (AesonField (..), JsonDecodeError (..), DPIJsonNode(..)) where
12+
module Database.Oracle.Simple.JSON (AesonField (..), JsonDecodeError (..), DPIJsonNode(..), getJson) where
1313

1414
import Control.Exception (Exception (displayException), SomeException, catch, evaluate, throwIO)
1515
import Control.Monad (void, (<=<))

src/Database/Oracle/Simple/Queue.hs

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
{-# LANGUAGE DerivingStrategies #-}
22
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
33
{-# LANGUAGE ViewPatterns #-}
4+
{-# LANGUAGE TypeApplications #-}
5+
{-# LANGUAGE RankNTypes #-}
6+
{-# LANGUAGE RecordWildCards #-}
7+
{-# LANGUAGE ScopedTypeVariables #-}
48

59
module Database.Oracle.Simple.Queue (
610
DPIQueue (..)
711
, DPIMsgProps (..)
812
, DPIDeqOptions (..)
913
, DPIEnqOptions (..)
1014
, DPIObjectType (..)
11-
, ObjectType (..)
1215
, deqMany
1316
, deqOne
1417
, enqMany
1518
, enqOne
1619
, getDeqOptions
1720
, getEnqOptions
1821
, queueRelease
19-
, genJSONQueue
22+
, genQueueJSON
23+
, genQueueObject
2024
, genMsgProps
2125
, genQueue
2226
, getMsgPropsNumOfAttempts
2327
, getMsgPropsDelay
2428
, getMsgPropsPayLoadBytes
2529
, getMsgPropsPayLoadJson
30+
, getMsgPropsPayLoadObject
2631
, setMsgPropsPayLoadBytes
2732
, setMsgPropsPayLoadJSON
33+
, setMsgPropsPayLoadObject
34+
, objectAppendElement
35+
, getObjectElementByIdx
2836
) where
2937

3038
import Foreign (alloca, withArray, withForeignPtr, nullPtr)
@@ -33,7 +41,10 @@ import Foreign.C.Types (CInt (..), CUInt (..))
3341
import Foreign.Ptr (Ptr)
3442
import Foreign.C.String
3543
import Database.Oracle.Simple.Internal
44+
import Database.Oracle.Simple.ToField
45+
import Database.Oracle.Simple.FromField
3646
import qualified Data.ByteString.Char8 as BSC
47+
import Data.Proxy (Proxy (..))
3748

3849
newtype DPIQueue = DPIQueue (Ptr DPIQueue)
3950
deriving (Show, Eq)
@@ -51,13 +62,6 @@ newtype DPIEnqOptions = DPIEnqOptions (Ptr DPIEnqOptions)
5162
deriving (Show, Eq)
5263
deriving newtype (Storable)
5364

54-
newtype DPIObjectType = DPIObjectType (Ptr DPIObjectType)
55-
deriving (Show, Eq)
56-
deriving newtype (Storable)
57-
58-
data ObjectType = JSON | Raw
59-
deriving (Show, Eq)
60-
6165
deqMany :: DPIQueue -> Int -> IO DPIMsgProps
6266
deqMany dpiQueue numProps = do
6367
alloca $ \dpiMsgPropsPtr -> do
@@ -167,8 +171,8 @@ foreign import ccall unsafe "dpiQueue_release"
167171
DPIQueue ->
168172
IO CInt
169173

170-
genJSONQueue :: Connection -> String -> IO DPIQueue
171-
genJSONQueue (Connection fptr) queueName = do
174+
genQueueJSON :: Connection -> String -> IO DPIQueue
175+
genQueueJSON (Connection fptr) queueName = do
172176
withForeignPtr fptr $ \conn -> do
173177
alloca $ \dpiQueuePtr -> do
174178
withCStringLen queueName $ \(queueNameC , fromIntegral -> queueNameLen) -> do
@@ -202,14 +206,20 @@ foreign import ccall unsafe "dpiConn_newMsgProps"
202206
Ptr DPIMsgProps ->
203207
IO CInt
204208

205-
-- For now, Passing objectType will not work :( use setPayLoadType.
206209
genQueue :: Connection -> String -> IO DPIQueue
207210
genQueue (Connection fptr) queueName = do
208211
withForeignPtr fptr $ \conn -> do
209212
alloca $ \dpiQueuePtr -> do
210213
withCStringLen queueName $ \(queueNameC , fromIntegral -> queueNameLen) -> do
211214
throwOracleError =<< dpiConn_newQueue conn queueNameC queueNameLen nullPtr dpiQueuePtr
212-
-- TODO: Accomodate ObjectType
215+
peek dpiQueuePtr
216+
217+
genQueueObject :: Connection -> String -> DPIObjectType -> IO DPIQueue
218+
genQueueObject (Connection fptr) queueName (DPIObjectType objectType) = do
219+
withForeignPtr fptr $ \conn -> do
220+
alloca $ \dpiQueuePtr -> do
221+
withCStringLen queueName $ \(queueNameC , fromIntegral -> queueNameLen) -> do
222+
throwOracleError =<< dpiConn_newQueue conn queueNameC queueNameLen objectType dpiQueuePtr
213223
peek dpiQueuePtr
214224

215225
foreign import ccall unsafe "dpiConn_newQueue"
@@ -221,7 +231,7 @@ foreign import ccall unsafe "dpiConn_newQueue"
221231
-- | name Length
222232
CUInt ->
223233
-- | dpiObjectType *
224-
Ptr () ->
234+
Ptr DPIObjectType ->
225235
-- | dpiQueue **
226236
Ptr DPIQueue ->
227237
IO CInt
@@ -256,7 +266,6 @@ foreign import ccall unsafe "dpiMsgProps_getDelay"
256266
Ptr CUInt ->
257267
IO CInt
258268

259-
260269
{-
261270
This function internally calls getPayLoad which either returns payLoad in either Object or in bytes.
262271
Hence, the result might be null.
@@ -271,13 +280,21 @@ getMsgPropsPayLoadBytes dpiMsgProps = do
271280
if cStr == nullPtr
272281
then return Nothing
273282
else Just . BSC.pack <$> peekCString cStr
274-
283+
284+
getMsgPropsPayLoadObject :: DPIMsgProps -> IO (Maybe DPIObject)
285+
getMsgPropsPayLoadObject dpiMsgProps =
286+
alloca $ \dpiObjectPtr -> do
287+
throwOracleError =<< dpiMsgProps_getPayload dpiMsgProps dpiObjectPtr nullPtr nullPtr
288+
if dpiObjectPtr == nullPtr
289+
then return Nothing
290+
else Just <$> peek dpiObjectPtr
291+
275292
foreign import ccall unsafe "dpiMsgProps_getPayload"
276293
dpiMsgProps_getPayload ::
277294
-- | dpiMsgProps *
278295
DPIMsgProps ->
279296
-- | dpiObject **
280-
Ptr DPIObjectType ->
297+
Ptr DPIObject ->
281298
-- | const char ** value
282299
Ptr CString ->
283300
-- | valueLength
@@ -313,6 +330,18 @@ foreign import ccall unsafe "dpiMsgProps_setPayloadBytes"
313330
CUInt ->
314331
IO CInt
315332

333+
setMsgPropsPayLoadObject :: DPIMsgProps -> DPIObject-> IO ()
334+
setMsgPropsPayLoadObject dpiMsgProps obj = do
335+
throwOracleError =<< dpiMsgProps_setPayloadObject dpiMsgProps obj
336+
337+
foreign import ccall unsafe "dpiMsgProps_setPayloadObject"
338+
dpiMsgProps_setPayloadObject ::
339+
-- | dpiMsgProps *
340+
DPIMsgProps ->
341+
-- | dpiObject* obj
342+
DPIObject ->
343+
IO CInt
344+
316345
setMsgPropsPayLoadJSON :: DPIMsgProps -> DPIJson -> IO ()
317346
setMsgPropsPayLoadJSON dpiMsgProps payLoadJson = do
318347
throwOracleError =<< dpiMsgProps_setPayloadJson dpiMsgProps payLoadJson
@@ -324,3 +353,55 @@ foreign import ccall unsafe "dpiMsgProps_setPayloadJson"
324353
-- | dpiJson *
325354
DPIJson ->
326355
IO CInt
356+
357+
objectAppendElement :: forall a. (ToField a) => DPIObject -> a -> IO ()
358+
objectAppendElement obj val = do
359+
dataValue <- toField val
360+
let dataIsNull = case dataValue of
361+
AsNull -> 1
362+
_ -> 0
363+
alloca $ \dpiDataPtr -> do
364+
let dpiData = DPIData{..}
365+
poke dpiDataPtr (dpiData :: DPIData WriteBuffer)
366+
throwOracleError =<<
367+
dpiObject_appendElement
368+
obj
369+
(dpiNativeTypeToUInt (toDPINativeType (Proxy @a)))
370+
(dpiDataPtr :: Ptr (DPIData WriteBuffer))
371+
372+
foreign import ccall unsafe "dpiObject_appendElement"
373+
dpiObject_appendElement ::
374+
-- | dpiObject *
375+
DPIObject ->
376+
-- | dpiNativeTypeNum
377+
CUInt ->
378+
-- | dpiData* val
379+
Ptr (DPIData WriteBuffer) ->
380+
IO CInt
381+
382+
getObjectElementByIdx
383+
:: forall a. (FromField a) =>
384+
DPIObject ->
385+
Int ->
386+
IO a
387+
getObjectElementByIdx obj idx = do
388+
alloca $ \dpiDataPtr -> do
389+
throwOracleError =<<
390+
dpiObject_getElementExistsByIndex
391+
obj
392+
(CInt $ fromIntegral idx)
393+
(dpiNativeTypeToUInt (fromDPINativeType (Proxy @a)))
394+
dpiDataPtr
395+
readDPIDataBuffer (fromField @a) dpiDataPtr
396+
397+
foreign import ccall unsafe "dpiObject_getElementExistsByIndex"
398+
dpiObject_getElementExistsByIndex ::
399+
-- | dpiObject *
400+
DPIObject ->
401+
-- | int32_t index
402+
CInt ->
403+
-- | dpiNativeTypeNum
404+
CUInt ->
405+
-- | dpiData *
406+
Ptr (DPIData ReadBuffer) ->
407+
IO CInt

test/Main.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,13 @@ spec pool = do
395395
queue <- genQueue conn "test_queue"
396396
queueRelease queue
397397
-- No exception implies success
398+
398399
it "should set and get a msgProp payload" $ \conn -> do
399400
msgProps <- genMsgProps conn
400401
setMsgPropsPayLoadBytes msgProps (BSC.pack "Hello from Haskell!")
401402
payload <- getMsgPropsPayLoadBytes msgProps
402403
payload `shouldBe` Just "Hello from Haskell!"
403-
it "should enque and deque msg prop from queue" $ \conn -> do
404+
it "should enque and deque msg prop from queue for bytes" $ \conn -> do
404405
void $ execute_ conn "\
405406
\BEGIN\
406407
\ DBMS_AQADM.CREATE_QUEUE_TABLE(\
@@ -423,6 +424,18 @@ spec pool = do
423424
payload <- getMsgPropsPayLoadBytes newMsgProps
424425
payload `shouldBe` Just "Hello from Haskell!"
425426
queueRelease queue
427+
void $ execute_ conn "\
428+
\BEGIN\
429+
\ DBMS_AQADM.STOP_QUEUE(\
430+
\ queue_name => 'TEST_QUEUE'\
431+
\);\
432+
\ DBMS_AQADM.DROP_QUEUE(\
433+
\ queue_name => 'TEST_QUEUE'\
434+
\ );\
435+
\ DBMS_AQADM.DROP_QUEUE_TABLE(\
436+
\ queue_table => 'TEST_QUEUE_TABLE'\
437+
\ );\
438+
\END;"
426439
where
427440
handleOracleError action = Exc.try @OracleError action >>= either (\_ -> pure ()) (\_ -> pure ())
428441

0 commit comments

Comments
 (0)