Bryan O'Sullivan avatar Bryan O'Sullivan committed 1eea4f6

More implementation: query, fieldCount, affectedRows, and escape.

Also improved the performance of withRTSSignalsBlocked.

Comments (0)

Files changed (2)

Database/MySQL.hs

     , characterSetName
     , sslCipher
     , serverStatus
+    -- * Querying
+    , query
+    -- ** Results
+    , fieldCount
+    , affectedRows
+    -- * Escaping
+    , escape
     -- * General information
     , clientInfo
     , clientVersion
     ) where
 
+import Data.ByteString
+import Data.ByteString.Internal
+import Data.ByteString.Unsafe
+    
 import Control.Applicative
 import Data.Typeable (Typeable)
 import Control.Exception
       withRTSSignalsBlocked (mysql_change_user ptr cuser cpass cdb) >>=
       check "changeUser" ptr
 
+query :: Connection -> ByteString -> IO ()
+query conn q = withConn conn $ \ptr ->
+  unsafeUseAsCStringLen q $ \(p,l) ->
+  mysql_real_query ptr p (fromIntegral l) >>= check "query" ptr
+
+fieldCount :: Connection -> IO Word
+fieldCount conn = withConn conn $ fmap fromIntegral . mysql_field_count
+
+affectedRows :: Connection -> IO Word64
+affectedRows conn = withConn conn $ fmap fromIntegral . mysql_affected_rows
+
+escape :: Connection -> ByteString -> IO ByteString
+escape conn bs = withConn conn $ \ptr ->
+  unsafeUseAsCStringLen bs $ \(p,l) ->
+    createAndTrim (l*2 + 1) $ \to ->
+      fromIntegral <$> mysql_real_escape_string ptr (castPtr to) p
+                                                (fromIntegral l)
+
 withConn :: Connection -> (Ptr MYSQL -> IO a) -> IO a
 withConn conn = withForeignPtr (connFP conn)
 

Database/MySQL/C.hsc

     , mysql_character_set_name
     , mysql_get_ssl_cipher
     , mysql_stat
+    -- * Querying
+    , mysql_real_query
+    -- ** Results
+    , mysql_field_count
+    , mysql_affected_rows
+    -- * Escaping
+    , mysql_real_escape_string
     -- * General information
     , mysql_get_client_info
     , mysql_get_client_version
 import Control.Exception (finally)
 import Foreign.C.String (CString)
 import Foreign.C.Types
-import Foreign.Marshal.Alloc (alloca)
+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtr, withForeignPtr)
 import Foreign.Ptr (Ptr, nullPtr)
 import Foreign.Storable (Storable(..))
+import System.IO.Unsafe (unsafePerformIO)
 
 data MYSQL
 data MYSQL_STMT
 withRTSSignalsBlocked :: IO a -> IO a
 withRTSSignalsBlocked act
     | not rtsSupportsBoundThreads = act
-    | otherwise = runInBoundThread . alloca $ \set -> do
-  sigemptyset set
-  sigaddset set (#const SIGALRM)
-  sigaddset set (#const SIGVTALRM)
+    | otherwise = runInBoundThread . withForeignPtr rtsSignals $ \set -> do
   pthread_sigmask (#const SIG_BLOCK) set nullPtr
   act `finally` pthread_sigmask (#const SIG_UNBLOCK) set nullPtr
 
+rtsSignals :: ForeignPtr SigSet
+rtsSignals = unsafePerformIO $ do
+               fp <- mallocForeignPtr
+               withForeignPtr fp $ \set -> do
+                 sigemptyset set
+                 sigaddset set (#const SIGALRM)
+                 sigaddset set (#const SIGVTALRM)
+               return fp
+{-# NOINLINE rtsSignals #-}
+
 data SigSet
 
 instance Storable SigSet where
 foreign import ccall unsafe mysql_stat
     :: Ptr MYSQL -> IO CString
 
+foreign import ccall unsafe mysql_real_query
+    :: Ptr MYSQL -> CString -> CULong -> IO CInt
+
+foreign import ccall safe mysql_field_count
+    :: Ptr MYSQL -> IO CUInt
+
+foreign import ccall safe mysql_affected_rows
+    :: Ptr MYSQL -> IO CULLong
+
+foreign import ccall safe mysql_real_escape_string
+    :: Ptr MYSQL -> CString -> CString -> CULong -> IO CULong
+
 foreign import ccall safe mysql_get_client_info :: CString
 
 foreign import ccall safe mysql_get_client_version :: CULong
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.