diff --git a/CHANGELOG.md b/CHANGELOG.md index 2783a67d..fc759118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +0.14.1 (01-11-2022), [diff][diff-0.14.1] +======================================== + +* Reverted `Blob` changes (See [#1167][] for rationale). + 0.14.0 (27-10-2022), [diff][diff-0.14.0] ======================================== For breaking changes, see [Upgrading.md](Documentation/Upgrading.md). @@ -129,6 +134,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md). [diff-0.13.2]: https://github.com/stephencelis/SQLite.swift/compare/0.13.1...0.13.2 [diff-0.13.3]: https://github.com/stephencelis/SQLite.swift/compare/0.13.2...0.13.3 [diff-0.14.0]: https://github.com/stephencelis/SQLite.swift/compare/0.13.3...0.14.0 +[diff-0.14.1]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.14.1 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142 diff --git a/Documentation/Index.md b/Documentation/Index.md index ada9b7c3..730fe30b 100644 --- a/Documentation/Index.md +++ b/Documentation/Index.md @@ -90,7 +90,7 @@ process of downloading, compiling, and linking dependencies. ```swift dependencies: [ - .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0") + .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1") ] ``` @@ -111,7 +111,7 @@ install SQLite.swift with Carthage: 2. Update your Cartfile to include the following: ```ruby - github "stephencelis/SQLite.swift" ~> 0.14.0 + github "stephencelis/SQLite.swift" ~> 0.14.1 ``` 3. Run `carthage update` and [add the appropriate framework][Carthage Usage]. @@ -141,7 +141,7 @@ install SQLite.swift with Carthage: use_frameworks! target 'YourAppTargetName' do - pod 'SQLite.swift', '~> 0.14.0' + pod 'SQLite.swift', '~> 0.14.1' end ``` @@ -155,7 +155,7 @@ with the OS you can require the `standalone` subspec: ```ruby target 'YourAppTargetName' do - pod 'SQLite.swift/standalone', '~> 0.14.0' + pod 'SQLite.swift/standalone', '~> 0.14.1' end ``` @@ -165,7 +165,7 @@ dependency to sqlite3 or one of its subspecs: ```ruby target 'YourAppTargetName' do - pod 'SQLite.swift/standalone', '~> 0.14.0' + pod 'SQLite.swift/standalone', '~> 0.14.1' pod 'sqlite3/fts5', '= 3.15.0' # SQLite 3.15.0 with FTS5 enabled end ``` @@ -181,7 +181,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the target 'YourAppTargetName' do # Make sure you only require the subspec, otherwise you app might link against # the system SQLite, which means the SQLCipher-specific methods won't work. - pod 'SQLite.swift/SQLCipher', '~> 0.14.0' + pod 'SQLite.swift/SQLCipher', '~> 0.14.1' end ``` diff --git a/README.md b/README.md index ac0c2a7a..4cf72d03 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Swift code. ```swift dependencies: [ - .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0") + .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1") ] ``` @@ -155,7 +155,7 @@ install SQLite.swift with Carthage: 2. Update your Cartfile to include the following: ```ruby - github "stephencelis/SQLite.swift" ~> 0.14.0 + github "stephencelis/SQLite.swift" ~> 0.14.1 ``` 3. Run `carthage update` and diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec index c30aa765..f32282d3 100644 --- a/SQLite.swift.podspec +++ b/SQLite.swift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SQLite.swift" - s.version = "0.14.0" + s.version = "0.14.1" s.summary = "A type-safe, Swift-language layer over SQLite3." s.description = <<-DESC diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift index c8bd2c15..a709fb42 100644 --- a/Sources/SQLite/Core/Blob.swift +++ b/Sources/SQLite/Core/Blob.swift @@ -21,64 +21,36 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // -import Foundation -public final class Blob { +public struct Blob { - public let data: NSData + public let bytes: [UInt8] - public var bytes: UnsafePointer { - data.bytes.assumingMemoryBound(to: UInt8.self) + public init(bytes: [UInt8]) { + self.bytes = bytes } - public var length: Int { - data.count - } - - public convenience init(bytes: [UInt8]) { - guard bytes.count > 0 else { - self.init(data: NSData()) - return - } - self.init(data: NSData(bytes: bytes, length: bytes.count)) - } - - public convenience init(bytes: UnsafeRawPointer, length: Int) { - self.init(data: NSData(bytes: bytes, length: length)) - } - - public init(data: NSData) { - precondition(!(data is NSMutableData), "Blob cannot be initialized with mutable data") - self.data = data + public init(bytes: UnsafeRawPointer, length: Int) { + let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length) + self.init(bytes: [UInt8](i8bufptr)) } public func toHex() -> String { - guard length > 0 else { return "" } - - var hex = "" - for idx in 0.. Bool { - lhs.data == rhs.data + lhs.bytes == rhs.bytes } diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift index 2a7ec487..0e51e651 100644 --- a/Sources/SQLite/Core/Connection.swift +++ b/Sources/SQLite/Core/Connection.swift @@ -741,7 +741,7 @@ extension Context { func set(result: Binding?) { switch result { case let blob as Blob: - sqlite3_result_blob(self, blob.bytes, Int32(blob.length), nil) + sqlite3_result_blob(self, blob.bytes, Int32(blob.bytes.count), nil) case let double as Double: sqlite3_result_double(self, double) case let int as Int64: diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift index 80450258..6cb2e5d3 100644 --- a/Sources/SQLite/Core/Statement.swift +++ b/Sources/SQLite/Core/Statement.swift @@ -103,10 +103,10 @@ public final class Statement { switch value { case .none: sqlite3_bind_null(handle, Int32(idx)) - case let value as Blob where value.length == 0: + case let value as Blob where value.bytes.count == 0: sqlite3_bind_zeroblob(handle, Int32(idx), 0) case let value as Blob: - sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.length), SQLITE_TRANSIENT) + sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.bytes.count), SQLITE_TRANSIENT) case let value as Double: sqlite3_bind_double(handle, Int32(idx), value) case let value as Int64: diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift index 71889ae5..8af04df9 100644 --- a/Sources/SQLite/Extensions/Cipher.swift +++ b/Sources/SQLite/Extensions/Cipher.swift @@ -32,7 +32,7 @@ extension Connection { } public func key(_ key: Blob, db: String = "main") throws { - try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length) + try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count) } /// Same as `key(_ key: String, db: String = "main")`, running "PRAGMA cipher_migrate;" @@ -53,7 +53,7 @@ extension Connection { /// Same as `[`keyAndMigrate(_ key: String, db: String = "main")` accepting byte array as key public func keyAndMigrate(_ key: Blob, db: String = "main") throws { - try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length, migrate: true) + try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count, migrate: true) } /// Change the key on an open database. NB: only works if the database is already encrypted. @@ -68,7 +68,7 @@ extension Connection { } public func rekey(_ key: Blob, db: String = "main") throws { - try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.length) + try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count) } /// Converts a non-encrypted database to an encrypted one. diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift index e81c4964..44a31736 100644 --- a/Sources/SQLite/Foundation.swift +++ b/Sources/SQLite/Foundation.swift @@ -31,11 +31,13 @@ extension Data: Value { } public static func fromDatatypeValue(_ dataValue: Blob) -> Data { - dataValue.data as Data + Data(dataValue.bytes) } public var datatypeValue: Blob { - Blob(data: self as NSData) + withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in + Blob(bytes: pointer.baseAddress!, length: count) + } } } diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift index d5d2e9ff..3e329552 100644 --- a/Tests/SPM/Package.swift +++ b/Tests/SPM/Package.swift @@ -15,7 +15,7 @@ let package = Package( // for testing from same repository .package(path: "../..") // normally this would be: - // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0") + // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1") ], targets: [ .target( diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift index bef4bb83..f2e9435e 100644 --- a/Tests/SQLiteTests/Core/BlobTests.swift +++ b/Tests/SQLiteTests/Core/BlobTests.swift @@ -25,14 +25,14 @@ class BlobTests: XCTestCase { func test_init_array() { let blob = Blob(bytes: [42, 43, 44]) - XCTAssertEqual([UInt8](blob.data), [42, 43, 44]) + XCTAssertEqual(blob.bytes, [42, 43, 44]) } func test_init_unsafeRawPointer() { let pointer = UnsafeMutablePointer.allocate(capacity: 3) pointer.initialize(repeating: 42, count: 3) let blob = Blob(bytes: pointer, length: 3) - XCTAssertEqual([UInt8](blob.data), [42, 42, 42]) + XCTAssertEqual(blob.bytes, [42, 42, 42]) } func test_equality() { @@ -44,8 +44,4 @@ class BlobTests: XCTestCase { XCTAssertEqual(blob1, blob2) XCTAssertNotEqual(blob1, blob3) } - - func XXX_test_init_with_mutable_data_fails() { - _ = Blob(data: NSMutableData()) - } } diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift index 0d82e890..5f212505 100644 --- a/Tests/SQLiteTests/Core/StatementTests.swift +++ b/Tests/SQLiteTests/Core/StatementTests.swift @@ -22,7 +22,7 @@ class StatementTests: SQLiteTestCase { let statement = try db.prepare("SELECT email FROM users") XCTAssert(try statement.step()) let blob = statement.row[0] as Blob - XCTAssertEqual("alice@example.com", String(data: blob.data as Data, encoding: .utf8)!) + XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!) } func test_zero_sized_blob_returns_null() throws { @@ -31,7 +31,7 @@ class StatementTests: SQLiteTestCase { try db.run(blobs.create { $0.column(blobColumn) }) try db.run(blobs.insert(blobColumn <- Blob(bytes: []))) let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0)) - XCTAssertEqual([], [UInt8](blobValue.data)) + XCTAssertEqual([], blobValue.bytes) } func test_prepareRowIterator() throws { diff --git a/Tests/SQLiteTests/Extensions/CipherTests.swift b/Tests/SQLiteTests/Extensions/CipherTests.swift index bd7f2042..bc89cfa2 100644 --- a/Tests/SQLiteTests/Extensions/CipherTests.swift +++ b/Tests/SQLiteTests/Extensions/CipherTests.swift @@ -19,7 +19,7 @@ class CipherTests: XCTestCase { // db2 let key2 = keyData() - try db2.key(Blob(data: key2)) + try db2.key(Blob(bytes: key2.bytes, length: key2.length)) try db2.run("CREATE TABLE foo (bar TEXT)") try db2.run("INSERT INTO foo (bar) VALUES ('world')") @@ -47,7 +47,7 @@ class CipherTests: XCTestCase { func test_data_rekey() throws { let newKey = keyData() - try db2.rekey(Blob(data: newKey)) + try db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length)) XCTAssertEqual(1, try db2.scalar("SELECT count(*) FROM foo") as? Int64) } @@ -79,12 +79,11 @@ class CipherTests: XCTestCase { // sqlite> CREATE TABLE foo (bar TEXT); // sqlite> INSERT INTO foo (bar) VALUES ('world'); guard let cipherVersion: String = db1.cipherVersion, - cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.") - else { return } + cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.") else { return } let encryptedFile = cipherVersion.starts(with: "3.") ? - fixture("encrypted-3.x", withExtension: "sqlite") : - fixture("encrypted-4.x", withExtension: "sqlite") + fixture("encrypted-3.x", withExtension: "sqlite") : + fixture("encrypted-4.x", withExtension: "sqlite") try FileManager.default.setAttributes([FileAttributeKey.immutable: 1], ofItemAtPath: encryptedFile) XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile)) diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift index ffd3fae1..453febcd 100644 --- a/Tests/SQLiteTests/FoundationTests.swift +++ b/Tests/SQLiteTests/FoundationTests.swift @@ -5,7 +5,7 @@ class FoundationTests: XCTestCase { func testDataFromBlob() { let data = Data([1, 2, 3]) let blob = data.datatypeValue - XCTAssertEqual([1, 2, 3], [UInt8](blob.data)) + XCTAssertEqual([1, 2, 3], blob.bytes) } func testBlobToData() {