persistent-mysql-haskell
A pure haskell backend for the persistent library using MySQL database server.
http://www.yesodweb.com/book/persistent
Version on this page: | 0.5.2 |
LTS Haskell 14.27: | 0.5.2 |
Stackage Nightly 2019-08-07: | 0.5.2 |
Latest on Hackage: | 0.6.0 |
persistent-mysql-haskell-0.5.2@sha256:e3119000465a1facbf4d3cad111f816c5008eb9182d4c4a6b8d8a4a2a5ded1b5,2847
Module documentation for 0.5.2
- Database
- Database.Persist
persistent-mysql-haskell
A pure haskell backend for persistent using the MySQL database server. Internally it uses the mysql-haskell 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:
-
mysql
has concurrency issues as noted by @feuerbach. -
mysql-haskell, a pure haskell driver by @winterland1989, outperforms
mysql-simple
in benchmarks (see hackage or project repo). -
better portability and possible static compilation of an entire project that uses
persistent-mysql
. -
result streaming support means persistent
selectSource
streams data from database. Effectively addressing #657 selectSource does not stream results. -
a newtype-d
MySQLConnectInfo
allows adding configuring how persistent and the underlying driver are glued. Ex: #679 can be elegantly addressed in this library.
Personal experience on replacing mysql-simple
with mysql-haskell
in a project:
-
Performance gains consistent with benchmark.
-
Smoother deployment to AWS, since
mysql
appears to have a hard dependency on the oracle version oflibmysqlclient
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-haskell
ConnectInfo
and defaultConnectInfo
are not the same between mysql
and mysql-haskell
, therefore this package is not a 100% drop in replacement for persistent-mysql from the connection configuration perspective.
-
mysql-haskell
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 anddefaultConnectInfo
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-haskell
andmysql
have different APIs/mechanisms for securing the connection to MySQL.persistent-mysql-haskell
exposes an API to utilize TLS client params that ships withmysql-haskell
.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-haskell 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-haskell
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?
- TLDR: Upstream wants to gauge community interest before absorbing this backend into the main repo.
- Long version: See issue yesodweb/persistent/issues/659.
persistent-mysql supports X but persistent-mysql-haskell 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-haskell ship with tests?
-
It does! :)
persistent-test
is fully re-used with an additional flag to specifically test persistent-mysql-haskell.-
CI/Travis, see .travis.yml.
-
Local,
stack test persistent-test --flag persistent-test:mysql_haskell --exec persistent-test
-
Changes
ChangeLog for persistent-mysql-haskell
0.5.2
- Fix stackage#4312: Relax
network
version bound.
0.5.1
- #9 Add
insertEntityOnDuplicateKeyUpdate
andinsertEntityManyOnDuplicateKeyUpdate
functions
0.5.0
- Port #812 from
persistent-mysql
: Add support for SQL isolation levels - Port #833 from
persistent-mysql
:repsertMany
now matchesmapM_ (uncurry repsert)
and is atomic.
0.4.2
- #7 Fix boolean conversion bug.
0.4.1
- Fix #2: Better compatibility with
yesod
scaffold.
0.4.0
- Port #770 from
persistent-mysql
: Performance enhancements for bulk writes. - Port #773 from
persistent-mysql
: Support new conduit release. Includes bundled changes from other PRs.
0.3.6
- Port #752 from
persistent-mysql
: Fix mysql sqltype migrations.
0.3.5
- Updated
selectSource
implementation to stream results instead of loading everything into memory.
0.3.4.1
- Fix a haddock issue down-streamed from #693.
0.3.4
- Port #693 from
persistent-mysql
: Extend theSomeField
type to allowinsertManyOnDuplicateKeyUpdate
to conditionally copy values. - Port #702 from
persistent-mysql
: Fix behavior ofinsertManyOnDuplicateKeyUpdate
to ignore duplicate key exceptions when no updates specified. - Bumped TLS bounds to be in sync with
mysql-haskell
and land ourselves back on stackage.
0.3.3
- Port from
persistent-mysql
: MySQL on duplicate key update #674.
0.3.2.1
- Port from
persistent-mysql
: Prevent spurious no-op migrations whendefault=NULL
is specified - revised version #672 (which fixes bug #671 introduced by the earlier attempt #641).
0.3.2.0
- Added conditional declaration of
Show
instance for mysql-haskell’sConnectInfo
for compatibility withmysql-haskell-0.8.1.0+
.
0.3.1.0
- Fixed compiler warnings in
stack --pedantic
mode so the project can run upstream tests on Travis. - Minor README enhancements for badges and fixed URL for example when viewing outside of Github.
0.3.0.0
- Added API for setting TLS client parameters for secure MySQL connections.
- Exported Data.TLSSetting for convenient usage of TLS.
0.2.1.0
- Bumped up version to update README.
0.2.0.0
- Added APIs for setting port number and character encoding.
- Updated type signature for mkMySQLConnectInfo to align with mysql-haskell.
0.1.1.0
- Bumped up version to include README and example.
0.1.0.0
- Ported persistent-mysql 2.6 to use mysql-haskell as the underlying database driver.
- Deprecated MySQLConf and ConnectInfo native constructor and default instance in favor of mk functions for better forward compatibility. See http://www.snoyman.com/blog/2016/11/designing-apis-for-extensibility.