Skip to content

Commit a9f4313

Browse files
authored
Merge pull request #57 from vapor/fluent-gm
FluentKit 1.0.0 GM
2 parents 549d5a5 + 479b8e1 commit a9f4313

File tree

6 files changed

+68
-21
lines changed

6 files changed

+68
-21
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ let package = Package(
1010
.library(name: "FluentSQLiteDriver", targets: ["FluentSQLiteDriver"]),
1111
],
1212
dependencies: [
13-
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-rc.1"),
14-
.package(url: "https://github.com/vapor/sqlite-kit.git", from: "4.0.0-rc.1"),
13+
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-rc.2"),
14+
.package(url: "https://github.com/vapor/sqlite-kit.git", from: "4.0.0-rc.1.1"),
1515
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
1616
],
1717
targets: [

Sources/FluentSQLiteDriver/FluentSQLiteDatabase.swift

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import FluentSQL
33
struct _FluentSQLiteDatabase {
44
let database: SQLiteDatabase
55
let context: DatabaseContext
6+
let inTransaction: Bool
67
}
78

89
extension _FluentSQLiteDatabase: Database {
@@ -43,9 +44,16 @@ extension _FluentSQLiteDatabase: Database {
4344
}
4445

4546
func transaction<T>(_ closure: @escaping (Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
46-
self.database.withConnection { conn in
47+
guard !self.inTransaction else {
48+
return closure(self)
49+
}
50+
return self.database.withConnection { conn in
4751
conn.query("BEGIN TRANSACTION").flatMap { _ in
48-
let db = _FluentSQLiteDatabase(database: conn, context: self.context)
52+
let db = _FluentSQLiteDatabase(
53+
database: conn,
54+
context: self.context,
55+
inTransaction: true
56+
)
4957
return closure(db).flatMap { result in
5058
conn.query("COMMIT TRANSACTION").map { _ in
5159
result
@@ -63,6 +71,7 @@ extension _FluentSQLiteDatabase: Database {
6371
switch schema.action {
6472
case .update:
6573
if schema.createFields.isEmpty {
74+
self.logger.warning("Ignoring schema update. SQLite only supports adding columns to existing tables")
6675
return self.eventLoop.makeSucceededFuture(())
6776
}
6877
default:
@@ -89,7 +98,7 @@ extension _FluentSQLiteDatabase: Database {
8998

9099
func withConnection<T>(_ closure: @escaping (Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
91100
self.database.withConnection {
92-
closure(_FluentSQLiteDatabase(database: $0, context: self.context))
101+
closure(_FluentSQLiteDatabase(database: $0, context: self.context, inTransaction: self.inTransaction))
93102
}
94103
}
95104
}
@@ -134,18 +143,25 @@ private struct LastInsertRow: DatabaseOutput {
134143
return self
135144
}
136145

137-
func contains(_ path: [FieldKey]) -> Bool {
138-
path[0] == .id || path[0] == self.customIDKey
146+
func contains(_ key: FieldKey) -> Bool {
147+
key == .id || key == self.customIDKey
148+
}
149+
150+
func decodeNil(_ key: FieldKey) throws -> Bool {
151+
guard key == .id || key == self.customIDKey else {
152+
fatalError("Cannot decode field from last insert row: \(key).")
153+
}
154+
return false
139155
}
140156

141-
func decode<T>(_ path: [FieldKey], as type: T.Type) throws -> T where T : Decodable {
142-
guard path[0] == .id || path[0] == self.customIDKey else {
143-
fatalError("Cannot decode field from last insert row: \(path).")
157+
func decode<T>(_ key: FieldKey, as type: T.Type) throws -> T where T : Decodable {
158+
guard key == .id || key == self.customIDKey else {
159+
fatalError("Cannot decode field from last insert row: \(key).")
144160
}
145161
if let autoincrementInitializable = T.self as? AutoincrementIDInitializable.Type {
146162
return autoincrementInitializable.init(autoincrementID: self.lastAutoincrementID) as! T
147163
} else {
148-
fatalError("Unsupported database generated identiifer type: \(T.self)")
164+
fatalError("Unsupported database generated identifier type: \(T.self)")
149165
}
150166
}
151167
}

Sources/FluentSQLiteDriver/FluentSQLiteDriver.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ struct _FluentSQLiteDriver: DatabaseDriver {
88
func makeDatabase(with context: DatabaseContext) -> Database {
99
_FluentSQLiteDatabase(
1010
database: _ConnectionPoolSQLiteDatabase(pool: self.pool.pool(for: context.eventLoop), logger: context.logger),
11-
context: context
11+
context: context,
12+
inTransaction: false
1213
)
1314
}
1415

Sources/FluentSQLiteDriver/SQLiteConverterDelegate.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@ struct SQLiteConverterDelegate: SQLConverterDelegate {
1414
default: return nil
1515
}
1616
}
17+
18+
func nestedFieldExpression(_ column: String, _ path: [String]) -> SQLExpression {
19+
let path = path.joined(separator: ".")
20+
return SQLRaw("JSON_EXTRACT(\(column), '$.\(path)')")
21+
}
1722
}
Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
1+
import Foundation
2+
13
extension SQLiteRow: DatabaseOutput {
24
public func schema(_ schema: String) -> DatabaseOutput {
35
SchemaOutput(row: self, schema: schema)
46
}
57

6-
public func contains(_ path: [FieldKey]) -> Bool {
8+
public func contains(_ path: FieldKey) -> Bool {
79
self.column(self.columnName(path)) != nil
810
}
911

10-
public func decode<T>(_ path: [FieldKey], as type: T.Type) throws -> T
12+
public func decodeNil(_ key: FieldKey) throws -> Bool {
13+
try self.decodeNil(column: self.columnName(key))
14+
}
15+
16+
public func decode<T>(_ key: FieldKey, as type: T.Type) throws -> T
1117
where T: Decodable
1218
{
13-
try self.decode(column: self.columnName(path), as: T.self)
19+
try self.decode(column: self.columnName(key), as: T.self)
1420
}
1521

16-
func columnName(_ path: [FieldKey]) -> String {
17-
path.map { $0.description }.joined(separator: "_")
22+
func columnName(_ key: FieldKey) -> String {
23+
switch key {
24+
case .id:
25+
return "id"
26+
case .aggregate:
27+
return key.description
28+
case .string(let name):
29+
return name
30+
case .prefix(let prefix, let key):
31+
return self.columnName(prefix) + self.columnName(key)
32+
}
1833
}
1934
}
2035

@@ -30,13 +45,21 @@ private struct SchemaOutput: DatabaseOutput {
3045
SchemaOutput(row: self.row, schema: schema)
3146
}
3247

33-
func contains(_ path: [FieldKey]) -> Bool {
34-
self.row.contains(column: self.schema + "_" + self.row.columnName(path))
48+
func contains(_ key: FieldKey) -> Bool {
49+
self.row.contains(self.key(key))
3550
}
3651

37-
func decode<T>(_ path: [FieldKey], as type: T.Type) throws -> T
52+
func decodeNil(_ key: FieldKey) throws -> Bool {
53+
try self.row.decodeNil(self.key(key))
54+
}
55+
56+
func decode<T>(_ key: FieldKey, as type: T.Type) throws -> T
3857
where T : Decodable
3958
{
40-
try self.row.decode(column: self.schema + "_" + self.row.columnName(path), as: T.self)
59+
try self.row.decode(self.key(key), as: T.self)
60+
}
61+
62+
func key(_ key: FieldKey) -> FieldKey {
63+
.prefix(.string(self.schema + "_"), key)
4164
}
4265
}

Tests/FluentSQLiteDriverTests/FluentSQLiteDriverTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ final class FluentSQLiteDriverTests: XCTestCase {
99
func testArray() throws { try self.benchmarker.testArray() }
1010
func testBatch() throws { try self.benchmarker.testBatch() }
1111
func testChildren() throws { try self.benchmarker.testChildren() }
12+
func testCodable() throws { try self.benchmarker.testCodable() }
1213
func testChunk() throws { try self.benchmarker.testChunk() }
1314
func testCRUD() throws { try self.benchmarker.testCRUD() }
1415
func testEagerLoad() throws { try self.benchmarker.testEagerLoad() }
@@ -25,6 +26,7 @@ final class FluentSQLiteDriverTests: XCTestCase {
2526
func testParent() throws { try self.benchmarker.testParent() }
2627
func testPerformance() throws { try self.benchmarker.testPerformance() }
2728
func testRange() throws { try self.benchmarker.testRange() }
29+
func testSchema() throws { try self.benchmarker.testSchema() }
2830
func testSet() throws { try self.benchmarker.testSet() }
2931
func testSiblings() throws { try self.benchmarker.testSiblings() }
3032
func testSoftDelete() throws { try self.benchmarker.testSoftDelete() }

0 commit comments

Comments
 (0)