HDBC-mysql

MySQL driver for HDBC http://github.com/ryantm/hdbc-mysql

Latest on Hackage:0.7.1.0

This package is not currently in any snapshots. If you're interested in using it, we recommend adding it to Stackage Nightly. Doing so will make builds more reliable, and allow stackage.org to host generated Haddocks.

LGPL licensed by Chris Waterson
Maintained by Ryan Mulligan

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.

Developing hdbc-mysql with nix

# Nix shell
nix-shell -p haskell.packages.ghc801.ghc gcc mysql57 pkgconfig zlib openssl haskellPackages.haddock

# Use Cabal to build
cabal clean && cabal build

# Build test script
ghc -idist/build -L/nix/store/vksgj509kdnk3rva0x64qwp21nzrxy9b-mariadb-10.1.16/lib -lmysqlclient --make Test

# Run test script
./Test

Changes

2016-11-05 0.7.1.0 release prepared by Ryan Mulligan @ryantm

* Debug flag. Add Debug flag to cabal file to ease debugging by
tracing each type of call to the mysql library. By @kakkun61.

2016-08-25 0.7.0.0 release prepared by Ryan Mulligan @ryantm

* Support and requirement for GHC 8.0.1 added. By @ryantm and @wahjava.
* Specify previously required by unspecified dependencies on ssl and zlib.

2016-08-25 0.6.6.4 release prepared by Ryan Mulligan @ryantm

* Specifically require GHC to be less than version 8.0.1 to avoid
problems with cabal interface conflicts.

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.

comments powered byDisqus