packages feed

HDBC-mysql 0.6.3 → 0.6.4.0

raw patch · 6 files changed

+286/−42 lines, 6 filesdep ~basenew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Database.HDBC.MySQL: withRTSSignalsBlocked :: IO a -> IO a

Files

+ ChangeLog view
@@ -0,0 +1,48 @@+2010-06-01  Chris Waterson  <waterson@maubi.net>++	* Database/HDBC/MySQL/Connection.hsc.  Add runRaw, patch from Rune+	Harder Bak <rune@bak.dk>.++2010-04-16  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.6.2.  Fix incorrect usage of "with" and+	"withCString" to allocate buffers for libmysqlclient.  Send+	SqlString data as UTF-8 encoded byte strings; return string data+	as SqlByteStrings.++2009-03-01  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.6.1.  Expose Connection type.++2009-06-05  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.6. Use Foreign.Concurrent to correctly incorporate+	Haskell finalizer for binds.  Fix handling of SqlWord32 and+	SqlWord64 values: tip o' the cap to yeoh@cs.wisc.edu.++2009-03-02  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.5. Use "throwSqlError" instead of "throwDyn" so+	that we get legible errors under ghc-6.10.  This also removes the+	dependency on base 3.++2009-02-26  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.4. Fix incorrect binding size (should always be 4+	bytes, not compiler's "long") for MYSQL_TYPE_LONG columns.++2009-02-18  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.3 Deal with some of the problems where statements+	would mysteriously "close".  It turns out that only one statement+	can be "active" on a connection at a time, and that closing an+	inactive statement causes the current statement to close as well.++2009-02-14  Chris Waterson  <waterson@maubi.net>++	* HDBC-mysql-0.2 Fix binding width for dates: MySQL's length+	indicates 19 characters (which is the length of the string), but+	we need the full size of the MYSQL_TIME struct.  Leak connections+	and statements until I can figure out how to keep the ForeignPtr's+	alive.+
Database/HDBC/MySQL.hs view
@@ -1,42 +1,65 @@ {- | +Module      : Database.HDBC.MySQL+Copyright   : Copyright (c) 2009-2010 Chris Waterson+License     : LGPL+Maintainer  : bos@mailrank.com+Stability   : experimental+Portability : GHC+ This module provides a MySQL driver for the HDBC database interface. To use it, invoke the 'connectMySQL' method to create an @Database.HDBC.IConnection@ that you can use to interact with a MySQL database.  Use the 'defaultMySQLConnectInfo', overriding the default values as necessary. -> import Control.Monad-> import Database.HDBC-> import Database.HDBC.MySQL-> main = do conn <- connectMySQL defaultMySQLConnectInfo {->                        mysqlHost     = "db1.example.com",->                        mysqlUser     = "scott",->                        mysqlPassword = "tiger"->                     }->->           rows <- quickQuery' conn "SELECT 1 + 1" []->           forM_ rows $ \row -> putStrLn $ show row+@+import Control.Monad+import Database.HDBC+import Database.HDBC.MySQL +main = do+  rows <- 'withRTSSignalsBlocked' $ do+    conn <- 'connectMySQL' 'defaultMySQLConnectInfo' {+              'mysqlHost'     = \"db1.example.com\",+              'mysqlUser'     = \"scott\",+              'mysqlPassword' = \"tiger\"+            }+    'quickQuery'' conn \"SELECT 1 + 1\" []+  forM_ rows $ \row -> putStrLn $ show row+@+ There are some important caveats to note about this driver. -The first relates to transaction support.  The MySQL server supports a-variety of backend \"engines\", only some of which support-transactional access (e.g., InnoDB).  This driver will report that the-database supports transactions.  Should you decide to make use of the-transactional support in the HDBC API,-/it is up to you to make sure that you use a MySQL engine that supports transactions/.+* RTS signals.  If you are writing an application that links against GHC's+  threaded runtime (as most server-side applications do), you must use+  'withRTSSignalsBlocked' to defend the @mysqlclient@ library against the+  signals the RTS uses, or you may experience crashes. -The next relates to dates and times.  MySQL does not store time zone-information in @DATETIME@ or @TIMESTAMP@ columns: instead, it assumes-that all dates are stored in the \"server's time zone\".  At some-point in the future, this driver may query for the server's time zone-and apply appropriate time zone conversion to these datatypes. For-now, it simply treats all times as UTC; i.e., it assumes the server's-time zone is UTC.+* Transaction support.  The MySQL server supports a+  variety of backend \"engines\", only some of which support+  transactional access (e.g., InnoDB).  This driver will report that the+  database supports transactions.  Should you decide to make use of the+  transactional support in the HDBC API,+  /it is up to you to make sure that you use a MySQL engine that supports transactions/. +* Dates and times.  MySQL does not store time zone+  information in @DATETIME@ or @TIMESTAMP@ columns: instead, it assumes+  that all dates are stored in the \"server's time zone\".  At some+  point in the future, this driver may query for the server's time zone+  and apply appropriate time zone conversion to these datatypes. For+  now, it simply treats all times as UTC; i.e., it assumes the server's+  time zone is UTC.+ -} module Database.HDBC.MySQL-    (connectMySQL, MySQLConnectInfo(..), defaultMySQLConnectInfo, Connection)-where+    (+      MySQLConnectInfo(..)+    , Connection+    , connectMySQL+    , defaultMySQLConnectInfo+    , withRTSSignalsBlocked+    ) where+ import Database.HDBC.MySQL.Connection+import Database.HDBC.MySQL.RTS
Database/HDBC/MySQL/Connection.hsc view
@@ -1,9 +1,12 @@--- -*- mode: haskell; -*--{-# OPTIONS -fglasgow-exts #-}+{-# LANGUAGE EmptyDataDecls, ForeignFunctionInterface, ScopedTypeVariables #-}  module Database.HDBC.MySQL.Connection-    (connectMySQL, MySQLConnectInfo(..), defaultMySQLConnectInfo, Connection)-where+    (+      connectMySQL+    , MySQLConnectInfo(..)+    , defaultMySQLConnectInfo+    , Connection+    ) where  import Control.Exception import Control.Monad@@ -122,7 +125,7 @@          -- HDBC assumes that there is no such thing as auto-commit.         -- So we'll turn it off here and start our first transaction.-        mysql_autocommit mysql_ 0+        _ <- mysql_autocommit mysql_ 0          mysql__ <- newForeignPtr mysql_close mysql_         doStartTransaction mysql__@@ -671,7 +674,7 @@ doGetTables :: ForeignPtr MYSQL -> IO [String] doGetTables mysql__ = do   stmt <- newStatement mysql__ "SHOW TABLES"-  Types.execute stmt []+  _ <- Types.execute stmt []   rows <- unfoldRows stmt   Types.finish stmt   return $ map (fromSql . head) rows@@ -686,7 +689,7 @@ doDescribeTable :: ForeignPtr MYSQL -> String -> IO [(String, ColTypes.SqlColDesc)] doDescribeTable mysql__ table = do   stmt <- newStatement mysql__ ("DESCRIBE " ++ table)-  Types.execute stmt []+  _ <- Types.execute stmt []   rows <- unfoldRows stmt   Types.finish stmt   return $ map fromRow rows
+ Database/HDBC/MySQL/RTS.hsc view
@@ -0,0 +1,56 @@+{-# LANGUAGE EmptyDataDecls, ForeignFunctionInterface #-}++module Database.HDBC.MySQL.RTS (withRTSSignalsBlocked) where++import Control.Concurrent (runInBoundThread)+import Control.Exception (finally)+import Foreign.C.Types (CInt)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable(..))++#include <signal.h>++-- | Execute an 'IO' action with signals used by GHC's runtime signals+-- blocked.  The @mysqlclient@ C library does not correctly restart+-- system calls if they are interrupted by signals, so many MySQL API+-- calls can unexpectedly fail when called from a Haskell application.+-- This is most likely to occur if you are linking against GHC's+-- threaded runtime (using the @-threaded@ option).+--+-- This function blocks @SIGALRM@ and @SIGVTALRM@, runs your action,+-- then unblocks those signals.  If you have a series of HDBC calls+-- that may block for a period of time, it may be wise to wrap them in+-- this action.  Blocking and unblocking signals is cheap, but not+-- free.+--+-- Here is an example of an exception that could be avoided by+-- temporarily blocking GHC's runtime signals:+--+-- >  SqlError {+-- >    seState = "", +-- >    seNativeError = 2003, +-- >    seErrorMsg = "Can't connect to MySQL server on 'localhost' (4)"+-- >  }+withRTSSignalsBlocked :: IO a -> IO a+withRTSSignalsBlocked act = runInBoundThread . alloca $ \set -> do+  sigemptyset set+  sigaddset set (#const SIGALRM)+  sigaddset set (#const SIGVTALRM)+  pthread_sigmask (#const SIG_BLOCK) set nullPtr+  act `finally` pthread_sigmask (#const SIG_UNBLOCK) set nullPtr++data SigSet++instance Storable SigSet where+    sizeOf    _ = #{size sigset_t}+    alignment _ = alignment (undefined :: Ptr CInt)++foreign import ccall unsafe "signal.h sigaddset" sigaddset+    :: Ptr SigSet -> CInt -> IO ()++foreign import ccall unsafe "signal.h sigemptyset" sigemptyset+    :: Ptr SigSet -> IO ()++foreign import ccall unsafe "signal.h pthread_sigmask" pthread_sigmask+    :: CInt -> Ptr SigSet -> Ptr SigSet -> IO ()
HDBC-mysql.cabal view
@@ -1,18 +1,42 @@ Name:             HDBC-mysql Category:         Database Synopsis:         MySQL driver for HDBC-Version:          0.6.3-Description:      This package provides a MySQL driver for HDBC.+Version:          0.6.4.0 Stability:        Experimental-Maintainer:       Chris Waterson <waterson@maubi.net>+Maintainer:       Bryan O'Sullivan <bos@mailrank.com> Author:           Chris Waterson-Copyright:        Copyright (c) 2009-2010 Chris Waterson+Copyright:        2009-2010 Chris Waterson, 2011 MailRank License:          LGPL License-file:     COPYING-Homepage:         http://www.maubi.net/~waterson/hacks/hdbc-mysql.html-Build-Depends:    base >= 2 && < 4, bytestring, time, utf8-string, HDBC >= 2.1.0-Exposed-modules:  Database.HDBC.MySQL-Other-modules:    Database.HDBC.MySQL.Connection-ghc-options:      -Wall+Homepage:         http://github.com/mailrank/hdbc-mysql+Bug-Reports:      http://github.com/mailrank/hdbc-mysql/issues Build-Type:       Custom Tested-with:      GHC+Cabal-Version:    >= 1.6+Description:+  This package provides a MySQL driver for HDBC, implemented via+  bindings to the C @mysqlclient@ library.+extra-source-files:+  ChangeLog+  README.markdown++library+  Exposed-modules:  Database.HDBC.MySQL+  Other-modules:+    Database.HDBC.MySQL.Connection+    Database.HDBC.MySQL.RTS+  Build-Depends:+    HDBC >= 2.1.0,+    base >= 2 && < 5,+    bytestring,+    time,+    utf8-string+  ghc-options:      -Wall++source-repository head+  type:     git+  location: http://github.com/mailrank/hdbc-mysql++source-repository head+  type:     mercurial+  location: http://bitbucket.org/bos/hdbc-mysql
+ README.markdown view
@@ -0,0 +1,90 @@+HDBC-mysql+==========++This is a "native" HDBC driver for MySQL that makes use of+libmysqlclient to communicate with a MySQL server.  By way of+synopsis:++  import Control.Monad+  import Database.HDBC+  import Database.HDBC.MySQL+  main = do conn <- connectMySQL defaultMySQLConnectInfo {+                         mysqlHost     = "db1.example.com",+                         mysqlUser     = "scott",+                         mysqlPassword = "tiger"+                      }++            rows <- quickQuery' conn "SELECT 1 + 1" []+            forM_ rows $ \row -> putStrLn $ show row++At the moment, please consider this to be "alpha" software.  As far as+I can tell, it works.  There are some limitations that you should be+aware of.++Caveats+=======++  * This works with MySQL server and client libraries 5.0.75.  I+    haven't tried with 4.x nor 5.1.  I suspect that using a server+    version less than 4.1 won't work, due to lack of support for+    prepared statements.++  * MySQL DATETIME and TIMESTAMP columns have no time zone information,+    because they just don't.  So, I'm just converting them blindly to+    SqlEpochTime values, and assuming the times are UTC.  This is all+    fine if you're actually running your server in UTC, but it will+    probably be confusing if you're not.  It might be possible to+    interpret the times using the current connection's default+    time zone setting, instead.  Is that better?  Or worse?++  * Regardless, the types I convert to are now deprecated, and I need+    to implement the new types (SqlLocalDate, etc.)++  * Out of the box, MySQL probably uses MyISAM tables to store its+    data, and MyISAM tables don't support transactions.  Yet, I'm+    going to blindly respond "yes" if you ask whether the driver+    itself supports transactions, and assume that you know enough to+    use InnoDB tables in the database if you want to make use of+    HDBC's transactional support.  I *suppose* I might be able to+    discover what the default table type is, and say "no" if it's not+    a table type that supports transactions, but... meh.++  * I'm not sure that I can tell the difference between a MySQL TEXT+    and a MySQL BLOB column.  If you ask about the metadata of either,+    I'll tell you it's a SqlBinaryT.++  * The statement and table metadata could stand to be improved a bit.+    In particular, it would be nice if "describeTable foo" and+    "describeResults" on "SELECT * FROM foo" returned the same thing.+    (They're sorta close, I guess...)++  * Thread-safety could be an issue.  In the driver code, there's+    definitely a race condition between "prepare" and "disconnect",+    for example.  I haven't even *looked* at thread-safety issues for+    the MySQL driver.  I'm not sure if I should worry about it, or if+    we assume that's going to be dealt with at a higher level.++  * We might crash if someone opens a connection, prepares a+    statement, explicitly disconnects the connection, and then tries+    to play with the statement.++  * It probably makes sense to marshall to the SqlByteString type when+    retrieving BLOB data.++Testing+=======++There's a little test program that runs a query and spews out the+results.  To compile it,++  ghc -idist/build -L/opt/local/lib/mysql5/mysql -lmysqlclient --make Test++I'm still trying to get the Makefile right so that it can build the+test sources: it's not there yet.  Here's how I've been doing it, for+now:++  cd testsrc+  ghc --make -package HUnit -package HDBC -Wall -i../dist/build -i.. -L/opt/local/lib/mysql5/mysql -lmysqlclient -o runtests runtests.hs++One issue is that I want the location of the MySQL library to come+from the configuration data, rather than be hard-coded.