Skip to content

Commit

Permalink
Support multiple in-memory databases (#86)
Browse files Browse the repository at this point in the history
* cleanup config storage

* fix comments
  • Loading branch information
tanner0101 authored Jul 16, 2020
1 parent d6f72bb commit 442968e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 35 deletions.
34 changes: 34 additions & 0 deletions Sources/SQLiteKit/SQLiteConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import struct Foundation.UUID

public struct SQLiteConfiguration {
public enum Storage {
/// Stores the SQLite database in memory.
///
/// Uses a randomly generated identifier. See `memory(identifier:)`.
public static var memory: Self {
.memory(identifier: UUID().uuidString)
}

/// Stores the SQLite database in memory.
/// - parameters:
/// - identifier: Uniquely identifies the in-memory storage.
/// Connections using the same identifier share data.
case memory(identifier: String)

/// Uses the SQLite database file at the specified path.
///
/// Non-absolute paths will check the current working directory.
case file(path: String)
}

public var storage: Storage

/// If `true`, foreign keys will be enabled automatically on new connections.
public var enableForeignKeys: Bool

/// Creates a new `SQLiteConfiguration`.
public init(storage: Storage, enableForeignKeys: Bool = true) {
self.storage = storage
self.enableForeignKeys = enableForeignKeys
}
}
36 changes: 2 additions & 34 deletions Sources/SQLiteKit/SQLiteConnectionSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ public struct SQLiteConnectionSource: ConnectionPoolSource {

private var connectionStorage: SQLiteConnection.Storage {
switch self.configuration.storage {
case .memory:
case .memory(let identifier):
return .file(
path: "file:\(ObjectIdentifier(threadPool).unique)?mode=memory&cache=shared"
path: "file:\(identifier)?mode=memory&cache=shared"
)
case .file(let path):
return .file(path: path)
case .connection(let storage):
return storage
}
}

Expand Down Expand Up @@ -45,34 +43,4 @@ public struct SQLiteConnectionSource: ConnectionPoolSource {
}
}

public struct SQLiteConfiguration {
public enum Storage {
case memory
case file(path: String)
case connection(SQLiteConnection.Storage)
}

public var storage: Storage
public var enableForeignKeys: Bool

public init(storage: Storage, enableForeignKeys: Bool = true) {
self.storage = storage
self.enableForeignKeys = enableForeignKeys
}
}

extension SQLiteConnection: ConnectionPoolItem { }


private extension ObjectIdentifier {
var unique: String {
let raw = "\(self)"
let parts = raw.split(separator: "(")
switch parts.count {
case 2:
return parts[1].split(separator: ")").first.flatMap(String.init) ?? raw
default:
return raw
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SQLiteKit
import SQLKitBenchmark
import XCTest

class SQLiteTests: XCTestCase {
class SQLiteKitTests: XCTestCase {
func testSQLKitBenchmark() throws {
let benchmark = SQLBenchmarker(on: db)
try benchmark.run()
Expand Down Expand Up @@ -95,6 +95,31 @@ class SQLiteTests: XCTestCase {
XCTAssertEqual(res[0].column("foreign_keys"), .integer(1))
}

func testMultipleInMemoryDatabases() throws {
let a = SQLiteConnectionSource(
configuration: .init(storage: .memory, enableForeignKeys: true),
threadPool: self.threadPool
)
let b = SQLiteConnectionSource(
configuration: .init(storage: .memory, enableForeignKeys: true),
threadPool: self.threadPool
)

let a1 = try a.makeConnection(logger: .init(label: "test"), on: self.eventLoopGroup.next()).wait()
defer { try! a1.close().wait() }
let a2 = try a.makeConnection(logger: .init(label: "test"), on: self.eventLoopGroup.next()).wait()
defer { try! a2.close().wait() }
let b1 = try b.makeConnection(logger: .init(label: "test"), on: self.eventLoopGroup.next()).wait()
defer { try! b1.close().wait() }
let b2 = try b.makeConnection(logger: .init(label: "test"), on: self.eventLoopGroup.next()).wait()
defer { try! b2.close().wait() }

_ = try a1.query("CREATE TABLE foo (bar INTEGER)").wait()
_ = try a2.query("SELECT * FROM foo").wait()
_ = try b1.query("CREATE TABLE foo (bar INTEGER)").wait()
_ = try b2.query("SELECT * FROM foo").wait()
}

var db: SQLDatabase {
self.connection.sql()
}
Expand Down

0 comments on commit 442968e

Please sign in to comment.