Copyright | (c) 2011 MailRank Inc. |
---|---|
License | BSD3 |
Maintainer | Paul Rouse <[email protected]> |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell98 |
Database.MySQL.Base
Contents
Description
A low-level client library for the MySQL database, implemented as
bindings to the C mysqlclient
API.
The C library is thread-safe, but uses thread-local state. Therefore,
if these bindings are used in a multi-threaded program, "bound" threads
should be used (see Control.Concurrent). In addition, explicit calls
to initLibrary
, and possibly initThread
and endThread
may be needed
in a multi-threaded program.
- data ConnectInfo = ConnectInfo {}
- data SSLInfo = SSLInfo {}
- type Seconds = Word
- data Protocol
- data Option
- = ConnectTimeout Seconds
- | Compress
- | NamedPipe
- | InitCommand ByteString
- | ReadDefaultFile FilePath
- | ReadDefaultGroup ByteString
- | CharsetDir FilePath
- | CharsetName String
- | LocalInFile Bool
- | Protocol Protocol
- | SharedMemoryBaseName ByteString
- | ReadTimeout Seconds
- | WriteTimeout Seconds
- | UseRemoteConnection
- | UseEmbeddedConnection
- | GuessConnection
- | ClientIP ByteString
- | SecureAuth Bool
- | ReportDataTruncation Bool
- | Reconnect Bool
- | SSLVerifyServerCert Bool
- | FoundRows
- | IgnoreSIGPIPE
- | IgnoreSpace
- | Interactive
- | LocalFiles
- | MultiResults
- | MultiStatements
- | NoSchema
- defaultConnectInfo :: ConnectInfo
- defaultSSLInfo :: SSLInfo
- data Connection
- data Result
- data Type
- data Row
- data MySQLError
- connect :: ConnectInfo -> IO Connection
- close :: Connection -> IO ()
- autocommit :: Connection -> Bool -> IO ()
- ping :: Connection -> IO ()
- changeUser :: Connection -> String -> String -> Maybe String -> IO ()
- selectDB :: Connection -> String -> IO ()
- setCharacterSet :: Connection -> String -> IO ()
- threadId :: Connection -> IO Word
- serverInfo :: Connection -> IO String
- hostInfo :: Connection -> IO String
- protocolInfo :: Connection -> IO Word
- characterSet :: Connection -> IO String
- sslCipher :: Connection -> IO (Maybe String)
- serverStatus :: Connection -> IO String
- query :: Connection -> ByteString -> IO ()
- insertID :: Connection -> IO Word64
- escape :: Connection -> ByteString -> IO ByteString
- fieldCount :: Either Connection Result -> IO Int
- affectedRows :: Connection -> IO Int64
- isResultValid :: Result -> IO Bool
- freeResult :: Result -> IO ()
- storeResult :: Connection -> IO Result
- useResult :: Connection -> IO Result
- fetchRow :: Result -> IO [Maybe ByteString]
- fetchFields :: Result -> IO [Field]
- dataSeek :: Result -> Int64 -> IO ()
- rowSeek :: Result -> Row -> IO Row
- rowTell :: Result -> IO Row
- nextResult :: Connection -> IO Bool
- commit :: Connection -> IO ()
- rollback :: Connection -> IO ()
- clientInfo :: String
- clientVersion :: Word
- initLibrary :: IO ()
- initThread :: IO ()
- endThread :: IO ()
Licensing
Important licensing note: This library is BSD-licensed under the terms of the MySQL FOSS License Exception http://www.mysql.com/about/legal/licensing/foss-exception/.
Since this library links against the GPL-licensed mysqlclient
library, a non-open-source application that uses it may be
subject to the terms of the GPL.
Our rules for managing Connection
and Result
values are
unfortunately complicated, thanks to MySQL's lifetime rules.
At the C libmysqlclient
level, a single MYSQL
connection may
cause multiple MYSQL_RES
result values to be created over the
course of multiple queries, but only one of these MYSQL_RES
values may be alive at a time. The programmer is responsible for
knowing when to call mysql_free_result
.
Meanwhile, up in Haskell-land, we'd like both Connection
and
Result
values to be managed either manually or automatically. In
particular, we want finalizers to tidy up after a messy programmer,
and we'd prefer it if people didn't need to be mindful of calling
mysql_free_result
. This means that we must wrestle with the
lifetime rules. An obvious approach would be to use some monad and
type magic to enforce those rules, but then we'd end up with an
awkward API.
Instead, we allow Result
values to stay alive for arbitrarily
long times, while preserving the right to mark them as
invalid. When a Result
is marked invalid, its associated
MYSQL_RES
is freed, and can no longer be used.
Since all functions over Result
values are in the IO
monad, we
don't risk disrupting pure code by introducing this notion of
invalidity. If code tries to use an invalid Result
, a
MySQLError
will be thrown. This should not occur in normal
code, so there should be no need to use isResultValid
to test a
Result
for validity.
Each of the following functions will invalidate a Result
:
A Result
must be able to keep a Connection
alive so that a
streaming Result
constructed by useResult
can continue to pull
data from the server, but a Connection
must (a) be able to cause
the MYSQL_RES
behind a Result
to be deleted at a moment's notice,
while (b) not artificially prolonging the life of either the Result
or its MYSQL_RES
.
data ConnectInfo Source #
Constructors
ConnectInfo | |
Fields
|
Instances
Constructors
SSLInfo | |
Constructors
defaultConnectInfo :: ConnectInfo Source #
Default information for setting up a connection.
Defaults are as follows:
- Server on
localhost
- User
root
- No password
- Database
test
- Character set
utf8
Use as in the following example:
connect defaultConnectInfo { connectHost = "db.example.com" }
defaultSSLInfo :: SSLInfo Source #
Default (empty) information for setting up an SSL connection.
data Connection Source #
Connection to a MySQL database.
Column types supported by MySQL.
data MySQLError Source #
The constructors of MySQLError
are not currently exported, but they
have a consistent set of field names which are exported. These fields are:
errFunction :: String errNumber :: Int errMessage :: String
Instances
Connection management
connect :: ConnectInfo -> IO Connection Source #
Connect to a database.
close :: Connection -> IO () Source #
Close a connection, and mark any outstanding Result
as
invalid.
autocommit :: Connection -> Bool -> IO () Source #
Turn autocommit on or off.
By default, MySQL runs with autocommit mode enabled. In this mode, as soon as you modify a table, MySQL stores your modification permanently.
ping :: Connection -> IO () Source #
changeUser :: Connection -> String -> String -> Maybe String -> IO () Source #
setCharacterSet :: Connection -> String -> IO () Source #
Connection information
serverInfo :: Connection -> IO String Source #
protocolInfo :: Connection -> IO Word Source #
characterSet :: Connection -> IO String Source #
serverStatus :: Connection -> IO String Source #
Querying
query :: Connection -> ByteString -> IO () Source #
insertID :: Connection -> IO Word64 Source #
Return the value generated for an AUTO_INCREMENT
column by the
previous INSERT
or UPDATE
statement.
See http://dev.mysql.com/doc/refman/5.5/en/mysql-insert-id.html
Escaping
escape :: Connection -> ByteString -> IO ByteString Source #
Results
fieldCount :: Either Connection Result -> IO Int Source #
Return the number of fields (columns) in a result.
- If
Left
Connection
, returns the number of columns for the most recent query on the connection. - For
Right
Result
, returns the number of columns in each row of this result.
The number of columns may legitimately be zero.
affectedRows :: Connection -> IO Int64 Source #
Working with results
isResultValid :: Result -> IO Bool Source #
Check whether a Result
is still valid, i.e. backed by a live
MYSQL_RES
value.
freeResult :: Result -> IO () Source #
Immediately free the MYSQL_RES
value associated with this
Result
, and mark the Result
as invalid.
storeResult :: Connection -> IO Result Source #
Retrieve a complete result.
Any previous outstanding Result
is first marked as invalid.
useResult :: Connection -> IO Result Source #
Initiate a row-by-row retrieval of a result.
Any previous outstanding Result
is first marked as invalid.
Multiple results
nextResult :: Connection -> IO Bool Source #
Transactions
commit :: Connection -> IO () Source #
Commit the current transaction.
rollback :: Connection -> IO () Source #
Roll back the current transaction.
General information
clientInfo :: String Source #
clientVersion :: Word Source #
Concurrency
initLibrary :: IO () Source #
Call mysql_library_init
A single-threaded program can rely on an implicit initialisation done
when making the first connection, but a multi-threaded one should call
initLibrary
separately, and it should be done before other threads
might call into this library, since this function is not thread-safe.
See https://ro-che.info/articles/2015-04-17-safe-concurrent-mysql-haskell
and https://dev.mysql.com/doc/refman/5.7/en/c-api-threaded-clients.html
for details.
initThread :: IO () Source #
Call mysql_thread_init
Again a single-threaded program does not need to call this explicitly. Even
in a multi-threaded one, if each connection is made, used, and destroyed
in a single thread, it is sufficient to rely on the connect
call to do
an implicit thread initialisation. But in other cases, for example when
using a connection pool, each thread requires explicit initialisation.
See https://ro-che.info/articles/2015-04-17-safe-concurrent-mysql-haskell
and https://dev.mysql.com/doc/refman/5.7/en/c-api-threaded-clients.html
for details.
Call mysql_thread_end
This is needed at thread exit to avoid a memory leak, except when using
a non-debug build of at least version 5.7.9 of the MySQL library.
See https://dev.mysql.com/doc/refman/5.7/en/mysql-thread-end.html.
The threads in question are the OS threads, so calling this function
is likely to be important when using large numbers of bound threads (see
Control.Concurrent). Unbound threads - those created with forkIO
and
friends - share a small number of OS threads, so in those it is hard to
call this function safely, and there is little benefit in doing so, but in
any case using this library in unbound threads is not recommended (see
https://ro-che.info/articles/2015-04-17-safe-concurrent-mysql-haskell).