Skip to content

Commit ff7bdbc

Browse files
committed
Merge branch 'master' into rcv-services
2 parents 38e8999 + cf9b7e5 commit ff7bdbc

File tree

6 files changed

+40
-22
lines changed

6 files changed

+40
-22
lines changed

src/Simplex/Messaging/Agent/Store/SQLite.hs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ import Simplex.Messaging.Agent.Store.Migrations (DBMigrate (..), sharedMigrateSc
6767
import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations
6868
import Simplex.Messaging.Agent.Store.SQLite.Common
6969
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
70-
import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationConfig (..), MigrationError (..))
7170
import Simplex.Messaging.Agent.Store.SQLite.Util (SQLiteFunc, createStaticFunction, mkSQLiteFunc)
71+
import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationConfig (..), MigrationError (..))
7272
import qualified Simplex.Messaging.Crypto as C
7373
import Simplex.Messaging.Util (ifM, safeDecodeUtf8)
7474
import System.Directory (copyFile, createDirectoryIfMissing, doesFileExist)
@@ -77,10 +77,10 @@ import System.FilePath (takeDirectory, takeFileName, (</>))
7777
-- * SQLite Store implementation
7878

7979
createDBStore :: DBOpts -> [Migration] -> MigrationConfig -> IO (Either MigrationError DBStore)
80-
createDBStore opts@DBOpts {dbFilePath, dbKey, keepKey, track} migrations migrationConfig = do
80+
createDBStore opts@DBOpts {dbFilePath} migrations migrationConfig = do
8181
let dbDir = takeDirectory dbFilePath
8282
createDirectoryIfMissing True dbDir
83-
st <- connectSQLiteStore dbFilePath dbKey keepKey track
83+
st <- connectSQLiteStore opts
8484
r <- migrateDBSchema st opts Nothing migrations migrationConfig `onException` closeDBStore st
8585
case r of
8686
Right () -> pure $ Right st
@@ -99,23 +99,24 @@ migrateDBSchema st DBOpts {dbFilePath, vacuum} migrationsTable migrations Migrat
9999
dbm = DBMigrate {initialize, getCurrent, run, backup}
100100
in sharedMigrateSchema dbm (dbNew st) migrations confirm
101101

102-
connectSQLiteStore :: FilePath -> ScrubbedBytes -> Bool -> DB.TrackQueries -> IO DBStore
103-
connectSQLiteStore dbFilePath key keepKey track = do
102+
connectSQLiteStore :: DBOpts -> IO DBStore
103+
connectSQLiteStore DBOpts {dbFilePath, dbFunctions, dbKey = key, keepKey, track} = do
104104
dbNew <- not <$> doesFileExist dbFilePath
105-
dbConn <- dbBusyLoop (connectDB dbFilePath key track)
105+
dbConn <- dbBusyLoop $ connectDB dbFilePath dbFunctions key track
106106
dbConnection <- newMVar dbConn
107107
dbKey <- newTVarIO $! storeKey key keepKey
108108
dbClosed <- newTVarIO False
109109
dbSem <- newTVarIO 0
110-
pure DBStore {dbFilePath, dbKey, dbSem, dbConnection, dbNew, dbClosed}
110+
pure DBStore {dbFilePath, dbFunctions, dbKey, dbSem, dbConnection, dbNew, dbClosed}
111111

112-
connectDB :: FilePath -> ScrubbedBytes -> DB.TrackQueries -> IO DB.Connection
113-
connectDB path key track = do
112+
connectDB :: FilePath -> [SQLiteFuncDef] -> ScrubbedBytes -> DB.TrackQueries -> IO DB.Connection
113+
connectDB path functions key track = do
114114
db <- DB.open path track
115115
prepare db `onException` DB.close db
116116
-- _printPragmas db path
117117
pure db
118118
where
119+
functions' = SQLiteFuncDef "simplex_xor_md5_combine" 2 True sqliteXorMd5CombinePtr : functions
119120
prepare db = do
120121
let db' = SQL.connectionHandle $ DB.conn db
121122
unless (BA.null key) . SQLite3.exec db' $ "PRAGMA key = " <> keyString key <> ";"
@@ -127,8 +128,9 @@ connectDB path key track = do
127128
PRAGMA secure_delete = ON;
128129
PRAGMA auto_vacuum = FULL;
129130
|]
130-
createStaticFunction db' "simplex_xor_md5_combine" 2 True sqliteXorMd5CombinePtr
131-
>>= either (throwIO . userError . show) pure
131+
forM_ functions' $ \SQLiteFuncDef {funcName, argCount, deterministic, funcPtr} ->
132+
createStaticFunction db' funcName argCount deterministic funcPtr
133+
>>= either (throwIO . userError . show) pure
132134

133135
foreign export ccall "simplex_xor_md5_combine" sqliteXorMd5Combine :: SQLiteFunc
134136

@@ -155,12 +157,12 @@ openSQLiteStore st@DBStore {dbClosed} key keepKey =
155157
ifM (readTVarIO dbClosed) (openSQLiteStore_ st key keepKey) (putStrLn "openSQLiteStore: already opened")
156158

157159
openSQLiteStore_ :: DBStore -> ScrubbedBytes -> Bool -> IO ()
158-
openSQLiteStore_ DBStore {dbConnection, dbFilePath, dbKey, dbClosed} key keepKey =
160+
openSQLiteStore_ DBStore {dbConnection, dbFilePath, dbFunctions, dbKey, dbClosed} key keepKey =
159161
bracketOnError
160162
(takeMVar dbConnection)
161163
(tryPutMVar dbConnection)
162164
$ \DB.Connection {slow, track} -> do
163-
DB.Connection {conn} <- connectDB dbFilePath key track
165+
DB.Connection {conn} <- connectDB dbFilePath dbFunctions key track
164166
atomically $ do
165167
writeTVar dbClosed False
166168
writeTVar dbKey $! storeKey key keepKey

src/Simplex/Messaging/Agent/Store/SQLite/Common.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
module Simplex.Messaging.Agent.Store.SQLite.Common
77
( DBStore (..),
88
DBOpts (..),
9+
SQLiteFuncDef (..),
910
withConnection,
1011
withConnection',
1112
withTransaction,
@@ -20,9 +21,13 @@ import Control.Concurrent (threadDelay)
2021
import Control.Concurrent.STM (retry)
2122
import Data.ByteArray (ScrubbedBytes)
2223
import qualified Data.ByteArray as BA
24+
import Data.ByteString (ByteString)
2325
import Database.SQLite.Simple (SQLError)
2426
import qualified Database.SQLite.Simple as SQL
27+
import Database.SQLite3.Bindings
28+
import Foreign.Ptr
2529
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
30+
import Simplex.Messaging.Agent.Store.SQLite.Util
2631
import Simplex.Messaging.Util (ifM, unlessM)
2732
import qualified UnliftIO.Exception as E
2833
import UnliftIO.MVar
@@ -33,6 +38,7 @@ storeKey key keepKey = if keepKey || BA.null key then Just key else Nothing
3338

3439
data DBStore = DBStore
3540
{ dbFilePath :: FilePath,
41+
dbFunctions :: [SQLiteFuncDef],
3642
dbKey :: TVar (Maybe ScrubbedBytes),
3743
dbSem :: TVar Int,
3844
dbConnection :: MVar DB.Connection,
@@ -42,12 +48,21 @@ data DBStore = DBStore
4248

4349
data DBOpts = DBOpts
4450
{ dbFilePath :: FilePath,
51+
dbFunctions :: [SQLiteFuncDef],
4552
dbKey :: ScrubbedBytes,
4653
keepKey :: Bool,
4754
vacuum :: Bool,
4855
track :: DB.TrackQueries
4956
}
5057

58+
-- e.g. `SQLiteFuncDef "name" 2 True f`
59+
data SQLiteFuncDef = SQLiteFuncDef
60+
{ funcName :: ByteString,
61+
argCount :: CArgCount,
62+
deterministic :: Bool,
63+
funcPtr :: FunPtr SQLiteFunc
64+
}
65+
5166
withConnectionPriority :: DBStore -> Bool -> (DB.Connection -> IO a) -> IO a
5267
withConnectionPriority DBStore {dbSem, dbConnection} priority action
5368
| priority = E.bracket_ signal release $ withMVar dbConnection action

tests/AgentTests/FunctionalAPITests.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3715,7 +3715,7 @@ insertUser :: DBStore -> IO ()
37153715
insertUser st = withTransaction st (`DB.execute_` "INSERT INTO users DEFAULT VALUES")
37163716
#else
37173717
createStore :: String -> IO (Either MigrationError DBStore)
3718-
createStore dbPath = createAgentStore (DBOpts dbPath "" False True DB.TQOff) (MigrationConfig MCError Nothing)
3718+
createStore dbPath = createAgentStore (DBOpts dbPath [] "" False True DB.TQOff) (MigrationConfig MCError Nothing)
37193719

37203720
insertUser :: DBStore -> IO ()
37213721
insertUser st = withTransaction st (`DB.execute_` "INSERT INTO users (user_id) VALUES (1)")

tests/AgentTests/MigrationTests.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ createStore randSuffix migrations confirmMigrations = do
230230
let dbOpts =
231231
DBOpts {
232232
dbFilePath = testDB randSuffix,
233+
dbFunctions = [],
233234
dbKey = "",
234235
keepKey = False,
235236
vacuum = True,

tests/AgentTests/SQLiteTests.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ withStore2 = before connect2 . after (removeStore . fst)
7272
connect2 :: IO (DBStore, DBStore)
7373
connect2 = do
7474
s1@DBStore {dbFilePath} <- createStore'
75-
s2 <- connectSQLiteStore dbFilePath "" False DB.TQOff
75+
s2 <- connectSQLiteStore $ DBOpts dbFilePath [] "" False False DB.TQOff
7676
pure (s1, s2)
7777

7878
createStore' :: IO DBStore
@@ -83,7 +83,7 @@ createEncryptedStore key keepKey = do
8383
-- Randomize DB file name to avoid SQLite IO errors supposedly caused by asynchronous
8484
-- IO operations on multiple similarly named files; error seems to be environment specific
8585
r <- randomIO :: IO Word32
86-
Right st <- createDBStore (DBOpts (testDB <> show r) key keepKey True DB.TQOff) appMigrations (MigrationConfig MCError Nothing)
86+
Right st <- createDBStore (DBOpts (testDB <> show r) [] key keepKey True DB.TQOff) appMigrations (MigrationConfig MCError Nothing)
8787
withTransaction' st (`SQL.execute_` "INSERT INTO users (user_id) VALUES (1);")
8888
pure st
8989

tests/AgentTests/SchemaDump.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,22 @@ testVerifySchemaDump :: IO ()
5151
testVerifySchemaDump = do
5252
savedSchema <- ifM (doesFileExist appSchema) (readFile appSchema) (pure "")
5353
savedSchema `deepseq` pure ()
54-
void $ createDBStore (DBOpts testDB "" False True TQOff) appMigrations (MigrationConfig MCConsole Nothing)
54+
void $ createDBStore (DBOpts testDB [] "" False True TQOff) appMigrations (MigrationConfig MCConsole Nothing)
5555
getSchema testDB appSchema `shouldReturn` savedSchema
5656
removeFile testDB
5757

5858
testVerifyLintFKeyIndexes :: IO ()
5959
testVerifyLintFKeyIndexes = do
6060
savedLint <- ifM (doesFileExist appLint) (readFile appLint) (pure "")
6161
savedLint `deepseq` pure ()
62-
void $ createDBStore (DBOpts testDB "" False True TQOff) appMigrations (MigrationConfig MCConsole Nothing)
62+
void $ createDBStore (DBOpts testDB [] "" False True TQOff) appMigrations (MigrationConfig MCConsole Nothing)
6363
getLintFKeyIndexes testDB "tests/tmp/agent_lint.sql" `shouldReturn` savedLint
6464
removeFile testDB
6565

6666
testSchemaMigrations :: IO ()
6767
testSchemaMigrations = do
6868
let noDownMigrations = dropWhileEnd (\Migration {down} -> isJust down) appMigrations
69-
Right st <- createDBStore (DBOpts testDB "" False True TQOff) noDownMigrations (MigrationConfig MCError Nothing)
69+
Right st <- createDBStore (DBOpts testDB [] "" False True TQOff) noDownMigrations (MigrationConfig MCError Nothing)
7070
mapM_ (testDownMigration st) $ drop (length noDownMigrations) appMigrations
7171
closeDBStore st
7272
removeFile testDB
@@ -89,19 +89,19 @@ testSchemaMigrations = do
8989

9090
testUsersMigrationNew :: IO ()
9191
testUsersMigrationNew = do
92-
Right st <- createDBStore (DBOpts testDB "" False True TQOff) appMigrations (MigrationConfig MCError Nothing)
92+
Right st <- createDBStore (DBOpts testDB [] "" False True TQOff) appMigrations (MigrationConfig MCError Nothing)
9393
withTransaction' st (`SQL.query_` "SELECT user_id FROM users;")
9494
`shouldReturn` ([] :: [Only Int])
9595
closeDBStore st
9696

9797
testUsersMigrationOld :: IO ()
9898
testUsersMigrationOld = do
9999
let beforeUsers = takeWhile (("m20230110_users" /=) . name) appMigrations
100-
Right st <- createDBStore (DBOpts testDB "" False True TQOff) beforeUsers (MigrationConfig MCError Nothing)
100+
Right st <- createDBStore (DBOpts testDB [] "" False True TQOff) beforeUsers (MigrationConfig MCError Nothing)
101101
withTransaction' st (`SQL.query_` "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'users';")
102102
`shouldReturn` ([] :: [Only String])
103103
closeDBStore st
104-
Right st' <- createDBStore (DBOpts testDB "" False True TQOff) appMigrations (MigrationConfig MCYesUp Nothing)
104+
Right st' <- createDBStore (DBOpts testDB [] "" False True TQOff) appMigrations (MigrationConfig MCYesUp Nothing)
105105
withTransaction' st' (`SQL.query_` "SELECT user_id FROM users;")
106106
`shouldReturn` ([Only (1 :: Int)])
107107
closeDBStore st'

0 commit comments

Comments
 (0)