Skip to content

Commit 5680160

Browse files
authored
Merge pull request #1105 from stephencelis/userVersion
Native user_version support in Connection
2 parents 1c86a47 + 608684a commit 5680160

File tree

5 files changed

+51
-20
lines changed

5 files changed

+51
-20
lines changed

Documentation/Index.md

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,21 +1457,11 @@ try db.run(users.drop(ifExists: true))
14571457

14581458
### Migrations and Schema Versioning
14591459

1460-
You can add a convenience property on `Connection` to query and set the
1460+
You can use the convenience property on `Connection` to query and set the
14611461
[`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version).
14621462

14631463
This is a great way to manage your schema’s version over migrations.
1464-
1465-
```swift
1466-
extension Connection {
1467-
public var userVersion: Int32 {
1468-
get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
1469-
set { try! run("PRAGMA user_version = \(newValue)") }
1470-
}
1471-
}
1472-
```
1473-
1474-
Then you can conditionally run your migrations along the lines of:
1464+
You can conditionally run your migrations along the lines of:
14751465

14761466
```swift
14771467
if db.userVersion == 0 {

Sources/SQLite/Core/Connection.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,19 @@ public final class Connection {
152152
Int(sqlite3_total_changes(handle))
153153
}
154154

155+
/// The user version of the database.
156+
/// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
157+
public var userVersion: Int32? {
158+
get {
159+
(try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
160+
}
161+
set {
162+
if let userVersion = newValue {
163+
_ = try? run("PRAGMA user_version = \(userVersion)")
164+
}
165+
}
166+
}
167+
155168
// MARK: - Execute
156169

157170
/// Executes a batch of SQL statements.

Tests/SQLiteTests/ConnectionTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ class ConnectionTests: SQLiteTestCase {
9696
XCTAssertEqual(2, db.totalChanges)
9797
}
9898

99+
func test_userVersion() {
100+
db.userVersion = 2
101+
XCTAssertEqual(2, db.userVersion!)
102+
}
103+
99104
func test_prepare_preparesAndReturnsStatements() {
100105
_ = try! db.prepare("SELECT * FROM users WHERE admin = 0")
101106
_ = try! db.prepare("SELECT * FROM users WHERE admin = ?", 0)

Tests/SQLiteTests/QueryTests.swift

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,27 @@ class QueryTests: XCTestCase {
391391
let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
392392
date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
393393
let update = try emails.update(value)
394-
let encodedJSON = try JSONEncoder().encode(value1)
395-
let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
396-
assertSQL(
394+
395+
// NOTE: As Linux JSON decoding doesn't order keys the same way, we need to check prefix, suffix,
396+
// and extract JSON to decode it and check the decoded object.
397+
398+
let expectedPrefix =
397399
"""
398400
UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
399-
\"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'
400-
""".replacingOccurrences(of: "\n", with: ""),
401-
update
402-
)
401+
\"date\" = '1970-01-01T00:00:00.000', \"sub\" = '
402+
""".replacingOccurrences(of: "\n", with: "")
403+
let expectedSuffix = "'"
404+
405+
let sql = update.asSQL()
406+
XCTAssert(sql.hasPrefix(expectedPrefix))
407+
XCTAssert(sql.hasSuffix(expectedSuffix))
408+
409+
let extractedJSON = String(sql[
410+
sql.index(sql.startIndex, offsetBy: expectedPrefix.count) ..<
411+
sql.index(sql.endIndex, offsetBy: -expectedSuffix.count)
412+
])
413+
let decodedJSON = try JSONDecoder().decode(TestCodable.self, from: extractedJSON.data(using: .utf8)!)
414+
XCTAssertEqual(decodedJSON, value1)
403415
}
404416

405417
func test_delete_compilesDeleteExpression() {

Tests/SQLiteTests/TestHelpers.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ let qualifiedTable = Table("table", database: "main")
105105
let virtualTable = VirtualTable("virtual_table")
106106
let _view = View("view") // avoid Mac XCTestCase collision
107107

108-
class TestCodable: Codable {
108+
class TestCodable: Codable, Equatable {
109109
let int: Int
110110
let string: String
111111
let bool: Bool
@@ -125,4 +125,15 @@ class TestCodable: Codable {
125125
self.optional = optional
126126
self.sub = sub
127127
}
128+
129+
static func == (lhs: TestCodable, rhs: TestCodable) -> Bool {
130+
lhs.int == rhs.int &&
131+
lhs.string == rhs.string &&
132+
lhs.bool == rhs.bool &&
133+
lhs.float == rhs.float &&
134+
lhs.double == rhs.double &&
135+
lhs.date == rhs.date &&
136+
lhs.optional == rhs.optional &&
137+
lhs.sub == rhs.sub
138+
}
128139
}

0 commit comments

Comments
 (0)