Skip to content

Commit

Permalink
Merge pull request yesodweb#9 from ianthehenry/sqlite-fks
Browse files Browse the repository at this point in the history
update the SQLite foreign key example
  • Loading branch information
psibi authored Jun 23, 2016
2 parents 7ab4ee9 + b8082fc commit 5c7b5bf
Showing 1 changed file with 14 additions and 12 deletions.
26 changes: 14 additions & 12 deletions cookbook/Activate-foreign-key-checking-in-Sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ In SQLite, foreign keys checks [are not enabled by default](https://www.sqlite.o
PRAGMA foreign_keys = ON;
```

The command to issue foreign keys is [a noop if done inside of a transaction](https://www.sqlite.org/foreignkeys.html#fk_enable), so it is necessary to enable them outside of one. Persistent functions like `runSqlPersistMPool` wrap your statements inside of a transaction, necessitating dropping down to the underlying Database.Sqlite package to enable foreign keys. To do this, add the following imports and functions to `Application.hs`:
The command to issue foreign keys is [a noop if done inside of a transaction](https://www.sqlite.org/foreignkeys.html#fk_enable), so it is necessary to enable them outside of one. Persistent functions like `runSqlPersistMPool` wrap your statements inside of a transaction, necessitating dropping down to the underlying `Database.Sqlite` package to enable foreign keys. To do this, add the following imports and functions to `Application.hs`:

```haskell
import qualified Database.Sqlite as Sqlite
import Database.Persist.Sqlite (createSqlPool, wrapConnection)
import Database.Persist.Sqlite (createSqlPool, wrapConnection)

rawConnection :: Text -> IO Sqlite.Connection
rawConnection t = Sqlite.open t
enableForeignKeys :: Sqlite.Connection -> IO ()
enableForeignKeys conn = Sqlite.prepare conn "PRAGMA foreign_keys = ON;" >>= void . Sqlite.step

createSqliteBackend :: Text -> LogFunc -> IO SqlBackend
createSqliteBackend connStr logFunc = do
conn <- Sqlite.open connStr
enableForeignKeys conn
wrapConnection conn logFunc

disableForeignKeys :: Sqlite.Connection -> IO ()
disableForeignKeys conn = Sqlite.prepare conn "PRAGMA foreign_keys = ON;" >>= void . Sqlite.step
```

Then, in the `makeFoundation` function, replace this code:
Expand All @@ -30,18 +34,16 @@ pool <- flip runLoggingT logFunc $ createSqlitePool
with this:

```
sqliteConn <- rawConnection (sqlDatabase $ appDatabaseConf appSettings)
disableForeignKeys sqliteConn
pool <- flip runLoggingT logFunc $ createSqlPool
(wrapConnection sqliteConn)
let dbPath = sqlDatabase (appDatabaseConf appSettings)
pool <- flip runLoggingT logFunc $ createSqlPool
(createSqliteBackend dbPath)
(sqlPoolSize $ appDatabaseConf appSettings)
```

You can then verify that foreign keys are enabled by sending `PRAGMA foreign_keys` to SQLite:

```haskell
import Database.Persist.Sql (SqlBackend, rawSql, unSingle)
import Database.Persist.Sql (SqlBackend, rawSql, unSingle)

fksEnabled :: MonadIO m => ReaderT SqlBackend m Bool
fksEnabled = do
Expand Down

0 comments on commit 5c7b5bf

Please sign in to comment.