Permalink
Browse files

Merge

  • Loading branch information...
2 parents c09d190 + 7c7adf1 commit c3cdd5b56d79f4ff18d29996e0a37e1057a26649 @bos bos committed Nov 17, 2011
Showing with 83 additions and 30 deletions.
  1. +1 −1 .hgtags
  2. +14 −7 Database/MySQL/Base.hs
  3. +20 −16 Database/MySQL/Base/C.hsc
  4. +7 −6 README.markdown
  5. +35 −0 cbits/mysql_signals.c
  6. +6 −0 include/mysql_signals.h
View
@@ -4,4 +4,4 @@
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
View
@@ -204,6 +204,7 @@ data Result = Result {
, 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'.
@@ -410,6 +411,7 @@ storeResult = frobResult "storeResult" mysql_store_result
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.
--
@@ -419,14 +421,17 @@ useResult = frobResult "useResult" mysql_use_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
@@ -437,7 +442,7 @@ frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc conn =
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
@@ -446,15 +451,17 @@ frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc conn =
, 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
@@ -463,10 +470,10 @@ isResultValid :: Result -> IO Bool
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
View
@@ -46,6 +46,7 @@ module Database.MySQL.Base.C
, mysql_fetch_row_nonblock
-- * Working with results
, mysql_free_result
+ , mysql_free_result_nonblock
, mysql_fetch_fields
, mysql_fetch_fields_nonblock
, mysql_data_seek
@@ -154,26 +155,26 @@ foreign import ccall safe mysql_ssl_set
-> 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
@@ -196,10 +197,10 @@ foreign import ccall safe mysql_set_character_set
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
@@ -211,16 +212,19 @@ foreign import ccall safe mysql_field_count
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
@@ -235,22 +239,22 @@ foreign import ccall safe mysql_row_seek
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
@@ -2,11 +2,12 @@
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
@@ -19,9 +20,9 @@ to the terms of the GPL.
# 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!
View
@@ -66,6 +66,16 @@ int STDCALL _hs_mysql_ping(MYSQL *mysql)
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;
@@ -75,6 +85,24 @@ const char *STDCALL _hs_mysql_stat(MYSQL *mysql)
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;
@@ -148,6 +176,13 @@ MYSQL_RES *STDCALL _hs_mysql_use_result(MYSQL *mysql)
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;
View
@@ -17,7 +17,11 @@ MYSQL *STDCALL _hs_mysql_real_connect(MYSQL *mysql, const char *host,
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);
@@ -27,6 +31,8 @@ MYSQL_ROW STDCALL _hs_mysql_fetch_row(MYSQL_RES *result);
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 */

0 comments on commit c3cdd5b

Please sign in to comment.