{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Database.Oracle.OCIFunctions where
import Prelude hiding (catch)
import Database.Oracle.OCIConstants
import Database.Util
import Foreign
import Foreign.C
import Control.Monad
import Control.Exception
import Data.Dynamic
import Data.Time
import System.Time
data OCIStruct = OCIStruct
type OCIHandle = Ptr OCIStruct
data OCIBuffer = OCIBuffer
type BufferPtr = Ptr OCIBuffer
type BufferFPtr = ForeignPtr OCIBuffer
type ColumnResultBuffer = ForeignPtr OCIBuffer
type BindBuffer = (ForeignPtr CShort, ForeignPtr OCIBuffer, ForeignPtr CUShort)
data Context = Context
type ContextPtr = Ptr Context
data EnvStruct = EnvStruct
type EnvHandle = Ptr EnvStruct
data ErrorStruct = ErrorStruct
type ErrorHandle = Ptr ErrorStruct
data ServerStruct = ServerStruct
type ServerHandle = Ptr ServerStruct
data UserStruct = UserStruct
type UserHandle = Ptr UserStruct
data ConnStruct = ConnStruct
type ConnHandle = Ptr ConnStruct
data SessStruct = SessStruct
type SessHandle = Ptr SessStruct
data StmtStruct = StmtStruct
type StmtHandle = Ptr StmtStruct
data DefnStruct = DefnStruct
type DefnHandle = Ptr DefnStruct
data ParamStruct = ParamStruct
type ParamHandle = Ptr ParamStruct
data BindStruct = BindStruct
type BindHandle = Ptr BindStruct
type ColumnInfo = (DefnHandle, ColumnResultBuffer, ForeignPtr CShort, ForeignPtr CUShort)
data OCIException = OCIException CInt String
deriving (Typeable, Show)
catchOCI :: IO a -> (OCIException -> IO a) -> IO a
throwOCI :: OCIException -> a
instance Exception OCIException
catchOCI = catch
throwOCI = throw
mkCInt :: Int -> CInt
mkCInt n = fromIntegral n
mkCShort :: CInt -> CShort
mkCShort n = fromIntegral n
mkCUShort :: CInt -> CUShort
mkCUShort n = fromIntegral n
cStrLen :: CStringLen -> CInt
cStrLen = mkCInt . snd
cStr :: CStringLen -> CString
cStr = fst
foreign import ccall "OCIEnvCreate" ociEnvCreate :: Ptr EnvHandle -> CInt -> Ptr a -> FunPtr a -> FunPtr a -> FunPtr a -> CInt -> Ptr (Ptr a) -> IO CInt
foreign import ccall "OCIHandleAlloc" ociHandleAlloc :: OCIHandle -> Ptr OCIHandle -> CInt -> CInt -> Ptr a -> IO CInt
foreign import ccall "oci.h OCIHandleFree" ociHandleFree :: OCIHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCIErrorGet" ociErrorGet :: OCIHandle -> CInt -> CString -> Ptr CInt -> CString -> CInt -> CInt -> IO CInt
foreign import ccall "oci.h OCIParamGet" ociParamGet :: OCIHandle -> CInt -> ErrorHandle -> Ptr OCIHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCIAttrGet" ociAttrGet
:: OCIHandle -> CInt -> BufferPtr -> Ptr CInt -> CInt -> ErrorHandle -> IO CInt
foreign import ccall "oci.h OCIAttrSet" ociAttrSet
:: OCIHandle -> CInt -> BufferPtr -> CInt -> CInt -> ErrorHandle -> IO CInt
foreign import ccall "oci.h OCILogon" ociLogon
:: EnvHandle -> ErrorHandle -> Ptr ConnHandle -> CString -> CInt -> CString -> CInt -> CString -> CInt -> IO CInt
foreign import ccall "oci.h OCILogoff" ociLogoff :: ConnHandle -> ErrorHandle -> IO CInt
foreign import ccall "oci.h OCISessionBegin" ociSessionBegin :: ConnHandle -> ErrorHandle -> SessHandle -> CInt -> CInt -> IO CInt
foreign import ccall "oci.h OCISessionEnd" ociSessionEnd :: ConnHandle -> ErrorHandle -> SessHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCIServerAttach" ociServerAttach :: ServerHandle -> ErrorHandle -> CString -> CInt -> CInt -> IO CInt
foreign import ccall "oci.h OCIServerDetach" ociServerDetach :: ServerHandle -> ErrorHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCITerminate" ociTerminate :: CInt -> IO CInt
foreign import ccall "oci.h OCITransStart" ociTransStart :: ConnHandle -> ErrorHandle -> Word8 -> CInt -> IO CInt
foreign import ccall "oci.h OCITransCommit" ociTransCommit :: ConnHandle -> ErrorHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCITransRollback" ociTransRollback :: ConnHandle -> ErrorHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCIStmtPrepare" ociStmtPrepare :: StmtHandle -> ErrorHandle -> CString -> CInt -> CInt -> CInt -> IO CInt
foreign import ccall "oci.h OCIDefineByPos" ociDefineByPos
:: StmtHandle -> Ptr DefnHandle -> ErrorHandle -> CInt -> BufferPtr -> CInt -> CUShort -> Ptr CShort -> Ptr CUShort -> Ptr CUShort -> CInt -> IO CInt
foreign import ccall "oci.h OCIStmtExecute" ociStmtExecute :: ConnHandle -> StmtHandle -> ErrorHandle -> CInt -> CInt -> OCIHandle -> OCIHandle -> CInt -> IO CInt
foreign import ccall "oci.h OCIStmtFetch" ociStmtFetch :: StmtHandle -> ErrorHandle -> CInt -> CShort -> CInt -> IO CInt
foreign import ccall "oci.h OCIBindByPos" ociBindByPos ::
StmtHandle
-> Ptr BindHandle
-> ErrorHandle
-> CUInt
-> BufferPtr
-> CInt
-> CUShort
-> Ptr CShort
-> Ptr CUShort
-> Ptr CUShort
-> CUInt
-> Ptr CUInt
-> CUInt
-> IO CInt
foreign import ccall "oci.h OCIBindDynamic" ociBindDynamic ::
BindHandle -> ErrorHandle -> ContextPtr -> FunPtr OCICallbackInBind
-> ContextPtr -> FunPtr OCICallbackOutBind -> IO CInt
type OCICallbackInBind = ContextPtr -> BindHandle -> CInt -> CInt
-> Ptr BufferPtr -> CInt -> Ptr Word8 -> Ptr CShort -> IO CInt
type OCICallbackOutBind = ContextPtr -> BindHandle -> CInt -> CInt
-> Ptr BufferPtr -> Ptr CInt -> Ptr Word8 -> Ptr CShort -> Ptr (Ptr CShort) -> IO CInt
foreign import ccall "wrapper" mkOCICallbackInBind ::
OCICallbackInBind -> IO (FunPtr OCICallbackInBind)
foreign import ccall "wrapper" mkOCICallbackOutBind ::
OCICallbackOutBind -> IO (FunPtr OCICallbackOutBind)
getOCIErrorMsg2 :: OCIHandle -> CInt -> Ptr CInt -> CString -> CInt -> IO (CInt, String)
getOCIErrorMsg2 ocihandle handleType errCodePtr errMsgBuf maxErrMsgLen = do
rc <- ociErrorGet ocihandle 1 nullPtr errCodePtr errMsgBuf maxErrMsgLen handleType
if rc < 0
then return (0, "Error message not available.")
else do
msg <- peekCString errMsgBuf
e <- peek errCodePtr
return (e, msg)
getOCIErrorMsg :: OCIHandle -> CInt -> IO (CInt, String)
getOCIErrorMsg ocihandle handleType = do
let stringBufferLen = 1000
allocaBytes stringBufferLen $ \errMsg ->
alloca $ \errCode ->
getOCIErrorMsg2 ocihandle handleType errCode errMsg (mkCInt stringBufferLen)
fromEnumOCIErrorCode :: CInt -> String
fromEnumOCIErrorCode err
| err == oci_SUCCESS = "OCI_SUCCESS"
| err == oci_SUCCESS_WITH_INFO = "OCI_SUCCESS_WITH_INFO"
| err == oci_NEED_DATA = "OCI_NEED_DATA"
| err == oci_NO_DATA = "OCI_NO_DATA"
| err == oci_INVALID_HANDLE = "OCI_INVALID_HANDLE"
| err == oci_STILL_EXECUTING = "OCI_STILL_EXECUTING"
| err == oci_CONTINUE = "OCI_CONTINUE"
| err == oci_RESERVED_FOR_INT_USE = "OCI_RESERVED_FOR_INT_USE"
| otherwise = "OCI_ERROR"
formatErrorCodeDesc :: CInt -> String -> String
formatErrorCodeDesc err desc
| err == oci_ERROR = ""
| otherwise = (fromEnumOCIErrorCode err) ++ " - " ++ desc
formatOCIMsg :: CInt -> String -> OCIHandle -> CInt -> IO (Int, String)
formatOCIMsg e m ocihandle handleType = do
(err, msg) <- getOCIErrorMsg ocihandle handleType
if msg == ""
then return (fromIntegral err, (formatErrorCodeDesc e m))
else return (fromIntegral err, (formatErrorCodeDesc e m) ++ " : " ++ msg)
formatMsgCommon :: OCIException -> OCIHandle -> CInt -> IO (Int, String)
formatMsgCommon (OCIException e m) h handleType = do
if e == 0
then return (0, "")
else case () of
_ | e == oci_ERROR -> do (formatOCIMsg e m h handleType)
| e == oci_SUCCESS_WITH_INFO -> do (formatOCIMsg e m h handleType)
| otherwise -> return (fromIntegral e, formatErrorCodeDesc e m)
formatErrorMsg :: OCIException -> ErrorHandle -> IO (Int, String)
formatErrorMsg exc err = formatMsgCommon exc (castPtr err) oci_HTYPE_ERROR
formatEnvMsg :: OCIException -> EnvHandle -> IO (Int, String)
formatEnvMsg exc err = formatMsgCommon exc (castPtr err) oci_HTYPE_ENV
testForError :: CInt -> String -> a -> IO a
testForError rc msg retval = do
if rc < 0
then throwOCI (OCIException rc msg)
else return retval
testForErrorWithPtr :: Storable a => CInt -> String -> Ptr a -> IO a
testForErrorWithPtr rc msg retval = do
if rc < 0
then throwOCI (OCIException rc msg)
else peek retval
envCreate :: IO EnvHandle
envCreate = alloca $ \ptr -> do
rc <- ociEnvCreate ptr oci_THREADED nullPtr nullFunPtr nullFunPtr nullFunPtr 0 nullPtr
testForErrorWithPtr rc "allocate initial end" ptr
handleAlloc :: CInt -> OCIHandle -> IO OCIHandle
handleAlloc handleType env = alloca $ \ptr -> do
rc <- ociHandleAlloc env ptr handleType 0 nullPtr
testForErrorWithPtr rc "allocate handle" ptr
handleFree :: CInt -> OCIHandle -> IO ()
handleFree handleType ptr = do
rc <- ociHandleFree ptr handleType
testForError rc "free handle" ()
setHandleAttr :: ErrorHandle -> OCIHandle -> CInt -> Ptr a -> CInt -> IO ()
setHandleAttr err ocihandle handleType handleAttr attrType = do
rc <- ociAttrSet ocihandle handleType (castPtr handleAttr) 0 attrType err
testForError rc "setHandleAttr" ()
setHandleAttrString :: ErrorHandle -> OCIHandle -> CInt -> String -> CInt -> IO ()
setHandleAttrString err ocihandle handleType s attrType = do
withCStringLen s $ \sC -> do
rc <- ociAttrSet ocihandle handleType (castPtr (cStr sC)) (cStrLen sC) attrType err
testForError rc "setHandleAttrString" ()
getHandleAttr :: (Storable a) => ErrorHandle -> OCIHandle -> CInt -> CInt -> IO a
getHandleAttr err ocihandle handleType attrType = alloca $ \ptr -> do
rc <- ociAttrGet ocihandle handleType (castPtr ptr) nullPtr attrType err
testForErrorWithPtr rc "getAttrHandle" ptr
getParam :: ErrorHandle -> StmtHandle -> Int -> IO ParamHandle
getParam err stmt posn = alloca $ \ptr -> do
rc <- ociParamGet (castPtr stmt) oci_HTYPE_STMT err ptr (mkCInt posn)
testForErrorWithPtr rc "getParam" (castPtr ptr)
dbLogon :: String -> String -> String -> EnvHandle -> ErrorHandle -> IO ConnHandle
dbLogon user pswd db env err =
withCStringLen user $ \userC ->
withCStringLen pswd $ \pswdC ->
withCStringLen db $ \dbC ->
alloca $ \conn -> do
rc <- ociLogon env err conn (cStr userC) (cStrLen userC) (cStr pswdC) (cStrLen pswdC) (cStr dbC) (cStrLen dbC)
case () of
_ | rc == oci_SUCCESS_WITH_INFO -> testForErrorWithPtr oci_ERROR "logon" conn
| otherwise -> testForErrorWithPtr rc "logon" conn
dbLogoff :: ErrorHandle -> ConnHandle -> IO ()
dbLogoff err conn = do
rc <- ociLogoff conn err
testForError rc "logoff" ()
terminate :: IO ()
terminate = do
rc <- ociTerminate oci_DEFAULT
testForError rc "terminate" ()
serverDetach :: ErrorHandle -> ServerHandle -> IO ()
serverDetach err server = do
rc <- ociServerDetach server err oci_DEFAULT
testForError rc "server detach" ()
serverAttach :: ErrorHandle -> ServerHandle -> String -> IO ()
serverAttach err server dblink = do
withCStringLen dblink $ \s -> do
rc <- ociServerAttach server err (cStr s) (cStrLen s) oci_DEFAULT
testForError rc "server attach" ()
getSession :: ErrorHandle -> ConnHandle -> IO SessHandle
getSession err conn = liftM castPtr (getHandleAttr err (castPtr conn) oci_HTYPE_SVCCTX oci_ATTR_SESSION)
sessionBegin :: ErrorHandle -> ConnHandle -> SessHandle -> CInt -> IO ()
sessionBegin err conn sess cred = do
rc <- ociSessionBegin conn err sess cred oci_DEFAULT
testForError rc "session begin" ()
sessionEnd :: ErrorHandle -> ConnHandle -> SessHandle -> IO ()
sessionEnd err conn sess = do
rc <- ociSessionEnd conn err sess oci_DEFAULT
testForError rc "session end" ()
beginTrans :: ErrorHandle -> ConnHandle -> CInt -> IO ()
beginTrans err conn isolation = do
rc <- ociTransStart conn err 0 isolation
testForError rc "begin transaction" ()
commitTrans :: ErrorHandle -> ConnHandle -> IO ()
commitTrans err conn = do
rc <- ociTransCommit conn err oci_DEFAULT
testForError rc "commit" ()
rollbackTrans :: ErrorHandle -> ConnHandle -> IO ()
rollbackTrans err conn = do
rc <- ociTransRollback conn err oci_DEFAULT
testForError rc "rollback" ()
stmtPrepare :: ErrorHandle -> StmtHandle -> String -> IO ()
stmtPrepare err stmt sqltext = do
withCStringLen sqltext $ \sqltextC -> do
rc <- ociStmtPrepare stmt err (cStr sqltextC) (cStrLen sqltextC) oci_NTV_SYNTAX oci_DEFAULT
testForError rc "stmtPrepare" ()
stmtExecute :: ErrorHandle -> ConnHandle -> StmtHandle -> Int -> IO ()
stmtExecute err conn stmt iterations = do
rc <- ociStmtExecute conn stmt err (mkCInt iterations) 0 nullPtr nullPtr oci_DEFAULT
testForError rc "stmtExecute" ()
defineByPos :: ErrorHandle
-> StmtHandle
-> Int
-> Int
-> CInt
-> IO ColumnInfo
defineByPos err stmt posn bufsize sqldatatype = do
bufferFPtr <- mallocForeignPtrBytes bufsize
nullIndFPtr <- mallocForeignPtr
retSizeFPtr <- mallocForeignPtr
alloca $ \defnPtr ->
withForeignPtr bufferFPtr $ \bufferPtr ->
withForeignPtr nullIndFPtr $ \nullIndPtr ->
withForeignPtr retSizeFPtr $ \retSizePtr -> do
rc <- ociDefineByPos stmt defnPtr err (mkCInt posn) bufferPtr (mkCInt bufsize) (mkCUShort sqldatatype) nullIndPtr retSizePtr nullPtr oci_DEFAULT
defn <- peek defnPtr
testForError rc "defineByPos" (defn, bufferFPtr, nullIndFPtr, retSizeFPtr)
substituteBindPlaceHolders sql =
sbph sql 1 False ""
sbph :: String -> Int -> Bool -> String -> String
sbph [] _ _ acc = reverse acc
sbph ('\'':cs) i inQuote acc = sbph cs i (not inQuote) ('\'':acc)
sbph ('?':cs) i False acc = sbph cs (i+1) False ((reverse (show i)) ++ (':':acc))
sbph (c:cs) i inQuote acc = sbph cs i inQuote (c:acc)
bindByPos ::
ErrorHandle
-> StmtHandle
-> Int
-> CShort
-> BufferPtr
-> Int
-> CInt
-> IO ()
bindByPos err stmt pos nullInd bufptr sze sqltype = do
indFPtr <- mallocForeignPtr
sizeFPtr <- mallocForeignPtr
withForeignPtr indFPtr $ \p -> poke p nullInd
withForeignPtr sizeFPtr $ \p -> poke p (fromIntegral sze)
bufFPtr <- newForeignPtr_ bufptr
bindOutputByPos err stmt pos (indFPtr, bufFPtr, sizeFPtr) sze sqltype
return ()
bindOutputByPos ::
ErrorHandle
-> StmtHandle
-> Int
-> BindBuffer
-> Int
-> CInt
-> IO BindHandle
bindOutputByPos err stmt pos (nullIndFPtr, bufFPtr, sizeFPtr) sze sqltype =
alloca $ \bindHdl ->
withForeignPtr nullIndFPtr $ \indPtr -> do
withForeignPtr sizeFPtr $ \sizePtr ->
withForeignPtr bufFPtr $ \bufPtr -> do
rc <- ociBindByPos stmt bindHdl err (fromIntegral pos) bufPtr
(fromIntegral sze) (fromIntegral sqltype)
indPtr sizePtr nullPtr 0 nullPtr (fromIntegral oci_DEFAULT)
testForError rc "bindOutputByPos" ()
bptr <- peek bindHdl
return bptr
stmtFetch :: ErrorHandle -> StmtHandle -> IO CInt
stmtFetch err stmt = do
let numRowsToFetch = 1
rc <- ociStmtFetch stmt err numRowsToFetch (mkCShort oci_FETCH_NEXT) oci_DEFAULT
if rc == oci_NO_DATA
then return rc
else testForError rc "stmtFetch" rc
maybeBufferNull :: ForeignPtr CShort -> Maybe a -> IO a -> IO (Maybe a)
maybeBufferNull nullIndFPtr nullVal action =
withForeignPtr nullIndFPtr $ \nullIndPtr -> do
nullInd <- liftM cShort2Int (peek nullIndPtr)
if (nullInd == -1)
then return nullVal
else do
v <- action
return (Just v)
nullByte :: CChar
nullByte = 0
cShort2Int :: CShort -> Int
cShort2Int n = fromIntegral n
cUShort2Int :: CUShort -> Int
cUShort2Int n = fromIntegral n
cuCharToInt :: CUChar -> Int
cuCharToInt c = fromIntegral c
byteToInt :: Ptr CUChar -> Int -> IO Int
byteToInt buffer n = do
b <- peekByteOff buffer n
return (cuCharToInt b)
bufferToString :: ColumnInfo -> IO (Maybe String)
bufferToString (_, bufFPtr, nullFPtr, sizeFPtr) =
withForeignPtr nullFPtr $ \nullIndPtr -> do
nullInd <- liftM cShort2Int (peek nullIndPtr)
if (nullInd == -1)
then return Nothing
else do
withForeignPtr bufFPtr $ \bufferPtr ->
withForeignPtr sizeFPtr $ \retSizePtr -> do
retsize <- liftM cUShort2Int (peek retSizePtr)
pokeByteOff (castPtr bufferPtr) retsize nullByte
val <- peekCString (castPtr bufferPtr)
return (Just val)
makeYear :: Int -> Int -> Int
makeYear c100 y100 = 100 * (c100 - 100) + (y100 - 100)
makeYearByte :: Int -> Word8
makeYearByte y = fromIntegral ((rem y 100) + 100)
makeCentByte :: Int -> Word8
makeCentByte y = fromIntegral ((quot y 100) + 100)
dumpBuffer :: Ptr Word8 -> IO ()
dumpBuffer buf = do
dumpByte 0
dumpByte 1
dumpByte 2
dumpByte 3
dumpByte 4
dumpByte 5
dumpByte 6
putStrLn ""
where
dumpByte n = do
b <- (peekByteOff buf n :: IO Word8)
putStr $ (show b) ++ " "
bufferToCaltime :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe CalendarTime)
bufferToCaltime nullind fptr = maybeBufferNull nullind Nothing $
withForeignPtr fptr $ \bufferPtr -> do
let buffer = castPtr bufferPtr
century100 <- byteToInt buffer 0
year100 <- byteToInt buffer 1
month <- byteToInt buffer 2
day <- byteToInt buffer 3
hour <- byteToInt buffer 4
minute <- byteToInt buffer 5
second <- byteToInt buffer 6
return $ CalendarTime
{ ctYear = makeYear century100 year100
, ctMonth = toEnum (month - 1)
, ctDay = day
, ctHour = hour - 1
, ctMin = minute - 1
, ctSec = second - 1
, ctPicosec = 0
, ctWDay = Sunday
, ctYDay = -1
, ctTZName = "UTC"
, ctTZ = 0
, ctIsDST = False
}
bufferToUTCTime :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe UTCTime)
bufferToUTCTime nullind fptr = maybeBufferNull nullind Nothing $
withForeignPtr fptr $ \bufferPtr -> do
let buffer = castPtr bufferPtr
century100 <- byteToInt buffer 0
year100 <- byteToInt buffer 1
month <- byteToInt buffer 2
day <- byteToInt buffer 3
hour <- byteToInt buffer 4
minute <- byteToInt buffer 5
second <- byteToInt buffer 6
let year = makeYear century100 year100
return (mkUTCTime year month day (hour-1) (minute-1) (second-1))
setBufferByte :: BufferPtr -> Int -> Word8 -> IO ()
setBufferByte buf n v = pokeByteOff buf n v
calTimeToBuffer :: BufferPtr -> CalendarTime -> IO ()
calTimeToBuffer buf ct = do
setBufferByte buf 0 (makeCentByte (ctYear ct))
setBufferByte buf 1 (makeYearByte (ctYear ct))
setBufferByte buf 2 (fromIntegral ((fromEnum (ctMonth ct)) + 1))
setBufferByte buf 3 (fromIntegral (ctDay ct))
setBufferByte buf 4 (fromIntegral (ctHour ct + 1))
setBufferByte buf 5 (fromIntegral (ctMin ct + 1))
setBufferByte buf 6 (fromIntegral (ctSec ct + 1))
utcTimeToBuffer :: BufferPtr -> UTCTime -> IO ()
utcTimeToBuffer buf utc = do
let (LocalTime ltday time) = utcToLocalTime (hoursToTimeZone 0) utc
let (TimeOfDay hour minute second) = time
let (year, month, day) = toGregorian ltday
setBufferByte buf 0 (makeCentByte (fromIntegral year))
setBufferByte buf 1 (makeYearByte (fromIntegral year))
setBufferByte buf 2 (fromIntegral month)
setBufferByte buf 3 (fromIntegral day)
setBufferByte buf 4 (fromIntegral (hour+1))
setBufferByte buf 5 (fromIntegral (minute+1))
setBufferByte buf 6 (round (second+1))
bufferPeekValue :: (Storable a) => BufferFPtr -> IO a
bufferPeekValue buffer = do
v <- withForeignPtr buffer $ \bufferPtr -> peek $ castPtr bufferPtr
return v
bufferToA :: (Storable a) => ForeignPtr CShort -> BufferFPtr -> IO (Maybe a)
bufferToA nullind buffer = maybeBufferNull nullind Nothing (bufferPeekValue buffer)
bufferToCInt :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe CInt)
bufferToCInt = bufferToA
bufferToInt :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe Int)
bufferToInt nullind b = do
cint <- bufferToCInt nullind b
return $ maybe Nothing (Just . fromIntegral) cint
bufferToCDouble :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe CDouble)
bufferToCDouble = bufferToA
bufferToDouble :: ForeignPtr CShort -> BufferFPtr -> IO (Maybe Double)
bufferToDouble nullind b = do
cdbl <- bufferToCDouble nullind b
return $ maybe Nothing (Just . realToFrac) cdbl
bufferToStmtHandle :: BufferFPtr -> IO StmtHandle
bufferToStmtHandle buffer = do
withForeignPtr buffer $ \bufferPtr -> do
v <- peek (castPtr bufferPtr)
return v