Bryan O'Sullivan avatar Bryan O'Sullivan committed a81ee36 Merge

Merge

Comments (0)

Files changed (7)

 5292a58383497dc07949a385738742531ba8babb 0.1.1.0
 be4fc2abfa5adb284af9df93d85644267a260bcd 0.1.1.0
 716f62f748a367ee2ba61e24ffdf231b8c20b416 0.1.1.1
-3cf139703c2fe6054355e38b5dc137daf639da84 0.1.1.2
+f15e9f546d237e19f8bdf5bfa7203630dd7fa1aa 0.1.1.2

Database/MySQL/Base.hs

     , resFetchFields :: Ptr MYSQL_RES -> IO (Ptr Field)
     , resFetchRow :: Ptr MYSQL_RES -> IO MYSQL_ROW
     , resFetchLengths :: Ptr MYSQL_RES -> IO (Ptr CULong)
+    , resFreeResult :: Ptr MYSQL_RES -> IO ()
     } | EmptyResult
 
 -- | A row cursor, used by 'rowSeek' and 'rowTell'.
               mysql_fetch_fields_nonblock
               mysql_fetch_row_nonblock
               mysql_fetch_lengths_nonblock
+              mysql_free_result_nonblock
 
 -- | Initiate a row-by-row retrieval of a result.
 --
             mysql_fetch_fields
             mysql_fetch_row
             mysql_fetch_lengths
+            mysql_free_result
 
 frobResult :: String
            -> (Ptr MYSQL -> IO (Ptr MYSQL_RES))
            -> (Ptr MYSQL_RES -> IO (Ptr Field))
            -> (Ptr MYSQL_RES -> IO MYSQL_ROW)
            -> (Ptr MYSQL_RES -> IO (Ptr CULong))
+           -> (Ptr MYSQL_RES -> IO ())
            -> Connection -> IO Result
-frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc conn =
+frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc
+           myFreeResult conn =
   withConn conn $ \ptr -> do
     cleanupConnResult (connResult conn)
     res <- frob ptr
            then return EmptyResult
            else connectionError func conn
       else do
-        fp <- newForeignPtr res $ freeResult_ valid res
+        fp <- newForeignPtr res $ freeResult_ valid myFreeResult res
         let ret = Result {
                     resFP = fp
                   , resFields = fromIntegral fields
                   , resFetchFields = fetchFieldsFunc
                   , resFetchRow = fetchRowFunc
                   , resFetchLengths = fetchLengthsFunc
+                  , resFreeResult = myFreeResult
                   }
-        weak <- mkWeakPtr ret (Just (freeResult_ valid res))
+        weak <- mkWeakPtr ret (Just (freeResult_ valid myFreeResult res))
         writeIORef (connResult conn) (Just weak)
         return ret
 
 -- | Immediately free the @MYSQL_RES@ value associated with this
 -- 'Result', and mark the @Result@ as invalid.
 freeResult :: Result -> IO ()
-freeResult Result{..}      = withForeignPtr resFP $ freeResult_ resValid
+freeResult Result{..}      = withForeignPtr resFP $
+                             freeResult_ resValid resFreeResult
 freeResult EmptyResult{..} = return ()
 
 -- | Check whether a 'Result' is still valid, i.e. backed by a live
 isResultValid Result{..}  = readIORef resValid
 isResultValid EmptyResult = return False
 
-freeResult_ :: IORef Bool -> Ptr MYSQL_RES -> IO ()
-freeResult_ valid ptr = do
+freeResult_ :: IORef Bool -> (Ptr MYSQL_RES -> IO ()) -> Ptr MYSQL_RES -> IO ()
+freeResult_ valid free ptr = do
   wasValid <- atomicModifyIORef valid $ \prev -> (False, prev)
-  when wasValid $ mysql_free_result ptr
+  when wasValid $ free ptr
 
 fetchRow :: Result -> IO [Maybe ByteString]
 fetchRow res@Result{..}  = withRes "fetchRow" res $ \ptr -> do

Database/MySQL/Base/C.hsc

     , mysql_fetch_row_nonblock
     -- * Working with results
     , mysql_free_result
+    , mysql_free_result_nonblock
     , mysql_fetch_fields
     , mysql_fetch_fields_nonblock
     , mysql_data_seek
     -> CString                  -- ^ Ciphers.
     -> IO MyBool
 
-foreign import ccall unsafe mysql_close
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_close" mysql_close
     :: Ptr MYSQL -> IO ()
 
-foreign import ccall unsafe mysql_ping
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_ping" mysql_ping
     :: Ptr MYSQL -> IO CInt
 
 foreign import ccall safe mysql_thread_id
     :: Ptr MYSQL -> IO CULong
 
-foreign import ccall unsafe mysql_autocommit
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_autocommit" mysql_autocommit
     :: Ptr MYSQL -> MyBool -> IO MyBool
 
-foreign import ccall unsafe mysql_change_user
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_change_user" mysql_change_user
     :: Ptr MYSQL
     -> CString                  -- ^ user
     -> CString                  -- ^ password
     -> CString                  -- ^ database
     -> IO MyBool
 
-foreign import ccall unsafe mysql_select_db
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_select_db" mysql_select_db
     :: Ptr MYSQL
     -> CString
     -> IO CInt
 foreign import ccall safe mysql_get_ssl_cipher
     :: Ptr MYSQL -> IO CString
 
-foreign import ccall unsafe mysql_stat
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_stat" mysql_stat
     :: Ptr MYSQL -> IO CString
 
-foreign import ccall unsafe mysql_real_query
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_real_query" mysql_real_query
     :: Ptr MYSQL -> CString -> CULong -> IO CInt
 
 foreign import ccall safe mysql_insert_id
 foreign import ccall safe mysql_affected_rows
     :: Ptr MYSQL -> IO CULLong
 
-foreign import ccall unsafe mysql_store_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_store_result" mysql_store_result
     :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
 
-foreign import ccall unsafe mysql_use_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_use_result"  mysql_use_result
     :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
 
-foreign import ccall unsafe mysql_free_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_free_result" mysql_free_result
     :: Ptr MYSQL_RES -> IO ()
 
-foreign import ccall unsafe mysql_fetch_fields
+foreign import ccall safe "mysql.h mysql_free_result" mysql_free_result_nonblock
+    :: Ptr MYSQL_RES -> IO ()
+
+foreign import ccall safe mysql_fetch_fields
     :: Ptr MYSQL_RES -> IO (Ptr Field)
 
 foreign import ccall safe "mysql.h mysql_fetch_fields" mysql_fetch_fields_nonblock
 foreign import ccall safe mysql_row_tell
     :: Ptr MYSQL_RES -> IO MYSQL_ROW_OFFSET
 
-foreign import ccall unsafe mysql_next_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_next_result" mysql_next_result
     :: Ptr MYSQL -> IO CInt
 
-foreign import ccall unsafe mysql_commit
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_commit" mysql_commit
     :: Ptr MYSQL -> IO MyBool
 
-foreign import ccall unsafe mysql_rollback
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_rollback" mysql_rollback
     :: Ptr MYSQL -> IO MyBool
 
-foreign import ccall unsafe mysql_fetch_row
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_fetch_row" mysql_fetch_row
     :: Ptr MYSQL_RES -> IO MYSQL_ROW
 
 foreign import ccall safe "mysql.h mysql_fetch_row" mysql_fetch_row_nonblock
     :: Ptr MYSQL_RES -> IO MYSQL_ROW
 
-foreign import ccall unsafe mysql_fetch_lengths
+foreign import ccall safe mysql_fetch_lengths
     :: Ptr MYSQL_RES -> IO (Ptr CULong)
 
 foreign import ccall safe "mysql.h mysql_fetch_lengths" mysql_fetch_lengths_nonblock
 
 This library is a Haskell binding to the MySQL `mysqlclient` client
 library.  It is a fairly faithful, low level library that implements
-most of the MySQL client API.
+most of the MySQL client API.  The major departure from the C API is
+that in Haskell, resource management is mostly automatic and safe.
 
 This library deliberately avoids the question of providing a "good"
-API. Its purpose is to serve as a base on which higher-level libraries
-can be build.
+API. Its purpose is to serve as a base upon which higher-level
+libraries can be built.
 
 # Licensing
 
 
 # To do
 
-* Add support for prepared statements. This API is huge and of dubious
-  performance worth, so it's not currently a priority for me. Patches
-  welcome!
+* Add support for prepared statements. The prepared statement API is
+  huge and of dubious performance value, so it's not currently a
+  priority for us. Patches welcome!
 
 # Get involved!
 

cbits/mysql_signals.c

     return ret;
 }
 
+int STDCALL _hs_mysql_real_query(MYSQL *mysql, const char *q,
+				 unsigned long length)
+{
+    int ret;
+    block_rts_signals();
+    ret = mysql_real_query(mysql, q, length);
+    unblock_rts_signals();
+    return ret;
+}
+
 const char *STDCALL _hs_mysql_stat(MYSQL *mysql)
 {
     const char *ret;
     return ret;
 }
 
+my_bool STDCALL _hs_mysql_commit(MYSQL * mysql)
+{
+    my_bool ret;
+    block_rts_signals();
+    ret = mysql_commit(mysql);
+    unblock_rts_signals();
+    return ret;
+}
+
+my_bool STDCALL _hs_mysql_rollback(MYSQL * mysql)
+{
+    my_bool ret;
+    block_rts_signals();
+    ret = mysql_rollback(mysql);
+    unblock_rts_signals();
+    return ret;
+}
+
 my_bool STDCALL _hs_mysql_autocommit(MYSQL *mysql, my_bool auto_mode)
 {
     my_bool ret;
     return ret;
 }
 
+void STDCALL _hs_mysql_free_result(MYSQL_RES *result)
+{
+    block_rts_signals();
+    mysql_free_result(result);
+    unblock_rts_signals();
+}
+
 int STDCALL _hs_mysql_next_result(MYSQL *mysql)
 {
     int ret;

include/mysql_signals.h

 				      unsigned long clientflag);
 void STDCALL _hs_mysql_close(MYSQL *sock);
 int STDCALL _hs_mysql_ping(MYSQL *mysql);
+int STDCALL _hs_mysql_real_query(MYSQL *mysql, const char *q,
+				 unsigned long length);
 const char *STDCALL _hs_mysql_stat(MYSQL *mysql);
+my_bool STDCALL _hs_mysql_commit(MYSQL * mysql);
+my_bool STDCALL _hs_mysql_rollback(MYSQL * mysql);
 my_bool STDCALL _hs_mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
 my_bool STDCALL _hs_mysql_change_user(MYSQL *mysql, const char *user,
 				      const char *passwd, const char *db);
 unsigned long *STDCALL _hs_mysql_fetch_lengths(MYSQL_RES *result);
 MYSQL_RES *STDCALL _hs_mysql_store_result(MYSQL *mysql);
 MYSQL_RES *STDCALL _hs_mysql_use_result(MYSQL *mysql);
+void STDCALL _hs_mysql_free_result(MYSQL_RES *result);
 int STDCALL _hs_mysql_next_result(MYSQL *mysql);
+void STDCALL _hs_mysql_close(MYSQL *sock);
 
 #endif /* _mysql_signals_h */

File contents unchanged.

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.