persistent-mysql-pure
This is a fork of persistent-mysql-haskell.
Using the latest branch
from chordify.
A pure haskell backend for persistent using the MySQL database server.
Internally it uses the mysql-pure driver in order to access the database.
See example/Main.hs for how this MySQL backend can be used with Persistent.
Motivation
persistent-mysql
uses mysql (via mysql-simple) as the database driver. mysql
is a haskell FFI wrapper for mysqlclient
written in C.
Reasons to use a pure haskell driver:
Personal experience on replacing mysql-simple
with mysql-pure
in a project:
-
Performance gains consistent with benchmark.
-
Smoother deployment to AWS, since mysql
appears to have a hard dependency on the oracle version of libmysqlclient
that does not work with the open source variant that is available by default on Amazon Linux (and possibly on other Linux distros).
Potential issues moving from persistent-mysql to persistent-mysql-pure
ConnectInfo
and defaultConnectInfo
are not the same between mysql
and mysql-pure
, therefore this package is not a 100% drop in replacement for persistent-mysql from the connection configuration perspective.
-
mysql-pure
does not allow provide an API for the entirety of mysqlclient options. Therefore neither can this package.
-
Given the inevitable incompatibility with persistent-mysql
, and in the interest of providing a forward-compatible API, ConnectInfo
internals and defaultConnectInfo
have been deprecated. However the similar utility can be achieved like so:
import Database.Persist.MySQL
connectInfo :: MySQLConnectInfo
- connectInfo = defaultConnectInfo
- { connectHost = "localhost"
- , connectUser = "test"
- , connectPassword = "test"
- , connectDatabase = "test"
- }
+ connectInfo = mkMySQLConnectInfo "localhost" "test" "test" "test"
connectInfoNewPort :: MySQLConnectInfo
- connectInfoNewPort = connectInfo { connectPort = 3307 }
+ connectInfoNewPort = setMySQLConnectInfoPort 3307 connectInfo
connectInfoNewCharSet :: MySQLConnectInfo
- connectInfoNewCharSet = connectInfo { connectOptions = [CharsetName "utf8"] }
+ connectInfoNewCharSet = setMySQLConnectInfoCharset 33 connectInfo
-
mysql-pure
and mysql
have different APIs/mechanisms for securing the
connection to MySQL. persistent-mysql-pure
exposes an API to utilize
TLS client params
that ships with mysql-pure
.
connectInfoCustomCaStore :: MySQLConnectInfo
- connectInfoCustomCaStore = connectInfo { connectSSL = Just customCaParams }
+ connectInfoCustomCaStore = setMySQLConnectInfoTLS customCaParams connectInfo
where
- customCaParams = defaultSSLInfo { sslCAPath = "foobar.pem" }
+ customCaParams = makeClientParams $ CustomCAStore "foobar.pem"
Aside from connection configuration, persistent-mysql-pure is functionally on par with persistent-mysql (as of writing this). This can be seen by comparing persistent-test between this fork and upstream.
Yesod
In order to use persistent-mysql-pure
with yesod
you have to modify Settings.hs
:
- import Database.Persist.MySQL (MySQLConf (..))
+ import Database.Persist.MySQL (MySQLConf, mkMySQLConf, myConnInfo, myPoolSize, setMySQLConnectInfoCharset)
- import qualified Database.MySQL.Base as MySQL
- -- This code enables MySQL's strict mode, without which MySQL will truncate data.
- -- See https://github.com/yesodweb/persistent/wiki/Database-Configuration#strict-mode for details
- -- If you choose to keep strict mode enabled, it's recommended that you enable it in your my.cnf file so that it's also enabled for your MySQL console sessions.
- -- (If you enable it in your my.cnf file, you can delete this code).
- let appDatabaseConf = fromYamlAppDatabaseConf { myConnInfo = (myConnInfo fromYamlAppDatabaseConf) {
- MySQL.connectOptions =
- ( MySQL.connectOptions (myConnInfo fromYamlAppDatabaseConf)) ++ [MySQL.InitCommand "SET SESSION sql_mode = 'STRICT_ALL_TABLES';\0"]
- }
- }
And in Application.hs
:
- import qualified Database.MySQL.Base as MySQL
import Network.Wai.Handler.Warp (Settings, defaultSettings,
defaultShouldDisplayException,
runSettings, setHost,
- setFork, setOnOpen, setOnClose,
+ setFork,
setOnException, setPort, getPort)
- -- See http://www.yesodweb.com/blog/2016/11/use-mysql-safely-in-yesod
- MySQL.initLibrary
- $ setOnOpen (const $ MySQL.initThread >> return True)
- $ setOnClose (const MySQL.endThread)
Optionally you may enable the MYSQL strict mode (in each transaction)
by modifying Foundation.hs
(or editing the my.cnf
server configuration):
- import Database.Persist.Sql (ConnectionPool, runSqlPool)
+ import Database.Persist.Sql (ConnectionPool, rawExecute, runSqlPool)
- runSqlPool action $ appConnPool master
+ runSqlPool
+ (rawExecute "SET SESSION sql_mode = 'STRICT_ALL_TABLES'" [] >> action)
+ (appConnPool master)
FAQs
Why isn't this part of the main/upstream persistent repo?
persistent-mysql supports X but persistent-mysql-pure API doesn't. Why?
-
Internals (getters/setters) of MySQLConnectInfo and defaultConnectInfo
are intentionally masked for forward compatibility.
-
For all others, feel free to open an issue and/or submit a PR.
Does persistent-mysql-pure ship with tests?