@@ -30,7 +30,7 @@ import Control.Exception
30
30
import Control.Monad
31
31
import Control.Monad.Reader
32
32
33
- import Database.SQLite.Simple (open , close , query_ )
33
+ import Database.SQLite.Simple (open , close , query_ , execute_ , Query ( .. ) )
34
34
35
35
import Data.Aeson
36
36
import Data.Attoparsec.Text (asciiCI , skipSpace )
@@ -50,19 +50,32 @@ import qualified Data.Text.Encoding as TE
50
50
-- | Top-level 'Tool.BeamMigrationBackend'
51
51
migrationBackend :: Tool. BeamMigrationBackend Sqlite SqliteM
52
52
migrationBackend = Tool. BeamMigrationBackend
53
- " sqlite"
54
- " For beam-sqlite, this is the path to a sqlite3 file"
55
- getDbConstraints
56
- (Db. sql92Deserializers <> sqliteDataTypeDeserializers <>
57
- Db. beamCheckDeserializers)
58
- (BL. unpack . (<> " ;" ) . sqliteRenderSyntaxScript . fromSqliteCommand)
59
- " sqlite.sql"
60
- sqlitePredConverter Db. defaultActionProvider
61
- (\ fp action ->
62
- bracket (open fp) close $ \ conn ->
63
- catch (Right <$> runReaderT (runSqliteM action)
64
- (\ _ -> pure () , conn))
65
- (\ e -> pure (Left (show (e :: SomeException )))))
53
+ { Tool. backendName = " sqlite"
54
+ , Tool. backendConnStringExplanation = " For beam-sqlite, this is the path to a sqlite3 file"
55
+ , Tool. backendGetDbConstraints = getDbConstraints
56
+ , Tool. backendPredicateParsers = Db. sql92Deserializers <> sqliteDataTypeDeserializers <>
57
+ Db. beamCheckDeserializers
58
+ , Tool. backendRenderSyntax = (BL. unpack . (<> " ;" ) . sqliteRenderSyntaxScript . fromSqliteCommand)
59
+ , Tool. backendFileExtension = " sqlite.sql"
60
+ , Tool. backendConvertToHaskell = sqlitePredConverter
61
+ , Tool. backendActionProvider = Db. defaultActionProvider
62
+ , Tool. backendRunSqlScript = runSqlScript
63
+ , Tool. backendWithTransaction =
64
+ \ (SqliteM go) ->
65
+ SqliteM . ReaderT $ \ ctx@ (pt, conn) ->
66
+ mask $ \ unmask -> do
67
+ let ex q = pt (show q) >> execute_ conn q
68
+ ex " BEGIN TRANSACTION"
69
+ unmask (runReaderT go ctx <* ex " COMMIT TRANSACTION" ) `catch`
70
+ \ (SomeException e) -> ex " ROLLBACK TRANSACTION" >> throwIO e
71
+ , Tool. backendConnect = \ fp -> do
72
+ conn <- open fp
73
+ pure Tool. BeamMigrateConnection
74
+ { Tool. backendRun = \ action ->
75
+ catch (Right <$> runReaderT (runSqliteM action)
76
+ (\ _ -> pure () , conn))
77
+ (\ e -> pure (Left (show (e :: SomeException ))))
78
+ , Tool. backendClose = close conn } }
66
79
67
80
-- | 'Db.BeamDeserializers' or SQLite specific types. Specifically,
68
81
-- 'sqliteBlob', 'sqliteText', and 'sqliteBigInt'. These are compatible with the
@@ -78,8 +91,13 @@ sqliteDataTypeDeserializers =
78
91
" bigint" -> pure sqliteBigIntType
79
92
Object o ->
80
93
(fmap (\ (_ :: Maybe Word ) -> sqliteBlobType) (o .: " binary" )) <|>
81
- (fmap (\ (_ :: Maybe Word ) -> sqliteBlobType) (o .: " varbinary" ))
94
+ (fmap (\ (_ :: Maybe Word ) -> sqliteBlobType) (o .: " varbinary" )) <|>
95
+ Db. beamDeserializeJSON " sqlite" customDtParser v
82
96
_ -> fail " Could not parse sqlite-specific data type"
97
+ where
98
+ customDtParser = withObject " custom data type" $ \ v -> do
99
+ txt <- v .: " custom"
100
+ pure (parseSqliteDataType txt)
83
101
84
102
-- | Render a series of 'Db.MigrationSteps' in the 'SqliteCommandSyntax' into a
85
103
-- line-by-line list of lazy 'BL'ByteString's. The output is suitable for
@@ -121,15 +139,19 @@ sqliteTypeToHs :: SqliteDataTypeSyntax
121
139
-> Maybe HsDataType
122
140
sqliteTypeToHs = Just . sqliteDataTypeToHs
123
141
142
+ customSqliteDataType :: T. Text -> SqliteDataTypeSyntax
143
+ customSqliteDataType txt =
144
+ SqliteDataTypeSyntax (emit (TE. encodeUtf8 txt))
145
+ (hsErrorType (" Unknown SQLite datatype '" ++ T. unpack txt ++ " '" ))
146
+ (Db. BeamSerializedDataType $
147
+ Db. beamSerializeJSON " sqlite"
148
+ (object [ " custom" .= txt ]))
149
+ False
150
+
124
151
parseSqliteDataType :: T. Text -> SqliteDataTypeSyntax
125
152
parseSqliteDataType txt =
126
153
case A. parseOnly dtParser txt of
127
- Left {} -> SqliteDataTypeSyntax (emit (TE. encodeUtf8 txt))
128
- (hsErrorType (" Unknown SQLite datatype '" ++ T. unpack txt ++ " '" ))
129
- (Db. BeamSerializedDataType $
130
- Db. beamSerializeJSON " sqlite"
131
- (toJSON txt))
132
- False
154
+ Left {} -> customSqliteDataType txt
133
155
Right x -> x
134
156
where
135
157
dtParser = charP <|> varcharP <|>
@@ -226,6 +248,11 @@ parseSqliteDataType txt =
226
248
asciiCI " SET" *> ws *>
227
249
A. takeWhile (not . isSpace))
228
250
251
+ runSqlScript :: T. Text -> SqliteM ()
252
+ runSqlScript t =
253
+ SqliteM . ReaderT $ \ (_, conn) ->
254
+ execute_ conn (Query t)
255
+
229
256
-- TODO constraints and foreign keys
230
257
231
258
-- | Get a list of database predicates for the current database. This is beam's
0 commit comments