From a1fbf0d0351fde7f3430434a1741a4b1cb98d42f Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 10:19:47 -0400 Subject: [PATCH 01/17] Adds SQLCipher.swift Swift Package Manager integration when SQLCipher package trait is enabled - Package.swift -- Updates swift-tools-version to 6.1 to support traits -- Adds https://github.com/sqlcipher/SQLCipher.swift dependency -- Adds SQLCipher trait -- Adds SQLCipher dependency to GRDB target when SQLCipher trait is enabled -- Adds SQLCipherConfig library target to expose SQLCipher_config.h functions to swift with pass through to C variadic functions -- Adds SQLCipherConfig library depdency to GRDB target when SQLCipher trait is enabled -- Adds SQLCIPHER_HAS_CODEC swiftSettings/cSettings to GRDB target when SQLCipher trait is enabled -- Adds SQLCIPHER swiftSettings to GRDB target when SQLCipher trait is enabled -- Adds GRDBCIPHER_USE_ENCRYPTION to GRDBTests target when SQLCipher trait is enabled - Adjusts imports to check `#if SQLCIPHER` before `#if SWIFT_PACKAGE` - Adds Database+SQLCipher extension with SQLCipher operations, enabled by `#if SQLITE_HAS_CODEC` - Adds test_SPM_SQLCipher Makefile task and adds it as a dependent task of smokeTest Resolves #1772 --- GRDB.xcodeproj/project.pbxproj | 6 + GRDB/Core/Database+SQLCipher.swift | 211 ++++++++++++++++++ Makefile | 9 +- Package.swift | 39 +++- Sources/SQLCipherConfig/SQLCipher_config.c | 1 + .../include/SQLCipher_config.h | 32 +++ .../SQLCipherConfig/include/module.modulemap | 4 + Tests/GRDBTests/EncryptionTests.swift | 55 ++++- 8 files changed, 350 insertions(+), 7 deletions(-) create mode 100644 GRDB/Core/Database+SQLCipher.swift create mode 100644 Sources/SQLCipherConfig/SQLCipher_config.c create mode 100644 Sources/SQLCipherConfig/include/SQLCipher_config.h create mode 100644 Sources/SQLCipherConfig/include/module.modulemap diff --git a/GRDB.xcodeproj/project.pbxproj b/GRDB.xcodeproj/project.pbxproj index c0d3f02a70..0195499764 100755 --- a/GRDB.xcodeproj/project.pbxproj +++ b/GRDB.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 1C5348402E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */; }; + 1C5348412E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */; }; 4E13D2F32769B87F0037588C /* DatabaseBackupProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */; }; 4ED4BB592731DD25008B127D /* BackupTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED4BB582731DD25008B127D /* BackupTestCase.swift */; }; 56012B552573EED000B4925B /* CommonTableExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56012B542573EED000B4925B /* CommonTableExpressionTests.swift */; }; @@ -439,6 +441,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Database+SQLCipher.swift"; sourceTree = ""; }; 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseBackupProgress.swift; sourceTree = ""; }; 4ED4BB582731DD25008B127D /* BackupTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupTestCase.swift; sourceTree = ""; }; 56012B542573EED000B4925B /* CommonTableExpressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableExpressionTests.swift; sourceTree = ""; }; @@ -1587,6 +1590,7 @@ 56A238701B9C75030082EB20 /* Configuration.swift */, 56DAA2DA1DE9C827006E10C8 /* Cursor.swift */, 56A238711B9C75030082EB20 /* Database.swift */, + 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */, 566B91221FA4CF810012D5B0 /* Database+Schema.swift */, 566B91081FA4C3960012D5B0 /* Database+Statements.swift */, 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */, @@ -1963,6 +1967,7 @@ 563DE4F3231A91E2005081B7 /* DatabaseConfigurationTests.swift in Sources */, 56BF2282241781C5003D86EB /* UtilsTests.swift in Sources */, 56CC9243201E034D00CB597E /* PrefixWhileCursorTests.swift in Sources */, + 1C5348412E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */, 560714E3227DD0810091BB10 /* AssociationPrefetchingSQLTests.swift in Sources */, 56D496841D813147008276D7 /* SelectStatementTests.swift in Sources */, 561F38D82AC88A550051EEE9 /* JSONColumnTests.swift in Sources */, @@ -2272,6 +2277,7 @@ 56256ED925D1B316008C2BDD /* ForeignKey.swift in Sources */, 56D51D001EA789FA0074638A /* FetchableRecord+TableRecord.swift in Sources */, 56D110D328AFC81400E64463 /* PersistableRecord.swift in Sources */, + 1C5348402E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */, 5653EB0920944C7C00F46237 /* Association.swift in Sources */, 56A238851B9C75030082EB20 /* DatabaseValue.swift in Sources */, 5671FC201DA3CAC9003BF4FF /* FTS3TokenizerDescriptor.swift in Sources */, diff --git a/GRDB/Core/Database+SQLCipher.swift b/GRDB/Core/Database+SQLCipher.swift new file mode 100644 index 0000000000..140423e718 --- /dev/null +++ b/GRDB/Core/Database+SQLCipher.swift @@ -0,0 +1,211 @@ +#if SQLITE_HAS_CODEC +import SQLCipher + +extension Database { + + /// Granularitly of SQLCipher log outputs + /// Each log level is more verbose than the last + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_log_level + public enum CipherLogLevel: String { + case none + case error + case warn + case info + case debug + case trace + } + + /// - Returns: the SQLCipher version + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_version + public var cipherVersion: String? { + (try? String.fetchOne(self, sql: "PRAGMA cipher_version")) + } + + /// - Returns: the SQLCipher fips status: 1 for fips mode, 0 for non-fips mode + /// The FIPS status will not be initialized until the database connection has been keyed + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_fips_status + public var cipherFipsStatus: String? { + (try? String.fetchOne(self, sql: "PRAGMA cipher_fips_status")) + } + + /// - Returns: The compiled crypto provider. + /// The database must be keyed before requesting the name of the crypto provider. + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider + public var cipherProvider: String? { + (try? String.fetchOne(self, sql: "PRAGMA cipher_provider")) + } + + /// - Returns: the version number provided from the compiled crypto provider. + /// This value, if known, is available only after the database has been keyed. + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider_version + public var cipherProviderVersion: String? { + (try? String.fetchOne(self, sql: "PRAGMA cipher_provider_version")) + } + + /// Sets the passphrase used to crypt and decrypt an SQLCipher database. + /// + /// Call this method from `Configuration.prepareDatabase`, + /// as in the example below: + /// + /// var config = Configuration() + /// config.prepareDatabase { db in + /// try db.usePassphrase("secret") + /// } + public func usePassphrase(_ passphrase: String) throws { + guard var data = passphrase.data(using: .utf8) else { + throw DatabaseError(message: "invalid passphrase") + } + defer { + data.resetBytes(in: 0.. We (Zetetic) have been discouraging the use of sqlite3_rekey in + // > favor of attaching a new database with the desired encryption + // > options and using sqlcipher_export() to migrate the contents and + // > schema of the original db into the new one: + // > https://discuss.zetetic.net/t/how-to-encrypt-a-plaintext-sqlite-database-to-use-sqlcipher-and-avoid-file-is-encrypted-or-is-not-a-database-errors/ + let code = passphrase.withUnsafeBytes { + sqlite3_rekey(sqliteConnection, $0.baseAddress, CInt($0.count)) + } + guard code == SQLITE_OK else { + throw DatabaseError(resultCode: code, message: lastErrorMessage) + } + } + + /// When using Commercial or Enterprise SQLCipher packages you must call + /// `PRAGMA cipher_license` with a valid license code prior to executing + /// cryptographic operations on an encrypted database. + /// Failure to provide a license code, or use of an expired trial code, + /// will result in an `SQLITE_AUTH (23)` error code reported from the SQLite API + /// License Codes will activate SQLCipher Commercial or Enterprise packages + /// from Zetetic: https://www.zetetic.net/sqlcipher/buy/ + /// 15-day free trials are available by request: https://www.zetetic.net/sqlcipher/trial/ + /// + /// Call this method from `Configuration.prepareDatabase`, + /// as in the example below: + /// + /// var config = Configuration() + /// config.prepareDatabase { db in + /// try db.applyLicense(license) + /// } + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_license + /// - Parameter license: base64 SQLCipher license code to activate SQLCipher commercial + public func applyLicense(_ license: String) throws { + try execute(sql: "PRAGMA cipher_license = '\(license)'") + } + + /// Instructs SQLCipher to log internal debugging and operational information + /// to the sepecified log target (device) using `os_log` + /// The supplied logLevel will determine the granularity of the logs output + /// Available logLevel options are: NONE, ERROR, WARN, INFO, DEBUG, TRACE + /// Note that each level is more verbose than the last, + /// and particularly with DEBUG and TRACE the logging system will generate + /// a significant log volume + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_log + /// - Parameter logLevel: CipherLogLevel The granularity to use for the logging system - defaults to `DEBUG` + public func enableCipherLogging(logLevel: CipherLogLevel = .debug) throws { + try execute(sql: "PRAGMA cipher_log = device") + try execute(sql: "PRAGMA cipher_log_level = \(logLevel.rawValue.uppercased())") + } + + /// Instructs SQLCipher to disable logging internal debugging and operational information + /// + /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_log + public func disableCipherLogging() throws { + try execute(sql: "PRAGMA cipher_log_level = \(CipherLogLevel.none.rawValue.uppercased())") + } + + internal func validateSQLCipher() throws { + // https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 + // + // > In order to avoid situations where SQLite might be used + // > improperly at runtime, we strongly recommend that + // > applications institute a runtime test to ensure that the + // > application is actually using SQLCipher on the active + // > connection. + if cipherVersion == nil { + throw DatabaseError(resultCode: .SQLITE_MISUSE, message: """ + GRDB is not linked against SQLCipher. \ + Check https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 + """) + } + } + + internal func dropAllDatabaseObjects() throws { + // SQLCipher does not support the backup API: + // https://discuss.zetetic.net/t/using-the-sqlite-online-backup-api/2631 + // So we'll drop all database objects one after the other. + + // Prevent foreign keys from messing with drop table statements + let foreignKeysEnabled = try Bool.fetchOne(self, sql: "PRAGMA foreign_keys")! + if foreignKeysEnabled { + try execute(sql: "PRAGMA foreign_keys = OFF") + } + + try throwingFirstError( + execute: { + // Remove all database objects, one after the other + try inTransaction { + let sql = "SELECT type, name FROM sqlite_master WHERE name NOT LIKE 'sqlite_%'" + while let row = try Row.fetchOne(self, sql: sql) { + let type: String = row["type"] + let name: String = row["name"] + try execute(sql: "DROP \(type) \(name.quotedDatabaseIdentifier)") + } + return .commit + } + }, + finally: { + // Restore foreign keys if needed + if foreignKeysEnabled { + try execute(sql: "PRAGMA foreign_keys = ON") + } + }) + } +} + +#endif diff --git a/Makefile b/Makefile index 9c91521f3b..73f0b912d6 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # make distclean - Restore repository to a pristine state default: test -smokeTest: test_framework_GRDBiOS_maxTarget test_framework_GRDBiOS_minTarget test_framework_SQLCipher3 test_framework_SQLCipher4Encrypted test_framework_GRDBCustomSQLiteiOS_maxTarget test_SPM +smokeTest: test_framework_GRDBiOS_maxTarget test_framework_GRDBiOS_minTarget test_framework_SQLCipher3 test_framework_SQLCipher4Encrypted test_framework_GRDBCustomSQLiteiOS_maxTarget test_SPM test_SPM_SQLCipher # ===== # Tools @@ -223,6 +223,13 @@ test_SPM: $(SWIFT) build -c release set -o pipefail && $(SWIFT) test --parallel +test_SPM_SQLCipher: + rm -rf Tests/products + $(SWIFT) package clean + $(SWIFT) build + $(SWIFT) build -c release + set -o pipefail && $(SWIFT) test --parallel --traits SQLCipher + test_universal_xcframework: rm -rf Tests/products mkdir Tests/products diff --git a/Package.swift b/Package.swift index 9d0c79554f..f51b2866a1 100644 --- a/Package.swift +++ b/Package.swift @@ -12,6 +12,11 @@ let darwinPlatforms: [Platform] = [ .visionOS, .watchOS, ] + +let sqlcipherTraitTargetCondition: TargetDependencyCondition? = .when(platforms: darwinPlatforms, traits: ["SQLCipher"]) + +let sqlcipherTraitBuildSettingCondition: BuildSettingCondition? = .when(platforms: darwinPlatforms, traits: ["SQLCipher"]) + var swiftSettings: [SwiftSetting] = [ .define("SQLITE_ENABLE_FTS5"), // Until Xcode has proper support for package traits, we must enable @@ -21,9 +26,17 @@ var swiftSettings: [SwiftSetting] = [ // TODO: when Xcode support traits, remove all mentions of SQLITE_DISABLE_SNAPSHOT and update as below: // .define("SQLITE_ENABLE_SNAPSHOT", .when(platforms: darwinPlatforms, traits: ["GRDBSQLite"])), .define("SQLITE_ENABLE_SNAPSHOT"), + .define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition), + .define("SQLCIPHER", sqlcipherTraitBuildSettingCondition) +] + +var cSettings: [CSetting] = [ + .define("SQLITE_HAS_CODEC", to: nil, sqlcipherTraitBuildSettingCondition) +] + +var dependencies: [PackageDescription.Package.Dependency] = [ + .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", exact: "4.11.0") ] -var cSettings: [CSetting] = [] -var dependencies: [PackageDescription.Package.Dependency] = [] // Don't rely on those environment variables. They are ONLY testing conveniences: // $ SQLITE_ENABLE_PREUPDATE_HOOK=1 make test_SPM @@ -55,9 +68,11 @@ let package = Package( .library(name: "GRDBSQLite", targets: ["GRDBSQLite"]), .library(name: "GRDB", targets: ["GRDB"]), .library(name: "GRDB-dynamic", type: .dynamic, targets: ["GRDB"]), + .library(name: "SQLCipherConfig", targets: ["SQLCipherConfig"]) ], traits: [ "GRDBSQLite", + .trait(name: "SQLCipher", description: "Enables SQLCipher encryption when a passphrase is supplied to Database"), .default(enabledTraits: ["GRDBSQLite"]), ], dependencies: dependencies, @@ -65,15 +80,25 @@ let package = Package( .systemLibrary( name: "GRDBSQLite", providers: [.apt(["libsqlite3-dev"])]), + .target( + name: "SQLCipherConfig", + dependencies: [.product(name: "SQLCipher", package: "SQLCipher.swift")] + ), .target( name: "GRDB", dependencies: [ .target(name: "GRDBSQLite", condition: .when(traits: ["GRDBSQLite"])), + .product(name: "SQLCipher", package: "SQLCipher.swift", condition: sqlcipherTraitTargetCondition), + .target( + name: "SQLCipherConfig", + condition: sqlcipherTraitTargetCondition + ) ], path: "GRDB", resources: [.copy("PrivacyInfo.xcprivacy")], cSettings: cSettings, - swiftSettings: swiftSettings), + swiftSettings: swiftSettings +), .testTarget( name: "GRDBTests", dependencies: ["GRDB"], @@ -95,6 +120,7 @@ let package = Package( .copy("GRDBTests/Betty.jpeg"), .copy("GRDBTests/InflectionsTests.json"), .copy("GRDBTests/Issue1383.sqlite"), + .copy("CocoaPods/SQLCipher4/db.SQLCipher3") ], cSettings: cSettings, swiftSettings: swiftSettings + [ @@ -102,7 +128,12 @@ let package = Package( .swiftLanguageMode(.v5), .enableUpcomingFeature("InferSendableFromCaptures"), .enableUpcomingFeature("GlobalActorIsolatedTypesUsability"), - ]) + .define( + "GRDBCIPHER_USE_ENCRYPTION", + sqlcipherTraitBuildSettingCondition + ) + ] +) ], swiftLanguageModes: [.v6] ) diff --git a/Sources/SQLCipherConfig/SQLCipher_config.c b/Sources/SQLCipherConfig/SQLCipher_config.c new file mode 100644 index 0000000000..26b22bdb9b --- /dev/null +++ b/Sources/SQLCipherConfig/SQLCipher_config.c @@ -0,0 +1 @@ +// empty c-file diff --git a/Sources/SQLCipherConfig/include/SQLCipher_config.h b/Sources/SQLCipherConfig/include/SQLCipher_config.h new file mode 100644 index 0000000000..a405306f63 --- /dev/null +++ b/Sources/SQLCipherConfig/include/SQLCipher_config.h @@ -0,0 +1,32 @@ +#ifndef grdb_config_h +#define grdb_config_h + +#include + +typedef void(*_errorLogCallback)(void *pArg, int iErrCode, const char *zMsg); + +/// Wrapper around sqlite3_config(SQLITE_CONFIG_LOG, ...) which is a variadic +/// function that can't be used from Swift. +static inline void _registerErrorLogCallback(_errorLogCallback callback) { + sqlite3_config(SQLITE_CONFIG_LOG, callback, 0); +} + +#if SQLITE_VERSION_NUMBER >= 3029000 +/// Wrapper around sqlite3_db_config() which is a variadic function that can't +/// be used from Swift. +static inline void _disableDoubleQuotedStringLiterals(sqlite3 *db) { + sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, (void *)0); + sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, (void *)0); +} + +/// Wrapper around sqlite3_db_config() which is a variadic function that can't +/// be used from Swift. +static inline void _enableDoubleQuotedStringLiterals(sqlite3 *db) { + sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 1, (void *)0); + sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 1, (void *)0); +} +#else +static inline void _disableDoubleQuotedStringLiterals(sqlite3 *db) { } +static inline void _enableDoubleQuotedStringLiterals(sqlite3 *db) { } +#endif +#endif /* grdb_config_h */ diff --git a/Sources/SQLCipherConfig/include/module.modulemap b/Sources/SQLCipherConfig/include/module.modulemap new file mode 100644 index 0000000000..84e0f46ba5 --- /dev/null +++ b/Sources/SQLCipherConfig/include/module.modulemap @@ -0,0 +1,4 @@ +module SQLCipherConfig { + header "SQLCipher_config.h" + export * +} diff --git a/Tests/GRDBTests/EncryptionTests.swift b/Tests/GRDBTests/EncryptionTests.swift index a3a1c74536..ac11de8122 100644 --- a/Tests/GRDBTests/EncryptionTests.swift +++ b/Tests/GRDBTests/EncryptionTests.swift @@ -1,9 +1,15 @@ -#if SQLITE_HAS_CODEC +#if GRDBCIPHER import XCTest import GRDB class EncryptionTests: GRDBTestCase { +#if SWIFT_PACKAGE +let testBundle = Bundle.module +#else +let testBundle = Bundle(for: GRDBTestCase.self) +#endif + func testDatabaseQueueWithPassphraseToDatabaseQueueWithPassphrase() throws { do { var config = Configuration() @@ -707,7 +713,6 @@ class EncryptionTests: GRDBTestCase { else { XCTFail("Unknown SQLCipher version"); return } if cipherMajorVersion >= 4 { - let testBundle = Bundle(for: type(of: self)) let path = testBundle.url(forResource: "db", withExtension: "SQLCipher3")!.path var configuration = Configuration() configuration.prepareDatabase { db in @@ -728,5 +733,51 @@ class EncryptionTests: GRDBTestCase { } } } + + func testCipherVersion() throws { + try DatabaseQueue().inDatabase { db in + XCTAssertNotNil(db.cipherVersion, "SQLCipher not properly loaded") + } + } + + func testCipherFipsStatus() throws { + var config = Configuration() + config.prepareDatabase { db in + try db.usePassphrase("secret") + } + let dbQueue = try makeDatabaseQueue(configuration: config) + dbQueue.inDatabase { db in + XCTAssertEqual("0", db.cipherFipsStatus) + } + } + + func testCipherProvider() throws { + var config = Configuration() + config.prepareDatabase { db in + try db.usePassphrase("secret") + } + let dbQueue = try makeDatabaseQueue(configuration: config) + dbQueue.inDatabase { db in + XCTAssertEqual("commoncrypto", db.cipherProvider) + } + } + + func testCipherProviderVersion() throws { + var config = Configuration() + config.prepareDatabase { db in + try db.usePassphrase("secret") + } + let dbQueue = try makeDatabaseQueue(configuration: config) + guard let cipherVersion = try dbQueue.read({ $0.cipherVersion }) else { + XCTFail("No Cipher Version found") + return + } + if "4.10.0".compare(cipherVersion, options: .numeric) == .orderedDescending { + throw XCTSkip("cipher_provider_version isn't available until SQLCipher 4.10.0") + } + dbQueue.inDatabase { db in + XCTAssertNotNil(db.cipherProviderVersion) + } + } } #endif From a404421d2fb192d58979a550810b75c44cc17850 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Fri, 3 Oct 2025 13:50:16 -0400 Subject: [PATCH 02/17] Updates README.md documentation for SQLCipher Swift Package Manager integration --- README.md | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4261c65e8f..9db3ce7d41 100644 --- a/README.md +++ b/README.md @@ -4597,7 +4597,66 @@ try Player.customRequest().fetchAll(db) // [Player] Encryption ========== -**GRDB can encrypt your database with [SQLCipher](http://sqlcipher.net) v3.4+.** +**GRDB can encrypt your database with [SQLCipher](https://www.sqlcipher.net) v3.4+.** + +### Swift Package Manager Integration (SQLCipher v4.11+) + +Use the `GRDB.swift` Swift Package and specify the `SQLCipher` trait: + +```swift +depdencies: [ + .package(url: "https://github.com/groue/GRDB.swift.git", from: "7.9.0", traits: ["SQLCipher"]) +] +``` + +As of Xcode 16.4 (16F6), there's no direct way in the Xcode UI to select trait variations so you'll need to use a local wrapper package to pull in the GRDB dependency with the `SQLCipher` trait enabled: + +```swift +// swift-tools-version: 6.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "AppDependencies", + platforms: [ + .macOS(.v10_14), + .iOS(.v13), + .macCatalyst(.v13), + .watchOS(.v8), + .tvOS(.v15), + .visionOS(.v1) + ], + products: [ + .library( + name: "AppDependencies", + targets: ["AppDependencies"]), + ], + dependencies: [ + .package( + url: "https://github.com/groue/GRDB.swift.git", + from: "7.9.0", + traits: ["SQLCipher"]) + ], + targets: [ + .target( + name: "AppDependencies", + dependencies: [ + .product( + name: "GRDB", + package: "GRDB.swift") + ] + ) + ] +) +``` + +Within Xcode add your local `AppDependencies` wrapper package as a package dependency and GRDB with SQLCipher functionality will be accessible. + +### CocoaPods (SQLCipher v3.4-v4.10) + +> [!WARNING] +> CocoaPods has transitioned to [read-only maintainence mode](https://blog.cocoapods.org/CocoaPods-Specs-Repo/) and is scheduled to be deprecated from GRDB Use [CocoaPods](http://cocoapods.org/), and specify in your `Podfile`: @@ -4616,6 +4675,8 @@ Make sure you remove any existing `pod 'GRDB.swift'` from your Podfile. `GRDB.sw - [Creating or Opening an Encrypted Database](#creating-or-opening-an-encrypted-database) - [Changing the Passphrase of an Encrypted Database](#changing-the-passphrase-of-an-encrypted-database) - [Exporting a Database to an Encrypted Database](#exporting-a-database-to-an-encrypted-database) +- [SQLCipher Logging](#enabling-sqlcipher-logging) +- [SQLCipher Information Accessors](#sqlcipher-information-accessors) - [Security Considerations](#security-considerations) @@ -4736,6 +4797,120 @@ try existingDBQueue.inDatabase { db in // Now the export is completed, and the existing database can be deleted. ``` +### SQLCipher Logging + +To instruct SQLCipher to log internal debugging and operational information, use the convenience method `enableCipherLogging(logLevel:)`. + +Logs will be output to the target device using `os_log`. + +The supplied logLevel will determine the granularity of the logs output. Available logLevels are: + +``` +none +error +warn +info +debug +trace +``` + +Each level will be more verbose than the last, and particularly with debug and trace the logging system will generate significant log volume. + +If `enableCipherLogging(logLevel:)` is called without supplying a logLevel, the default logLevel of `debug` will be used. + +This convenience method only logs to the target device, but it's also possible to log to a file using `PRAGMA cipher_log = ;` directly. Please see the [SQLCipher API docs](https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_log) for additional information. + +Enable cipher logging when first setting up the db configuration or after it is setup: + +``` +var config = Configuration() +config.prepareDatabase { db in + try db.enableCipherLogging() + try db.usePassphrase("secret") +} + +let dbQueue = try DatabaseQueue(path: NSTemporaryDirectory().appending("test.db"), configuration: config) +``` + +Example output: + +``` +DEBUG CORE sqlite3_key: db=104E22830 +DEBUG CORE sqlite3_key_v2: db=104E22830 zDb=main db_index=0 +DEBUG CORE sqlcipherCodecAttach: db=104E22830, nDb=0 +DEBUG MEMORY sqlcipher_codec_ctx_init: allocating context +DEBUG MEMORY sqlcipher_codec_ctx_init: allocating kdf_salt +DEBUG MEMORY sqlcipher_codec_ctx_init: allocating hmac_kdf_salt +DEBUG CORE sqlcipher_codec_ctx_reserve_setup: base_reserve=16 block_sz=16 md_size=64 reserve=80 +DEBUG CORE sqlcipher_codec_ctx_reserve_setup: base_reserve=16 block_sz=16 md_size=64 reserve=80 +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating context +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating key +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating hmac_key +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating context +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating key +DEBUG MEMORY sqlcipher_cipher_ctx_init: allocating hmac_key +DEBUG CORE sqlcipher_cipher_ctx_copy: target=128009220, source=128009190 +DEBUG CORE sqlcipherCodecAttach: calling sqlcipherPagerSetCodec() +DEBUG CORE codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=4096 reserve=80 +DEBUG CORE codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize returned 0 +DEBUG CORE sqlcipherCodecAttach: calling sqlite3BtreeSecureDelete() +DEBUG CORE sqlcipherCodecAttach: calling sqlite3BtreeSetAutoVacuum() +DEBUG MEMORY codec_ctx_free: iCtx=7FF7BC080088 +DEBUG MEMORY cipher_ctx_free: iCtx=128008110 +DEBUG MEMORY cipher_ctx_free: iCtx=128008118 +``` + +You can disable cipher logging with `disableCipherLogging()`, following up on the previous example: + +``` +try dbQueue.inDatabase { db in + try db.disableCipherLogging() +} +``` + +### SQLCipher Information Accessors + +GRDB provides convenience accessors to get information about the SQLCipher version, the provider, the provider version, and the fips status. + +`cipherVersion`: Returns the SQLCipher version +- https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_version + +``` +let cipherVersion = try dbQueue.read { db in + return db.cipherVersion +} +``` + +`cipherProvider`: Returns the compiled crypto provider. The database must be keeyed before requesting the name of the crypto provider. +- https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider + +``` +let cipherProvider = try dbQueue.read { db in + return db.cipherProvider +} +``` + +`cipherProviderVersion`: Returns the version number provided from the compiled crypto provider. This value, if known, is available only after the database has been keyed. +- https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider_version + +``` +let cipherProviderVersion = try dbQueue.read { db in + return db.cipherProviderVersion +} +``` + +`cipherFipsStatus`: Returns the SQLCipher fips status: 1 for fips mode, 0 for non-fips mode. The FIPS status will not be initialized until the database connection has been keyed. +- https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_fips_status + +``` +let cipherFipsStatus = try dbQueue.read { db in + return db.cipherFipsStatus +} +``` + + + + ### Security Considerations From 843b6f24870147dd2c29c46f321f4eb96ec986fd Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 10:25:29 -0400 Subject: [PATCH 03/17] Adjusts Import Statements to import SQLCipher when SQLCipher trait is enabled (SQLCIPHER swiftSetting is set). --- GRDB/Core/Configuration.swift | 4 ++-- GRDB/Core/Database+Schema.swift | 4 ++-- GRDB/Core/Database+Statements.swift | 4 ++-- GRDB/Core/Database.swift | 4 ++-- GRDB/Core/DatabaseCollation.swift | 4 ++-- GRDB/Core/DatabaseError.swift | 4 ++-- GRDB/Core/DatabaseFunction.swift | 4 ++-- GRDB/Core/DatabaseSnapshotPool.swift | 4 ++-- GRDB/Core/DatabaseValue.swift | 4 ++-- GRDB/Core/Row.swift | 4 ++-- GRDB/Core/RowDecodingError.swift | 4 ++-- GRDB/Core/Statement.swift | 4 ++-- GRDB/Core/StatementAuthorizer.swift | 4 ++-- GRDB/Core/StatementColumnConvertible.swift | 4 ++-- GRDB/Core/Support/Foundation/Data.swift | 4 ++-- GRDB/Core/Support/Foundation/DatabaseDateComponents.swift | 4 ++-- GRDB/Core/Support/Foundation/Date.swift | 4 ++-- GRDB/Core/Support/Foundation/Decimal.swift | 4 ++-- GRDB/Core/Support/Foundation/UUID.swift | 4 ++-- GRDB/Core/Support/StandardLibrary/Optional.swift | 4 ++-- GRDB/Core/Support/StandardLibrary/StandardLibrary.swift | 4 ++-- GRDB/Core/TransactionObserver.swift | 4 ++-- GRDB/Core/WALSnapshot.swift | 4 ++-- GRDB/Dump/DumpFormats/DebugDumpFormat.swift | 4 ++-- GRDB/Dump/DumpFormats/JSONDumpFormat.swift | 4 ++-- GRDB/Dump/DumpFormats/LineDumpFormat.swift | 4 ++-- GRDB/Dump/DumpFormats/ListDumpFormat.swift | 4 ++-- GRDB/Dump/DumpFormats/QuoteDumpFormat.swift | 4 ++-- GRDB/FTS/FTS5.swift | 4 ++-- GRDB/FTS/FTS5CustomTokenizer.swift | 4 ++-- GRDB/FTS/FTS5Tokenizer.swift | 4 ++-- GRDB/FTS/FTS5WrapperTokenizer.swift | 4 ++-- GRDB/Record/FetchableRecord+Decodable.swift | 4 ++-- Tests/GRDBTests/AssociationPrefetchingRowTests.swift | 4 ++-- Tests/GRDBTests/DataMemoryTests.swift | 4 ++-- Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift | 4 ++-- Tests/GRDBTests/DatabasePoolTests.swift | 4 ++-- Tests/GRDBTests/GRDBTestCase.swift | 4 ++-- Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift | 4 ++-- Tests/GRDBTests/UpdateStatementTests.swift | 4 ++-- 40 files changed, 80 insertions(+), 80 deletions(-) diff --git a/GRDB/Core/Configuration.swift b/GRDB/Core/Configuration.swift index 933fb9c2b8..252d051efe 100644 --- a/GRDB/Core/Configuration.swift +++ b/GRDB/Core/Configuration.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Database+Schema.swift b/GRDB/Core/Database+Schema.swift index 593a1fcd8e..a4279a90e0 100644 --- a/GRDB/Core/Database+Schema.swift +++ b/GRDB/Core/Database+Schema.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Database+Statements.swift b/GRDB/Core/Database+Statements.swift index 34a362b9dc..8b4584bdae 100644 --- a/GRDB/Core/Database+Statements.swift +++ b/GRDB/Core/Database+Statements.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Database.swift b/GRDB/Core/Database.swift index 2614602ddd..9cecf155c4 100644 --- a/GRDB/Core/Database.swift +++ b/GRDB/Core/Database.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/DatabaseCollation.swift b/GRDB/Core/DatabaseCollation.swift index af59112bab..5b026e4f6f 100644 --- a/GRDB/Core/DatabaseCollation.swift +++ b/GRDB/Core/DatabaseCollation.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/DatabaseError.swift b/GRDB/Core/DatabaseError.swift index 78151bfca8..8370f8e2f4 100644 --- a/GRDB/Core/DatabaseError.swift +++ b/GRDB/Core/DatabaseError.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/DatabaseFunction.swift b/GRDB/Core/DatabaseFunction.swift index 35bc52bd0d..00291b1e06 100644 --- a/GRDB/Core/DatabaseFunction.swift +++ b/GRDB/Core/DatabaseFunction.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/DatabaseSnapshotPool.swift b/GRDB/Core/DatabaseSnapshotPool.swift index 4604c9c2cb..d9622a2cbf 100644 --- a/GRDB/Core/DatabaseSnapshotPool.swift +++ b/GRDB/Core/DatabaseSnapshotPool.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/DatabaseValue.swift b/GRDB/Core/DatabaseValue.swift index 2459e3ba75..6d7b03f281 100644 --- a/GRDB/Core/DatabaseValue.swift +++ b/GRDB/Core/DatabaseValue.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Row.swift b/GRDB/Core/Row.swift index c4b639ae79..74127949fe 100644 --- a/GRDB/Core/Row.swift +++ b/GRDB/Core/Row.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/RowDecodingError.swift b/GRDB/Core/RowDecodingError.swift index 025bb8035e..4af6e16676 100644 --- a/GRDB/Core/RowDecodingError.swift +++ b/GRDB/Core/RowDecodingError.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Statement.swift b/GRDB/Core/Statement.swift index 6bf3a89ad4..6c2eb761dd 100644 --- a/GRDB/Core/Statement.swift +++ b/GRDB/Core/Statement.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/StatementAuthorizer.swift b/GRDB/Core/StatementAuthorizer.swift index a8871726fe..6ea798c5f1 100644 --- a/GRDB/Core/StatementAuthorizer.swift +++ b/GRDB/Core/StatementAuthorizer.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/StatementColumnConvertible.swift b/GRDB/Core/StatementColumnConvertible.swift index 490dffb7f7..1dc9d26225 100644 --- a/GRDB/Core/StatementColumnConvertible.swift +++ b/GRDB/Core/StatementColumnConvertible.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/Foundation/Data.swift b/GRDB/Core/Support/Foundation/Data.swift index fd7d714a01..fe1fabf1cf 100644 --- a/GRDB/Core/Support/Foundation/Data.swift +++ b/GRDB/Core/Support/Foundation/Data.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift b/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift index d857ecbc24..66a5abb101 100644 --- a/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift +++ b/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/Foundation/Date.swift b/GRDB/Core/Support/Foundation/Date.swift index dadc00fd65..15ba06ac17 100644 --- a/GRDB/Core/Support/Foundation/Date.swift +++ b/GRDB/Core/Support/Foundation/Date.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/Foundation/Decimal.swift b/GRDB/Core/Support/Foundation/Decimal.swift index 70d84f3ab7..1c2e7ae891 100644 --- a/GRDB/Core/Support/Foundation/Decimal.swift +++ b/GRDB/Core/Support/Foundation/Decimal.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/Foundation/UUID.swift b/GRDB/Core/Support/Foundation/UUID.swift index 54b18b2c80..5c77f5f583 100644 --- a/GRDB/Core/Support/Foundation/UUID.swift +++ b/GRDB/Core/Support/Foundation/UUID.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/StandardLibrary/Optional.swift b/GRDB/Core/Support/StandardLibrary/Optional.swift index 253b06e53d..e6647d4a76 100644 --- a/GRDB/Core/Support/StandardLibrary/Optional.swift +++ b/GRDB/Core/Support/StandardLibrary/Optional.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift b/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift index f967fb8375..23d0a112de 100644 --- a/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift +++ b/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/TransactionObserver.swift b/GRDB/Core/TransactionObserver.swift index 67212aad65..578af415cb 100644 --- a/GRDB/Core/TransactionObserver.swift +++ b/GRDB/Core/TransactionObserver.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Core/WALSnapshot.swift b/GRDB/Core/WALSnapshot.swift index 729a8ac805..3c46c2c0f8 100644 --- a/GRDB/Core/WALSnapshot.swift +++ b/GRDB/Core/WALSnapshot.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Dump/DumpFormats/DebugDumpFormat.swift b/GRDB/Dump/DumpFormats/DebugDumpFormat.swift index f957b1936c..f3606e529e 100644 --- a/GRDB/Dump/DumpFormats/DebugDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/DebugDumpFormat.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Dump/DumpFormats/JSONDumpFormat.swift b/GRDB/Dump/DumpFormats/JSONDumpFormat.swift index 42dd67dba3..8eb19c2636 100644 --- a/GRDB/Dump/DumpFormats/JSONDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/JSONDumpFormat.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Dump/DumpFormats/LineDumpFormat.swift b/GRDB/Dump/DumpFormats/LineDumpFormat.swift index 5111090e5d..e8daca020b 100644 --- a/GRDB/Dump/DumpFormats/LineDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/LineDumpFormat.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Dump/DumpFormats/ListDumpFormat.swift b/GRDB/Dump/DumpFormats/ListDumpFormat.swift index f5536641a1..a7c7d05d74 100644 --- a/GRDB/Dump/DumpFormats/ListDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/ListDumpFormat.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift b/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift index c605ae1715..b0ecc8cde4 100644 --- a/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/FTS/FTS5.swift b/GRDB/FTS/FTS5.swift index 127a43fef2..9400d23e96 100644 --- a/GRDB/FTS/FTS5.swift +++ b/GRDB/FTS/FTS5.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/FTS/FTS5CustomTokenizer.swift b/GRDB/FTS/FTS5CustomTokenizer.swift index a209337a6c..fb0dcbe6b1 100644 --- a/GRDB/FTS/FTS5CustomTokenizer.swift +++ b/GRDB/FTS/FTS5CustomTokenizer.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/FTS/FTS5Tokenizer.swift b/GRDB/FTS/FTS5Tokenizer.swift index 35f3ae2672..cdd3fffe88 100644 --- a/GRDB/FTS/FTS5Tokenizer.swift +++ b/GRDB/FTS/FTS5Tokenizer.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/FTS/FTS5WrapperTokenizer.swift b/GRDB/FTS/FTS5WrapperTokenizer.swift index bda4ed1813..9b91bd14d5 100644 --- a/GRDB/FTS/FTS5WrapperTokenizer.swift +++ b/GRDB/FTS/FTS5WrapperTokenizer.swift @@ -5,8 +5,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/GRDB/Record/FetchableRecord+Decodable.swift b/GRDB/Record/FetchableRecord+Decodable.swift index c54ab06bcc..c713ee8e6b 100644 --- a/GRDB/Record/FetchableRecord+Decodable.swift +++ b/GRDB/Record/FetchableRecord+Decodable.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/AssociationPrefetchingRowTests.swift b/Tests/GRDBTests/AssociationPrefetchingRowTests.swift index c6fd39bd8a..af160aafc1 100644 --- a/Tests/GRDBTests/AssociationPrefetchingRowTests.swift +++ b/Tests/GRDBTests/AssociationPrefetchingRowTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/DataMemoryTests.swift b/Tests/GRDBTests/DataMemoryTests.swift index 1187ed2504..937cd419c1 100644 --- a/Tests/GRDBTests/DataMemoryTests.swift +++ b/Tests/GRDBTests/DataMemoryTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift b/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift index 7302e2aa42..66ca9587cb 100644 --- a/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift +++ b/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/DatabasePoolTests.swift b/Tests/GRDBTests/DatabasePoolTests.swift index f8192e58f8..9876966853 100644 --- a/Tests/GRDBTests/DatabasePoolTests.swift +++ b/Tests/GRDBTests/DatabasePoolTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/GRDBTestCase.swift b/Tests/GRDBTests/GRDBTestCase.swift index af1df612be..d075a5748d 100644 --- a/Tests/GRDBTests/GRDBTestCase.swift +++ b/Tests/GRDBTests/GRDBTestCase.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift b/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift index 02b77ec50c..ba9b5e558d 100644 --- a/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift +++ b/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Tests/GRDBTests/UpdateStatementTests.swift b/Tests/GRDBTests/UpdateStatementTests.swift index f11e351176..dfe9f33412 100644 --- a/Tests/GRDBTests/UpdateStatementTests.swift +++ b/Tests/GRDBTests/UpdateStatementTests.swift @@ -4,8 +4,8 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -// #elseif SomeTrait -// import ... +#elseif SQLCIPHER +import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif From b11f4e22143d791bc82d1a647c62b83e99c458c9 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 10:46:01 -0400 Subject: [PATCH 04/17] - Adds SQLCipherConfig import to Database when SQLCipher trait is enabled - Removes SQLCipher related methods from Database as they are now moved to Database+SQLCipher - Adds SQLITE_DISABLE_SNAPSHOT swiftSetting to Package.swift when SQLCipher trait is enabled --- GRDB/Core/Database.swift | 93 +--------------------------------------- Package.swift | 1 + 2 files changed, 2 insertions(+), 92 deletions(-) diff --git a/GRDB/Core/Database.swift b/GRDB/Core/Database.swift index 9cecf155c4..02521a2be3 100644 --- a/GRDB/Core/Database.swift +++ b/GRDB/Core/Database.swift @@ -6,6 +6,7 @@ import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework #elseif SQLCIPHER import SQLCipher +import SQLCipherConfig #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif @@ -641,24 +642,6 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib } } - #if SQLITE_HAS_CODEC - private func validateSQLCipher() throws { - // https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 - // - // > In order to avoid situations where SQLite might be used - // > improperly at runtime, we strongly recommend that - // > applications institute a runtime test to ensure that the - // > application is actually using SQLCipher on the active - // > connection. - if try String.fetchOne(self, sql: "PRAGMA cipher_version") == nil { - throw DatabaseError(resultCode: .SQLITE_MISUSE, message: """ - GRDB is not linked against SQLCipher. \ - Check https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 - """) - } - } - #endif - private func validateFormat() throws { // Users are surprised when they open a picture as a database and // see no error (https://github.com/groue/GRDB.swift/issues/54). @@ -1947,80 +1930,6 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib @available(*, unavailable) extension Database: Sendable { } -#if SQLITE_HAS_CODEC -extension Database { - - // MARK: - Encryption - - /// Sets the passphrase used to crypt and decrypt an SQLCipher database. - /// - /// Call this method from `Configuration.prepareDatabase`, - /// as in the example below: - /// - /// var config = Configuration() - /// config.prepareDatabase { db in - /// try db.usePassphrase("secret") - /// } - public func usePassphrase(_ passphrase: String) throws { - guard var data = passphrase.data(using: .utf8) else { - throw DatabaseError(message: "invalid passphrase") - } - defer { - data.resetBytes(in: 0.. We (Zetetic) have been discouraging the use of sqlite3_rekey in - // > favor of attaching a new database with the desired encryption - // > options and using sqlcipher_export() to migrate the contents and - // > schema of the original db into the new one: - // > https://discuss.zetetic.net/t/how-to-encrypt-a-plaintext-sqlite-database-to-use-sqlcipher-and-avoid-file-is-encrypted-or-is-not-a-database-errors/ - let code = passphrase.withUnsafeBytes { - sqlite3_rekey(sqliteConnection, $0.baseAddress, CInt($0.count)) - } - guard code == SQLITE_OK else { - throw DatabaseError(resultCode: code, message: lastErrorMessage) - } - } -} -#endif - extension Database { /// Returns the count of changes executed by one statement execution. func countChanges(_ count: inout Int, forTable tableName: String, updates: () throws -> T) throws -> T { diff --git a/Package.swift b/Package.swift index f51b2866a1..73d7f0197a 100644 --- a/Package.swift +++ b/Package.swift @@ -26,6 +26,7 @@ var swiftSettings: [SwiftSetting] = [ // TODO: when Xcode support traits, remove all mentions of SQLITE_DISABLE_SNAPSHOT and update as below: // .define("SQLITE_ENABLE_SNAPSHOT", .when(platforms: darwinPlatforms, traits: ["GRDBSQLite"])), .define("SQLITE_ENABLE_SNAPSHOT"), + .define("SQLITE_DISABLE_SNAPSHOT", sqlcipherTraitBuildSettingCondition), .define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition), .define("SQLCIPHER", sqlcipherTraitBuildSettingCondition) ] From 4d79988dd8d32f7b1fe98a5e39ef5fc1cba961a4 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 12:35:43 -0400 Subject: [PATCH 05/17] Switches #if GRDBCIPHER in EncryptionTests to #if SQLITE_HAS_CODEC --- Tests/GRDBTests/EncryptionTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/GRDBTests/EncryptionTests.swift b/Tests/GRDBTests/EncryptionTests.swift index ac11de8122..fcf0bda751 100644 --- a/Tests/GRDBTests/EncryptionTests.swift +++ b/Tests/GRDBTests/EncryptionTests.swift @@ -1,4 +1,4 @@ -#if GRDBCIPHER +#if SQLITE_HAS_CODEC import XCTest import GRDB From 011fc7d8c33c1bbf3c8f89ab88c098642f98077d Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 13:37:31 -0400 Subject: [PATCH 06/17] Adds test_SPM_SQLCipher as depdendent task of test_framework_darwin --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 73f0b912d6..0c673b3a4b 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ endif test: test_framework test_archive test_install test_demo_apps test_framework: test_framework_darwin -test_framework_darwin: test_framework_GRDB test_framework_GRDBCustom test_framework_SQLCipher test_SPM +test_framework_darwin: test_framework_GRDB test_framework_GRDBCustom test_framework_SQLCipher test_SPM test_SPM_SQLCipher test_framework_GRDB: test_framework_GRDBOSX test_framework_GRDBiOS test_framework_GRDBtvOS test_framework_GRDBCustom: test_framework_GRDBCustomSQLiteOSX test_framework_GRDBCustomSQLiteiOS test_framework_SQLCipher: test_framework_SQLCipher3 test_framework_SQLCipher3Encrypted test_framework_SQLCipher4 test_framework_SQLCipher4Encrypted From 6666a359dc39de62bc554182587894ad385fe282 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Mon, 13 Oct 2025 16:38:43 -0400 Subject: [PATCH 07/17] - Adds Tests/SPM/sqlcipher test project + sample AppDependencies SPM to test installing GRDB with SQLCipher trait - Adds test_install_SPM_SQLCipher Makefile task called as dependent task of test_install_SPM - Adjusts README.md SQLCipher example AppDependencies Package.swift to match GRDB platform versions --- .gitignore | 6 + Makefile | 26 +- README.md | 8 +- .../SPM/sqlcipher/AppDependencies/.gitignore | 8 + .../sqlcipher/AppDependencies/Package.swift | 34 ++ .../AppDependencies/AppDependencies.swift | 2 + .../sqlcipher.xcodeproj/project.pbxproj | 400 ++++++++++++++++++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 85 ++++ .../sqlcipher/Assets.xcassets/Contents.json | 6 + .../SPM/sqlcipher/sqlcipher/ContentView.swift | 14 + .../sqlcipher/sqlcipher/sqlcipherApp.swift | 10 + 12 files changed, 604 insertions(+), 6 deletions(-) create mode 100644 Tests/SPM/sqlcipher/AppDependencies/.gitignore create mode 100644 Tests/SPM/sqlcipher/AppDependencies/Package.swift create mode 100644 Tests/SPM/sqlcipher/AppDependencies/Sources/AppDependencies/AppDependencies.swift create mode 100644 Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj create mode 100644 Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/Contents.json create mode 100644 Tests/SPM/sqlcipher/sqlcipher/ContentView.swift create mode 100644 Tests/SPM/sqlcipher/sqlcipher/sqlcipherApp.swift diff --git a/.gitignore b/.gitignore index 7c7e11035d..c06534e1d7 100644 --- a/.gitignore +++ b/.gitignore @@ -115,3 +115,9 @@ Tests/SPM/Packages # Test products Tests/products + +# SPM Package.resolved +**Package.resolved + +# SQLCipher SPM Test project xcworkspace +Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.xcworkspace/ diff --git a/Makefile b/Makefile index 0c673b3a4b..a55caf5d8d 100644 --- a/Makefile +++ b/Makefile @@ -285,7 +285,7 @@ test_install_manual: clean build \ $(XCPRETTY) -test_install_SPM: test_install_SPM_Package test_install_SPM_Project test_install_SPM_Dynamic_Project test_install_SPM_macos_release test_install_SPM_ios_release +test_install_SPM: test_install_SPM_Package test_install_SPM_Project test_install_SPM_Dynamic_Project test_install_SPM_macos_release test_install_SPM_ios_release test_install_SPM_SQLCipher test_install_SPM_Package: rm -rf Tests/products @@ -333,6 +333,30 @@ test_install_SPM_ios_release: clean build \ $(XCPRETTY) +test_install_SPM_SQLCipher: + rm -rf Tests/products + $(XCODEBUILD) \ + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination $(MAX_IOS_DESTINATION) \ + -configuration Release \ + clean build \ + $(XCPRETTY) + $(XCODEBUILD) \ + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination "platform=macOS" \ + -configuration Release \ + clean build \ + $(XCPRETTY) + $(XCODEBUILD) \ + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination $(MAX_TVOS_DESTINATION) \ + -configuration Release \ + clean build \ + $(XCPRETTY) + test_install_customSQLite: SQLiteCustom $(XCODEBUILD) \ -project Tests/CustomSQLite/CustomSQLite.xcodeproj \ diff --git a/README.md b/README.md index 9db3ce7d41..1f25695ccf 100644 --- a/README.md +++ b/README.md @@ -4620,12 +4620,10 @@ import PackageDescription let package = Package( name: "AppDependencies", platforms: [ - .macOS(.v10_14), + .macOS(.v10_15), .iOS(.v13), - .macCatalyst(.v13), - .watchOS(.v8), - .tvOS(.v15), - .visionOS(.v1) + .watchOS(.v7), + .tvOS(.v13) ], products: [ .library( diff --git a/Tests/SPM/sqlcipher/AppDependencies/.gitignore b/Tests/SPM/sqlcipher/AppDependencies/.gitignore new file mode 100644 index 0000000000..0023a53406 --- /dev/null +++ b/Tests/SPM/sqlcipher/AppDependencies/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Tests/SPM/sqlcipher/AppDependencies/Package.swift b/Tests/SPM/sqlcipher/AppDependencies/Package.swift new file mode 100644 index 0000000000..1cf151e41c --- /dev/null +++ b/Tests/SPM/sqlcipher/AppDependencies/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version: 6.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "AppDependencies", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .watchOS(.v7), + .tvOS(.v13) + ], + products: [ + .library( + name: "AppDependencies", + targets: ["AppDependencies"]), + ], + dependencies: [ + .package( + path: "../../../..", + traits: ["SQLCipher"]) + ], + targets: [ + .target( + name: "AppDependencies", + dependencies: [ + .product( + name: "GRDB", + package: "GRDB.swift") + ] + ) + ] +) diff --git a/Tests/SPM/sqlcipher/AppDependencies/Sources/AppDependencies/AppDependencies.swift b/Tests/SPM/sqlcipher/AppDependencies/Sources/AppDependencies/AppDependencies.swift new file mode 100644 index 0000000000..08b22b80fc --- /dev/null +++ b/Tests/SPM/sqlcipher/AppDependencies/Sources/AppDependencies/AppDependencies.swift @@ -0,0 +1,2 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book diff --git a/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj b/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..a12ad7009d --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj @@ -0,0 +1,400 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 1C4FE57B2E9D909E00C066A8 /* AppDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = 1C4FE57A2E9D909E00C066A8 /* AppDependencies */; }; + 1CFE15162E9D92A900D98E29 /* AppDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = 1CFE15152E9D92A900D98E29 /* AppDependencies */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1C7EBC072E9D8ED60059C430 /* sqlcipher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sqlcipher.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1CFE150A2E9D928F00D98E29 /* sqlcipher.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = sqlcipher.xcodeproj; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 1C7EBC092E9D8ED60059C430 /* sqlcipher */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = sqlcipher; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1C7EBC042E9D8ED60059C430 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1C4FE57B2E9D909E00C066A8 /* AppDependencies in Frameworks */, + 1CFE15162E9D92A900D98E29 /* AppDependencies in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1C7EBBFE2E9D8ED60059C430 = { + isa = PBXGroup; + children = ( + 1C7EBC092E9D8ED60059C430 /* sqlcipher */, + 1C7EBC082E9D8ED60059C430 /* Products */, + ); + sourceTree = ""; + }; + 1C7EBC082E9D8ED60059C430 /* Products */ = { + isa = PBXGroup; + children = ( + 1C7EBC072E9D8ED60059C430 /* sqlcipher.app */, + ); + name = Products; + sourceTree = ""; + }; + 1CFE150C2E9D928F00D98E29 /* Products */ = { + isa = PBXGroup; + children = ( + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1C7EBC062E9D8ED60059C430 /* sqlcipher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1C7EBC122E9D8ED90059C430 /* Build configuration list for PBXNativeTarget "sqlcipher" */; + buildPhases = ( + 1C7EBC032E9D8ED60059C430 /* Sources */, + 1C7EBC042E9D8ED60059C430 /* Frameworks */, + 1C7EBC052E9D8ED60059C430 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 1C7EBC092E9D8ED60059C430 /* sqlcipher */, + ); + name = sqlcipher; + packageProductDependencies = ( + 1C4FE57A2E9D909E00C066A8 /* AppDependencies */, + 1CFE15152E9D92A900D98E29 /* AppDependencies */, + ); + productName = sqlcipher; + productReference = 1C7EBC072E9D8ED60059C430 /* sqlcipher.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1C7EBBFF2E9D8ED60059C430 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 2600; + LastUpgradeCheck = 2600; + TargetAttributes = { + 1C7EBC062E9D8ED60059C430 = { + CreatedOnToolsVersion = 26.0.1; + }; + }; + }; + buildConfigurationList = 1C7EBC022E9D8ED60059C430 /* Build configuration list for PBXProject "sqlcipher" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 1C7EBBFE2E9D8ED60059C430; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + 1CFE15142E9D92A900D98E29 /* XCLocalSwiftPackageReference "AppDependencies" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = 1C7EBC082E9D8ED60059C430 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 1CFE150C2E9D928F00D98E29 /* Products */; + ProjectRef = 1CFE150A2E9D928F00D98E29 /* sqlcipher.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 1C7EBC062E9D8ED60059C430 /* sqlcipher */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1C7EBC052E9D8ED60059C430 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1C7EBC032E9D8ED60059C430 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1C7EBC102E9D8ED90059C430 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1C7EBC112E9D8ED90059C430 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + 1C7EBC132E9D8ED90059C430 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.groue.sqlcipher; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx xros xrsimulator"; + SUPPORTS_MACCATALYST = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,3,7"; + TVOS_DEPLOYMENT_TARGET = 15.6; + XROS_DEPLOYMENT_TARGET = 1.3; + }; + name = Debug; + }; + 1C7EBC142E9D8ED90059C430 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.groue.sqlcipher; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx xros xrsimulator"; + SUPPORTS_MACCATALYST = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,3,7"; + TVOS_DEPLOYMENT_TARGET = 15.6; + XROS_DEPLOYMENT_TARGET = 1.3; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1C7EBC022E9D8ED60059C430 /* Build configuration list for PBXProject "sqlcipher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1C7EBC102E9D8ED90059C430 /* Debug */, + 1C7EBC112E9D8ED90059C430 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1C7EBC122E9D8ED90059C430 /* Build configuration list for PBXNativeTarget "sqlcipher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1C7EBC132E9D8ED90059C430 /* Debug */, + 1C7EBC142E9D8ED90059C430 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 1CFE15142E9D92A900D98E29 /* XCLocalSwiftPackageReference "AppDependencies" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = AppDependencies; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 1C4FE57A2E9D909E00C066A8 /* AppDependencies */ = { + isa = XCSwiftPackageProductDependency; + productName = AppDependencies; + }; + 1CFE15152E9D92A900D98E29 /* AppDependencies */ = { + isa = XCSwiftPackageProductDependency; + productName = AppDependencies; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 1C7EBBFF2E9D8ED60059C430 /* Project object */; +} diff --git a/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AccentColor.colorset/Contents.json b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AppIcon.appiconset/Contents.json b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..ffdfe150be --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,85 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/Contents.json b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift new file mode 100644 index 0000000000..106fc86d7b --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift @@ -0,0 +1,14 @@ +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Text("Hello, world!") + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/Tests/SPM/sqlcipher/sqlcipher/sqlcipherApp.swift b/Tests/SPM/sqlcipher/sqlcipher/sqlcipherApp.swift new file mode 100644 index 0000000000..aec640930c --- /dev/null +++ b/Tests/SPM/sqlcipher/sqlcipher/sqlcipherApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct sqlcipherApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} From ad2d06cf2f40357b24e1896fdc3e9a98a2db17e4 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Tue, 14 Oct 2025 14:48:29 -0400 Subject: [PATCH 08/17] - Avoids hiding errors in high-level accessors in Database+SQLCipher - Removes exposing SQLCipherConfig shim package publicly in Package.swift - Calls dropAllDatabaseObjects from Database.erase() method when `#if SQLITE_HAS_CODEC` (SQLCipher enabled) - Adds `--traits SQLCipher` to swift build commands in test_SPM_SQLCipher Makefile task - Fixes formatting of XCODEBUILD commands in test_install_SPM_SQLCipher Makefile task - Removes setting SQLCIPHER swiftSetting in favor of using SQLCipher trait directly in import statements - Removes unneeded `#if SQLITE_VERSION_NUMBER >= 3029000` from SQLCipherConfig shim - Adjusts SQLCipher Information Accessors example code to use try variants in README.md - Adds details/summary to cipher_logging Example output in README.md - Adds cipherVersion display to sqlcipher SPM install test project - Removes references to Database+SQLCipher from GRDB.xcodeproj (only used for SPM) - Removes duplicate reference to AppDependencies in sqlcipher.xcodeproj (SQLCipher SPM example project) --- GRDB.xcodeproj/project.pbxproj | 6 --- GRDB/Core/Configuration.swift | 2 +- GRDB/Core/Database+SQLCipher.swift | 10 ++--- GRDB/Core/Database+Schema.swift | 2 +- GRDB/Core/Database+Statements.swift | 2 +- GRDB/Core/Database.swift | 32 +-------------- GRDB/Core/DatabaseCollation.swift | 2 +- GRDB/Core/DatabaseError.swift | 2 +- GRDB/Core/DatabaseFunction.swift | 2 +- GRDB/Core/DatabaseSnapshotPool.swift | 2 +- GRDB/Core/DatabaseValue.swift | 2 +- GRDB/Core/Row.swift | 2 +- GRDB/Core/RowDecodingError.swift | 2 +- GRDB/Core/Statement.swift | 2 +- GRDB/Core/StatementAuthorizer.swift | 2 +- GRDB/Core/StatementColumnConvertible.swift | 2 +- GRDB/Core/Support/Foundation/Data.swift | 2 +- .../Foundation/DatabaseDateComponents.swift | 2 +- GRDB/Core/Support/Foundation/Date.swift | 2 +- GRDB/Core/Support/Foundation/Decimal.swift | 2 +- GRDB/Core/Support/Foundation/UUID.swift | 2 +- .../Support/StandardLibrary/Optional.swift | 2 +- .../StandardLibrary/StandardLibrary.swift | 2 +- GRDB/Core/TransactionObserver.swift | 2 +- GRDB/Core/WALSnapshot.swift | 2 +- GRDB/Dump/DumpFormats/DebugDumpFormat.swift | 2 +- GRDB/Dump/DumpFormats/JSONDumpFormat.swift | 2 +- GRDB/Dump/DumpFormats/LineDumpFormat.swift | 2 +- GRDB/Dump/DumpFormats/ListDumpFormat.swift | 2 +- GRDB/Dump/DumpFormats/QuoteDumpFormat.swift | 2 +- GRDB/FTS/FTS5.swift | 2 +- GRDB/FTS/FTS5CustomTokenizer.swift | 2 +- GRDB/FTS/FTS5Tokenizer.swift | 2 +- GRDB/FTS/FTS5WrapperTokenizer.swift | 2 +- GRDB/Record/FetchableRecord+Decodable.swift | 2 +- Makefile | 40 +++++++++---------- Package.swift | 2 - README.md | 13 +++--- .../include/SQLCipher_config.h | 5 --- .../AssociationPrefetchingRowTests.swift | 2 +- Tests/GRDBTests/DataMemoryTests.swift | 2 +- .../DatabasePoolReleaseMemoryTests.swift | 2 +- Tests/GRDBTests/DatabasePoolTests.swift | 2 +- Tests/GRDBTests/EncryptionTests.swift | 16 ++++---- Tests/GRDBTests/GRDBTestCase.swift | 2 +- ...StatementColumnConvertibleFetchTests.swift | 2 +- Tests/GRDBTests/UpdateStatementTests.swift | 2 +- .../sqlcipher.xcodeproj/project.pbxproj | 2 - .../SPM/sqlcipher/sqlcipher/ContentView.swift | 7 +++- 49 files changed, 88 insertions(+), 123 deletions(-) diff --git a/GRDB.xcodeproj/project.pbxproj b/GRDB.xcodeproj/project.pbxproj index 0195499764..c0d3f02a70 100755 --- a/GRDB.xcodeproj/project.pbxproj +++ b/GRDB.xcodeproj/project.pbxproj @@ -7,8 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 1C5348402E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */; }; - 1C5348412E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */; }; 4E13D2F32769B87F0037588C /* DatabaseBackupProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */; }; 4ED4BB592731DD25008B127D /* BackupTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED4BB582731DD25008B127D /* BackupTestCase.swift */; }; 56012B552573EED000B4925B /* CommonTableExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56012B542573EED000B4925B /* CommonTableExpressionTests.swift */; }; @@ -441,7 +439,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Database+SQLCipher.swift"; sourceTree = ""; }; 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseBackupProgress.swift; sourceTree = ""; }; 4ED4BB582731DD25008B127D /* BackupTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupTestCase.swift; sourceTree = ""; }; 56012B542573EED000B4925B /* CommonTableExpressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableExpressionTests.swift; sourceTree = ""; }; @@ -1590,7 +1587,6 @@ 56A238701B9C75030082EB20 /* Configuration.swift */, 56DAA2DA1DE9C827006E10C8 /* Cursor.swift */, 56A238711B9C75030082EB20 /* Database.swift */, - 1C53483F2E82DDCD00D5E58A /* Database+SQLCipher.swift */, 566B91221FA4CF810012D5B0 /* Database+Schema.swift */, 566B91081FA4C3960012D5B0 /* Database+Statements.swift */, 4E13D2F22769B87F0037588C /* DatabaseBackupProgress.swift */, @@ -1967,7 +1963,6 @@ 563DE4F3231A91E2005081B7 /* DatabaseConfigurationTests.swift in Sources */, 56BF2282241781C5003D86EB /* UtilsTests.swift in Sources */, 56CC9243201E034D00CB597E /* PrefixWhileCursorTests.swift in Sources */, - 1C5348412E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */, 560714E3227DD0810091BB10 /* AssociationPrefetchingSQLTests.swift in Sources */, 56D496841D813147008276D7 /* SelectStatementTests.swift in Sources */, 561F38D82AC88A550051EEE9 /* JSONColumnTests.swift in Sources */, @@ -2277,7 +2272,6 @@ 56256ED925D1B316008C2BDD /* ForeignKey.swift in Sources */, 56D51D001EA789FA0074638A /* FetchableRecord+TableRecord.swift in Sources */, 56D110D328AFC81400E64463 /* PersistableRecord.swift in Sources */, - 1C5348402E82DDCD00D5E58A /* Database+SQLCipher.swift in Sources */, 5653EB0920944C7C00F46237 /* Association.swift in Sources */, 56A238851B9C75030082EB20 /* DatabaseValue.swift in Sources */, 5671FC201DA3CAC9003BF4FF /* FTS3TokenizerDescriptor.swift in Sources */, diff --git a/GRDB/Core/Configuration.swift b/GRDB/Core/Configuration.swift index 252d051efe..e2b1ea2c81 100644 --- a/GRDB/Core/Configuration.swift +++ b/GRDB/Core/Configuration.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Database+SQLCipher.swift b/GRDB/Core/Database+SQLCipher.swift index 140423e718..76e44f7152 100644 --- a/GRDB/Core/Database+SQLCipher.swift +++ b/GRDB/Core/Database+SQLCipher.swift @@ -20,7 +20,7 @@ extension Database { /// /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_version public var cipherVersion: String? { - (try? String.fetchOne(self, sql: "PRAGMA cipher_version")) + get throws { try String.fetchOne(self, sql: "PRAGMA cipher_version") } } /// - Returns: the SQLCipher fips status: 1 for fips mode, 0 for non-fips mode @@ -28,7 +28,7 @@ extension Database { /// /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_fips_status public var cipherFipsStatus: String? { - (try? String.fetchOne(self, sql: "PRAGMA cipher_fips_status")) + get throws { try String.fetchOne(self, sql: "PRAGMA cipher_fips_status") } } /// - Returns: The compiled crypto provider. @@ -36,7 +36,7 @@ extension Database { /// /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider public var cipherProvider: String? { - (try? String.fetchOne(self, sql: "PRAGMA cipher_provider")) + get throws { try String.fetchOne(self, sql: "PRAGMA cipher_provider") } } /// - Returns: the version number provided from the compiled crypto provider. @@ -44,7 +44,7 @@ extension Database { /// /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_provider_version public var cipherProviderVersion: String? { - (try? String.fetchOne(self, sql: "PRAGMA cipher_provider_version")) + get throws { try String.fetchOne(self, sql: "PRAGMA cipher_provider_version") } } /// Sets the passphrase used to crypt and decrypt an SQLCipher database. @@ -167,7 +167,7 @@ extension Database { // > applications institute a runtime test to ensure that the // > application is actually using SQLCipher on the active // > connection. - if cipherVersion == nil { + if try cipherVersion == nil { throw DatabaseError(resultCode: .SQLITE_MISUSE, message: """ GRDB is not linked against SQLCipher. \ Check https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 diff --git a/GRDB/Core/Database+Schema.swift b/GRDB/Core/Database+Schema.swift index a4279a90e0..d1e17ca491 100644 --- a/GRDB/Core/Database+Schema.swift +++ b/GRDB/Core/Database+Schema.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Database+Statements.swift b/GRDB/Core/Database+Statements.swift index 8b4584bdae..3f75d47284 100644 --- a/GRDB/Core/Database+Statements.swift +++ b/GRDB/Core/Database+Statements.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Database.swift b/GRDB/Core/Database.swift index 02521a2be3..628a1f6036 100644 --- a/GRDB/Core/Database.swift +++ b/GRDB/Core/Database.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher import SQLCipherConfig #else // Default SPM trait must be the default. It impossible to detect from Xcode. @@ -1779,35 +1779,7 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib func erase() throws { #if SQLITE_HAS_CODEC - // SQLCipher does not support the backup API: - // https://discuss.zetetic.net/t/using-the-sqlite-online-backup-api/2631 - // So we'll drop all database objects one after the other. - - // Prevent foreign keys from messing with drop table statements - let foreignKeysEnabled = try Bool.fetchOne(self, sql: "PRAGMA foreign_keys")! - if foreignKeysEnabled { - try execute(sql: "PRAGMA foreign_keys = OFF") - } - - try throwingFirstError( - execute: { - // Remove all database objects, one after the other - try inTransaction { - let sql = "SELECT type, name FROM sqlite_master WHERE name NOT LIKE 'sqlite_%'" - while let row = try Row.fetchOne(self, sql: sql) { - let type: String = row["type"] - let name: String = row["name"] - try execute(sql: "DROP \(type) \(name.quotedDatabaseIdentifier)") - } - return .commit - } - }, - finally: { - // Restore foreign keys if needed - if foreignKeysEnabled { - try execute(sql: "PRAGMA foreign_keys = ON") - } - }) + try dropAllDatabaseObjects() #else try DatabaseQueue().backup(to: self) #endif diff --git a/GRDB/Core/DatabaseCollation.swift b/GRDB/Core/DatabaseCollation.swift index 5b026e4f6f..82f583ab39 100644 --- a/GRDB/Core/DatabaseCollation.swift +++ b/GRDB/Core/DatabaseCollation.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/DatabaseError.swift b/GRDB/Core/DatabaseError.swift index 8370f8e2f4..f7c6b2c5d6 100644 --- a/GRDB/Core/DatabaseError.swift +++ b/GRDB/Core/DatabaseError.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/DatabaseFunction.swift b/GRDB/Core/DatabaseFunction.swift index 00291b1e06..845433a0da 100644 --- a/GRDB/Core/DatabaseFunction.swift +++ b/GRDB/Core/DatabaseFunction.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/DatabaseSnapshotPool.swift b/GRDB/Core/DatabaseSnapshotPool.swift index d9622a2cbf..40e55c4f68 100644 --- a/GRDB/Core/DatabaseSnapshotPool.swift +++ b/GRDB/Core/DatabaseSnapshotPool.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/DatabaseValue.swift b/GRDB/Core/DatabaseValue.swift index 6d7b03f281..7a36b34772 100644 --- a/GRDB/Core/DatabaseValue.swift +++ b/GRDB/Core/DatabaseValue.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Row.swift b/GRDB/Core/Row.swift index 74127949fe..8f34f28514 100644 --- a/GRDB/Core/Row.swift +++ b/GRDB/Core/Row.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/RowDecodingError.swift b/GRDB/Core/RowDecodingError.swift index 4af6e16676..b1db07eaac 100644 --- a/GRDB/Core/RowDecodingError.swift +++ b/GRDB/Core/RowDecodingError.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Statement.swift b/GRDB/Core/Statement.swift index 6c2eb761dd..5f91e013be 100644 --- a/GRDB/Core/Statement.swift +++ b/GRDB/Core/Statement.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/StatementAuthorizer.swift b/GRDB/Core/StatementAuthorizer.swift index 6ea798c5f1..6dc9c4ae51 100644 --- a/GRDB/Core/StatementAuthorizer.swift +++ b/GRDB/Core/StatementAuthorizer.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/StatementColumnConvertible.swift b/GRDB/Core/StatementColumnConvertible.swift index 1dc9d26225..4da0217444 100644 --- a/GRDB/Core/StatementColumnConvertible.swift +++ b/GRDB/Core/StatementColumnConvertible.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/Foundation/Data.swift b/GRDB/Core/Support/Foundation/Data.swift index fe1fabf1cf..ff895b6e72 100644 --- a/GRDB/Core/Support/Foundation/Data.swift +++ b/GRDB/Core/Support/Foundation/Data.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift b/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift index 66a5abb101..e7cec16243 100644 --- a/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift +++ b/GRDB/Core/Support/Foundation/DatabaseDateComponents.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/Foundation/Date.swift b/GRDB/Core/Support/Foundation/Date.swift index 15ba06ac17..a1d179e8fe 100644 --- a/GRDB/Core/Support/Foundation/Date.swift +++ b/GRDB/Core/Support/Foundation/Date.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/Foundation/Decimal.swift b/GRDB/Core/Support/Foundation/Decimal.swift index 1c2e7ae891..0be2a68a9a 100644 --- a/GRDB/Core/Support/Foundation/Decimal.swift +++ b/GRDB/Core/Support/Foundation/Decimal.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/Foundation/UUID.swift b/GRDB/Core/Support/Foundation/UUID.swift index 5c77f5f583..f2780c3cc0 100644 --- a/GRDB/Core/Support/Foundation/UUID.swift +++ b/GRDB/Core/Support/Foundation/UUID.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/StandardLibrary/Optional.swift b/GRDB/Core/Support/StandardLibrary/Optional.swift index e6647d4a76..b598b119ae 100644 --- a/GRDB/Core/Support/StandardLibrary/Optional.swift +++ b/GRDB/Core/Support/StandardLibrary/Optional.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift b/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift index 23d0a112de..c431aecc57 100644 --- a/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift +++ b/GRDB/Core/Support/StandardLibrary/StandardLibrary.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/TransactionObserver.swift b/GRDB/Core/TransactionObserver.swift index 578af415cb..80289983ef 100644 --- a/GRDB/Core/TransactionObserver.swift +++ b/GRDB/Core/TransactionObserver.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Core/WALSnapshot.swift b/GRDB/Core/WALSnapshot.swift index 3c46c2c0f8..7009b4b5e4 100644 --- a/GRDB/Core/WALSnapshot.swift +++ b/GRDB/Core/WALSnapshot.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Dump/DumpFormats/DebugDumpFormat.swift b/GRDB/Dump/DumpFormats/DebugDumpFormat.swift index f3606e529e..0d0288ce01 100644 --- a/GRDB/Dump/DumpFormats/DebugDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/DebugDumpFormat.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Dump/DumpFormats/JSONDumpFormat.swift b/GRDB/Dump/DumpFormats/JSONDumpFormat.swift index 8eb19c2636..47cb75d36c 100644 --- a/GRDB/Dump/DumpFormats/JSONDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/JSONDumpFormat.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Dump/DumpFormats/LineDumpFormat.swift b/GRDB/Dump/DumpFormats/LineDumpFormat.swift index e8daca020b..7416b96761 100644 --- a/GRDB/Dump/DumpFormats/LineDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/LineDumpFormat.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Dump/DumpFormats/ListDumpFormat.swift b/GRDB/Dump/DumpFormats/ListDumpFormat.swift index a7c7d05d74..146eb97856 100644 --- a/GRDB/Dump/DumpFormats/ListDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/ListDumpFormat.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift b/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift index b0ecc8cde4..fd67b7de15 100644 --- a/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift +++ b/GRDB/Dump/DumpFormats/QuoteDumpFormat.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/FTS/FTS5.swift b/GRDB/FTS/FTS5.swift index 9400d23e96..adb108cc70 100644 --- a/GRDB/FTS/FTS5.swift +++ b/GRDB/FTS/FTS5.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/FTS/FTS5CustomTokenizer.swift b/GRDB/FTS/FTS5CustomTokenizer.swift index fb0dcbe6b1..63e3912fb9 100644 --- a/GRDB/FTS/FTS5CustomTokenizer.swift +++ b/GRDB/FTS/FTS5CustomTokenizer.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/FTS/FTS5Tokenizer.swift b/GRDB/FTS/FTS5Tokenizer.swift index cdd3fffe88..41bd62aa92 100644 --- a/GRDB/FTS/FTS5Tokenizer.swift +++ b/GRDB/FTS/FTS5Tokenizer.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/FTS/FTS5WrapperTokenizer.swift b/GRDB/FTS/FTS5WrapperTokenizer.swift index 9b91bd14d5..0b355f6b56 100644 --- a/GRDB/FTS/FTS5WrapperTokenizer.swift +++ b/GRDB/FTS/FTS5WrapperTokenizer.swift @@ -5,7 +5,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/GRDB/Record/FetchableRecord+Decodable.swift b/GRDB/Record/FetchableRecord+Decodable.swift index c713ee8e6b..069a06d8fb 100644 --- a/GRDB/Record/FetchableRecord+Decodable.swift +++ b/GRDB/Record/FetchableRecord+Decodable.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Makefile b/Makefile index a55caf5d8d..0bad2f9d89 100644 --- a/Makefile +++ b/Makefile @@ -226,8 +226,8 @@ test_SPM: test_SPM_SQLCipher: rm -rf Tests/products $(SWIFT) package clean - $(SWIFT) build - $(SWIFT) build -c release + $(SWIFT) build --traits SQLCipher + $(SWIFT) build -c release --traits SQLCipher set -o pipefail && $(SWIFT) test --parallel --traits SQLCipher test_universal_xcframework: @@ -336,26 +336,26 @@ test_install_SPM_ios_release: test_install_SPM_SQLCipher: rm -rf Tests/products $(XCODEBUILD) \ - -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ - -scheme sqlcipher \ - -destination $(MAX_IOS_DESTINATION) \ - -configuration Release \ - clean build \ - $(XCPRETTY) + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination $(MAX_IOS_DESTINATION) \ + -configuration Release \ + clean build \ + $(XCPRETTY) $(XCODEBUILD) \ - -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ - -scheme sqlcipher \ - -destination "platform=macOS" \ - -configuration Release \ - clean build \ - $(XCPRETTY) + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination "platform=macOS" \ + -configuration Release \ + clean build \ + $(XCPRETTY) $(XCODEBUILD) \ - -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ - -scheme sqlcipher \ - -destination $(MAX_TVOS_DESTINATION) \ - -configuration Release \ - clean build \ - $(XCPRETTY) + -project Tests/SPM/sqlcipher/sqlcipher.xcodeproj \ + -scheme sqlcipher \ + -destination $(MAX_TVOS_DESTINATION) \ + -configuration Release \ + clean build \ + $(XCPRETTY) test_install_customSQLite: SQLiteCustom $(XCODEBUILD) \ diff --git a/Package.swift b/Package.swift index 73d7f0197a..3aa0b2fb23 100644 --- a/Package.swift +++ b/Package.swift @@ -28,7 +28,6 @@ var swiftSettings: [SwiftSetting] = [ .define("SQLITE_ENABLE_SNAPSHOT"), .define("SQLITE_DISABLE_SNAPSHOT", sqlcipherTraitBuildSettingCondition), .define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition), - .define("SQLCIPHER", sqlcipherTraitBuildSettingCondition) ] var cSettings: [CSetting] = [ @@ -69,7 +68,6 @@ let package = Package( .library(name: "GRDBSQLite", targets: ["GRDBSQLite"]), .library(name: "GRDB", targets: ["GRDB"]), .library(name: "GRDB-dynamic", type: .dynamic, targets: ["GRDB"]), - .library(name: "SQLCipherConfig", targets: ["SQLCipherConfig"]) ], traits: [ "GRDBSQLite", diff --git a/README.md b/README.md index 1f25695ccf..2aff247688 100644 --- a/README.md +++ b/README.md @@ -4830,7 +4830,8 @@ config.prepareDatabase { db in let dbQueue = try DatabaseQueue(path: NSTemporaryDirectory().appending("test.db"), configuration: config) ``` -Example output: +
+ Example output: ``` DEBUG CORE sqlite3_key: db=104E22830 @@ -4858,6 +4859,8 @@ DEBUG MEMORY cipher_ctx_free: iCtx=128008110 DEBUG MEMORY cipher_ctx_free: iCtx=128008118 ``` +
+ You can disable cipher logging with `disableCipherLogging()`, following up on the previous example: ``` @@ -4875,7 +4878,7 @@ GRDB provides convenience accessors to get information about the SQLCipher versi ``` let cipherVersion = try dbQueue.read { db in - return db.cipherVersion + try db.cipherVersion } ``` @@ -4884,7 +4887,7 @@ let cipherVersion = try dbQueue.read { db in ``` let cipherProvider = try dbQueue.read { db in - return db.cipherProvider + try db.cipherProvider } ``` @@ -4893,7 +4896,7 @@ let cipherProvider = try dbQueue.read { db in ``` let cipherProviderVersion = try dbQueue.read { db in - return db.cipherProviderVersion + try db.cipherProviderVersion } ``` @@ -4902,7 +4905,7 @@ let cipherProviderVersion = try dbQueue.read { db in ``` let cipherFipsStatus = try dbQueue.read { db in - return db.cipherFipsStatus + try db.cipherFipsStatus } ``` diff --git a/Sources/SQLCipherConfig/include/SQLCipher_config.h b/Sources/SQLCipherConfig/include/SQLCipher_config.h index a405306f63..b19032d087 100644 --- a/Sources/SQLCipherConfig/include/SQLCipher_config.h +++ b/Sources/SQLCipherConfig/include/SQLCipher_config.h @@ -11,7 +11,6 @@ static inline void _registerErrorLogCallback(_errorLogCallback callback) { sqlite3_config(SQLITE_CONFIG_LOG, callback, 0); } -#if SQLITE_VERSION_NUMBER >= 3029000 /// Wrapper around sqlite3_db_config() which is a variadic function that can't /// be used from Swift. static inline void _disableDoubleQuotedStringLiterals(sqlite3 *db) { @@ -25,8 +24,4 @@ static inline void _enableDoubleQuotedStringLiterals(sqlite3 *db) { sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 1, (void *)0); sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 1, (void *)0); } -#else -static inline void _disableDoubleQuotedStringLiterals(sqlite3 *db) { } -static inline void _enableDoubleQuotedStringLiterals(sqlite3 *db) { } -#endif #endif /* grdb_config_h */ diff --git a/Tests/GRDBTests/AssociationPrefetchingRowTests.swift b/Tests/GRDBTests/AssociationPrefetchingRowTests.swift index af160aafc1..76ec55d071 100644 --- a/Tests/GRDBTests/AssociationPrefetchingRowTests.swift +++ b/Tests/GRDBTests/AssociationPrefetchingRowTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/DataMemoryTests.swift b/Tests/GRDBTests/DataMemoryTests.swift index 937cd419c1..5d7f4f5406 100644 --- a/Tests/GRDBTests/DataMemoryTests.swift +++ b/Tests/GRDBTests/DataMemoryTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift b/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift index 66ca9587cb..67108860e9 100644 --- a/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift +++ b/Tests/GRDBTests/DatabasePoolReleaseMemoryTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/DatabasePoolTests.swift b/Tests/GRDBTests/DatabasePoolTests.swift index 9876966853..86dfa9a757 100644 --- a/Tests/GRDBTests/DatabasePoolTests.swift +++ b/Tests/GRDBTests/DatabasePoolTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/EncryptionTests.swift b/Tests/GRDBTests/EncryptionTests.swift index fcf0bda751..87cbbcb1e9 100644 --- a/Tests/GRDBTests/EncryptionTests.swift +++ b/Tests/GRDBTests/EncryptionTests.swift @@ -736,7 +736,7 @@ let testBundle = Bundle(for: GRDBTestCase.self) func testCipherVersion() throws { try DatabaseQueue().inDatabase { db in - XCTAssertNotNil(db.cipherVersion, "SQLCipher not properly loaded") + XCTAssertNotNil(try db.cipherVersion, "SQLCipher not properly loaded") } } @@ -746,8 +746,8 @@ let testBundle = Bundle(for: GRDBTestCase.self) try db.usePassphrase("secret") } let dbQueue = try makeDatabaseQueue(configuration: config) - dbQueue.inDatabase { db in - XCTAssertEqual("0", db.cipherFipsStatus) + try dbQueue.inDatabase { db in + XCTAssertEqual("0", try db.cipherFipsStatus) } } @@ -757,8 +757,8 @@ let testBundle = Bundle(for: GRDBTestCase.self) try db.usePassphrase("secret") } let dbQueue = try makeDatabaseQueue(configuration: config) - dbQueue.inDatabase { db in - XCTAssertEqual("commoncrypto", db.cipherProvider) + try dbQueue.inDatabase { db in + XCTAssertEqual("commoncrypto", try db.cipherProvider) } } @@ -768,15 +768,15 @@ let testBundle = Bundle(for: GRDBTestCase.self) try db.usePassphrase("secret") } let dbQueue = try makeDatabaseQueue(configuration: config) - guard let cipherVersion = try dbQueue.read({ $0.cipherVersion }) else { + guard let cipherVersion = try dbQueue.read({ try $0.cipherVersion }) else { XCTFail("No Cipher Version found") return } if "4.10.0".compare(cipherVersion, options: .numeric) == .orderedDescending { throw XCTSkip("cipher_provider_version isn't available until SQLCipher 4.10.0") } - dbQueue.inDatabase { db in - XCTAssertNotNil(db.cipherProviderVersion) + try dbQueue.inDatabase { db in + XCTAssertNotNil(try db.cipherProviderVersion) } } } diff --git a/Tests/GRDBTests/GRDBTestCase.swift b/Tests/GRDBTests/GRDBTestCase.swift index d075a5748d..79d8372ac1 100644 --- a/Tests/GRDBTests/GRDBTestCase.swift +++ b/Tests/GRDBTests/GRDBTestCase.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift b/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift index ba9b5e558d..af9692cc06 100644 --- a/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift +++ b/Tests/GRDBTests/StatementColumnConvertibleFetchTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/GRDBTests/UpdateStatementTests.swift b/Tests/GRDBTests/UpdateStatementTests.swift index dfe9f33412..2f6a90cdcb 100644 --- a/Tests/GRDBTests/UpdateStatementTests.swift +++ b/Tests/GRDBTests/UpdateStatementTests.swift @@ -4,7 +4,7 @@ import SQLCipher #elseif GRDBFRAMEWORK // GRDB.xcodeproj or CocoaPods (standard subspec) import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework -#elseif SQLCIPHER +#elseif SQLCipher import SQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite diff --git a/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj b/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj index a12ad7009d..39eb124ca6 100644 --- a/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj +++ b/Tests/SPM/sqlcipher/sqlcipher.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 1C4FE57B2E9D909E00C066A8 /* AppDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = 1C4FE57A2E9D909E00C066A8 /* AppDependencies */; }; - 1CFE15162E9D92A900D98E29 /* AppDependencies in Frameworks */ = {isa = PBXBuildFile; productRef = 1CFE15152E9D92A900D98E29 /* AppDependencies */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -30,7 +29,6 @@ buildActionMask = 2147483647; files = ( 1C4FE57B2E9D909E00C066A8 /* AppDependencies in Frameworks */, - 1CFE15162E9D92A900D98E29 /* AppDependencies in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift index 106fc86d7b..aadbfb1a67 100644 --- a/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift +++ b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift @@ -1,12 +1,17 @@ import SwiftUI +import GRDB struct ContentView: View { var body: some View { VStack { - Text("Hello, world!") + Text("SQLCipher version: \(cipherVersion)") } .padding() } + + private var cipherVersion: String { + try! DatabaseQueue().read { try $0.cipherVersion ?? "Not SQLCipher" } + } } #Preview { From a6593b3c7b844c083240be7a2b8f5fcee169d2d1 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Wed, 15 Oct 2025 10:55:19 -0400 Subject: [PATCH 09/17] Switches https://www.sqlcipher.net link over to https://www.zetetic.net/sqlcipher in README.md SQLCipher encryption section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2aff247688..c16133c385 100644 --- a/README.md +++ b/README.md @@ -4597,7 +4597,7 @@ try Player.customRequest().fetchAll(db) // [Player] Encryption ========== -**GRDB can encrypt your database with [SQLCipher](https://www.sqlcipher.net) v3.4+.** +**GRDB can encrypt your database with [SQLCipher](https://www.zetetic.net/sqlcipher) v3.4+.** ### Swift Package Manager Integration (SQLCipher v4.11+) From 92ec14c9f3e9ab861d487487140f5ae2f507d0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:01:11 +0200 Subject: [PATCH 10/17] DatabaseSnapshotPool creates its snapshot with the provided configuration This is necessary for inheriting the SQLCipher passphrase. Also, update DatabaseConfigurationTests.testPrepareDatabase() so that it accurately counts the number of prepareDatabase invocations. --- GRDB/Core/DatabaseSnapshotPool.swift | 4 ++-- .../DatabaseConfigurationTests.swift | 20 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/GRDB/Core/DatabaseSnapshotPool.swift b/GRDB/Core/DatabaseSnapshotPool.swift index 40e55c4f68..460c799f40 100644 --- a/GRDB/Core/DatabaseSnapshotPool.swift +++ b/GRDB/Core/DatabaseSnapshotPool.swift @@ -140,7 +140,7 @@ public final class DatabaseSnapshotPool { let walSnapshot = try db.isolated(readOnly: true) { try WALSnapshot(db) } - var holderConfig = Configuration() + var holderConfig = configuration holderConfig.allowsUnsafeTransactions = true snapshotHolder = try DatabaseQueue(path: path, configuration: holderConfig) try snapshotHolder.inDatabase { db in @@ -199,7 +199,7 @@ public final class DatabaseSnapshotPool { var configuration = Self.configure(configuration) // Acquire and hold WAL snapshot - var holderConfig = Configuration() + var holderConfig = configuration holderConfig.allowsUnsafeTransactions = true snapshotHolder = try DatabaseQueue(path: path, configuration: holderConfig) let walSnapshot = try snapshotHolder.inDatabase { db in diff --git a/Tests/GRDBTests/DatabaseConfigurationTests.swift b/Tests/GRDBTests/DatabaseConfigurationTests.swift index f0739ba1c7..e89018492d 100644 --- a/Tests/GRDBTests/DatabaseConfigurationTests.swift +++ b/Tests/GRDBTests/DatabaseConfigurationTests.swift @@ -12,24 +12,32 @@ class DatabaseConfigurationTests: GRDBTestCase { connectionCountMutex.increment() } + connectionCountMutex.store(0) _ = try DatabaseQueue(configuration: configuration) XCTAssertEqual(connectionCountMutex.load(), 1) + connectionCountMutex.store(0) _ = try makeDatabaseQueue(configuration: configuration) - XCTAssertEqual(connectionCountMutex.load(), 2) + XCTAssertEqual(connectionCountMutex.load(), 1) + connectionCountMutex.store(0) let pool = try makeDatabasePool(configuration: configuration) - XCTAssertEqual(connectionCountMutex.load(), 3) + XCTAssertEqual(connectionCountMutex.load(), 1) // writer + connectionCountMutex.store(0) try pool.read { _ in } - XCTAssertEqual(connectionCountMutex.load(), 4) + XCTAssertEqual(connectionCountMutex.load(), 1) // 1st reader + connectionCountMutex.store(0) try pool.makeSnapshot().read { _ in } - XCTAssertEqual(connectionCountMutex.load(), 5) + XCTAssertEqual(connectionCountMutex.load(), 1) // snapshot #if SQLITE_ENABLE_SNAPSHOT && !SQLITE_DISABLE_SNAPSHOT - try pool.makeSnapshotPool().read { _ in } - XCTAssertEqual(connectionCountMutex.load(), 6) + connectionCountMutex.store(0) + let snapshotPool = try pool.makeSnapshotPool() + XCTAssertEqual(connectionCountMutex.load(), 1) // snapshot + try snapshotPool.read { _ in } + XCTAssertEqual(connectionCountMutex.load(), 2) // 1st reader #endif } From be8ba2266ec4f763785ee39cf6802e3a67e9de88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:01:38 +0200 Subject: [PATCH 11/17] Enable snapshots in the SQLCipher trait --- Package.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Package.swift b/Package.swift index 3aa0b2fb23..a1bf71f952 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,6 @@ var swiftSettings: [SwiftSetting] = [ // TODO: when Xcode support traits, remove all mentions of SQLITE_DISABLE_SNAPSHOT and update as below: // .define("SQLITE_ENABLE_SNAPSHOT", .when(platforms: darwinPlatforms, traits: ["GRDBSQLite"])), .define("SQLITE_ENABLE_SNAPSHOT"), - .define("SQLITE_DISABLE_SNAPSHOT", sqlcipherTraitBuildSettingCondition), .define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition), ] From e20799d56b4bc14dfb5fd132ba7623d863ab2184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:18:21 +0200 Subject: [PATCH 12/17] Database.cipherVersion is not optional --- GRDB/Core/Database+SQLCipher.swift | 6 +++--- Tests/GRDBTests/EncryptionTests.swift | 7 ++----- Tests/SPM/sqlcipher/sqlcipher/ContentView.swift | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/GRDB/Core/Database+SQLCipher.swift b/GRDB/Core/Database+SQLCipher.swift index 76e44f7152..fa031d6259 100644 --- a/GRDB/Core/Database+SQLCipher.swift +++ b/GRDB/Core/Database+SQLCipher.swift @@ -19,8 +19,8 @@ extension Database { /// - Returns: the SQLCipher version /// /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_version - public var cipherVersion: String? { - get throws { try String.fetchOne(self, sql: "PRAGMA cipher_version") } + public var cipherVersion: String { + get throws { try String.fetchOne(self, sql: "PRAGMA cipher_version")! } } /// - Returns: the SQLCipher fips status: 1 for fips mode, 0 for non-fips mode @@ -167,7 +167,7 @@ extension Database { // > applications institute a runtime test to ensure that the // > application is actually using SQLCipher on the active // > connection. - if try cipherVersion == nil { + if try String.fetchOne(self, sql: "PRAGMA cipher_version") == nil { throw DatabaseError(resultCode: .SQLITE_MISUSE, message: """ GRDB is not linked against SQLCipher. \ Check https://discuss.zetetic.net/t/important-advisory-sqlcipher-with-xcode-8-and-new-sdks/1688 diff --git a/Tests/GRDBTests/EncryptionTests.swift b/Tests/GRDBTests/EncryptionTests.swift index 87cbbcb1e9..b101d3ebd5 100644 --- a/Tests/GRDBTests/EncryptionTests.swift +++ b/Tests/GRDBTests/EncryptionTests.swift @@ -736,7 +736,7 @@ let testBundle = Bundle(for: GRDBTestCase.self) func testCipherVersion() throws { try DatabaseQueue().inDatabase { db in - XCTAssertNotNil(try db.cipherVersion, "SQLCipher not properly loaded") + _ = try db.cipherVersion } } @@ -768,10 +768,7 @@ let testBundle = Bundle(for: GRDBTestCase.self) try db.usePassphrase("secret") } let dbQueue = try makeDatabaseQueue(configuration: config) - guard let cipherVersion = try dbQueue.read({ try $0.cipherVersion }) else { - XCTFail("No Cipher Version found") - return - } + let cipherVersion = try dbQueue.read { try $0.cipherVersion } if "4.10.0".compare(cipherVersion, options: .numeric) == .orderedDescending { throw XCTSkip("cipher_provider_version isn't available until SQLCipher 4.10.0") } diff --git a/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift index aadbfb1a67..6aaaccf97c 100644 --- a/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift +++ b/Tests/SPM/sqlcipher/sqlcipher/ContentView.swift @@ -10,7 +10,7 @@ struct ContentView: View { } private var cipherVersion: String { - try! DatabaseQueue().read { try $0.cipherVersion ?? "Not SQLCipher" } + try! DatabaseQueue().read { try $0.cipherVersion } } } From 4dfe014c03982aa478d7f4fe25dc3b4d3ce633a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:30:14 +0200 Subject: [PATCH 13/17] Rename SQLCipherConfig to GRDBSQLCipher --- GRDB/Core/Database.swift | 2 +- Package.swift | 4 ++-- Sources/{SQLCipherConfig => GRDBSQLCipher}/SQLCipher_config.c | 0 .../include/SQLCipher_config.h | 0 .../include/module.modulemap | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename Sources/{SQLCipherConfig => GRDBSQLCipher}/SQLCipher_config.c (100%) rename Sources/{SQLCipherConfig => GRDBSQLCipher}/include/SQLCipher_config.h (100%) rename Sources/{SQLCipherConfig => GRDBSQLCipher}/include/module.modulemap (65%) diff --git a/GRDB/Core/Database.swift b/GRDB/Core/Database.swift index 628a1f6036..010cf284b6 100644 --- a/GRDB/Core/Database.swift +++ b/GRDB/Core/Database.swift @@ -6,7 +6,7 @@ import SQLite3 #elseif GRDBCUSTOMSQLITE // GRDBCustom Framework #elseif SQLCipher import SQLCipher -import SQLCipherConfig +import GRDBSQLCipher #else // Default SPM trait must be the default. It impossible to detect from Xcode. import GRDBSQLite #endif diff --git a/Package.swift b/Package.swift index a1bf71f952..435a4b575e 100644 --- a/Package.swift +++ b/Package.swift @@ -79,7 +79,7 @@ let package = Package( name: "GRDBSQLite", providers: [.apt(["libsqlite3-dev"])]), .target( - name: "SQLCipherConfig", + name: "GRDBSQLCipher", dependencies: [.product(name: "SQLCipher", package: "SQLCipher.swift")] ), .target( @@ -88,7 +88,7 @@ let package = Package( .target(name: "GRDBSQLite", condition: .when(traits: ["GRDBSQLite"])), .product(name: "SQLCipher", package: "SQLCipher.swift", condition: sqlcipherTraitTargetCondition), .target( - name: "SQLCipherConfig", + name: "GRDBSQLCipher", condition: sqlcipherTraitTargetCondition ) ], diff --git a/Sources/SQLCipherConfig/SQLCipher_config.c b/Sources/GRDBSQLCipher/SQLCipher_config.c similarity index 100% rename from Sources/SQLCipherConfig/SQLCipher_config.c rename to Sources/GRDBSQLCipher/SQLCipher_config.c diff --git a/Sources/SQLCipherConfig/include/SQLCipher_config.h b/Sources/GRDBSQLCipher/include/SQLCipher_config.h similarity index 100% rename from Sources/SQLCipherConfig/include/SQLCipher_config.h rename to Sources/GRDBSQLCipher/include/SQLCipher_config.h diff --git a/Sources/SQLCipherConfig/include/module.modulemap b/Sources/GRDBSQLCipher/include/module.modulemap similarity index 65% rename from Sources/SQLCipherConfig/include/module.modulemap rename to Sources/GRDBSQLCipher/include/module.modulemap index 84e0f46ba5..9dc826c40b 100644 --- a/Sources/SQLCipherConfig/include/module.modulemap +++ b/Sources/GRDBSQLCipher/include/module.modulemap @@ -1,4 +1,4 @@ -module SQLCipherConfig { +module GRDBSQLCipher { header "SQLCipher_config.h" export * } From ece9f9ef0a0eacaf6f667c207405a4dd697a8204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:35:45 +0200 Subject: [PATCH 14/17] Duplicate the SQLCipher3 test database --- Package.swift | 2 +- Tests/GRDBTests/db.SQLCipher3 | Bin 0 -> 2048 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 Tests/GRDBTests/db.SQLCipher3 diff --git a/Package.swift b/Package.swift index 435a4b575e..77978ecf6c 100644 --- a/Package.swift +++ b/Package.swift @@ -118,7 +118,7 @@ let package = Package( .copy("GRDBTests/Betty.jpeg"), .copy("GRDBTests/InflectionsTests.json"), .copy("GRDBTests/Issue1383.sqlite"), - .copy("CocoaPods/SQLCipher4/db.SQLCipher3") + .copy("GRDBTests/db.SQLCipher3") ], cSettings: cSettings, swiftSettings: swiftSettings + [ diff --git a/Tests/GRDBTests/db.SQLCipher3 b/Tests/GRDBTests/db.SQLCipher3 new file mode 100644 index 0000000000000000000000000000000000000000..6a6fed7db1acfb5e3f453bf23fb3c35faceb9950 GIT binary patch literal 2048 zcmV+b2>i(86Gn(RFGoV1|jfIn;q)MGsS^2P%!DcZS1J#T++vo@~=JFoea|%)g zz$H?3-o@Z}I@VYXA!}M*cqxsC+hXV;DI0>^<#d+fc27VF=XWR#1*m@vC-C#TMH*&~ zg?IZlm)g1p#jD0rq|9}b7k1KkFK%~LqTNWzvYX6E4BO^0k4id*z^x%z;W#sIXkcb8 zW4w&i`JEI_H84tg3{>)bht!P`?wAMP{-5R*<9KYFy~3b>g@U1*?f&EuM7C=vigOHo zjVemIKiG#~Kq92llUqni57VllG7n%)UI2mVv^ygoP!u%n=?@3>csz-%r& zuSHn`TOMT2gCHCx{_KiBkYsx=Ei_NNNm;+wO(&IJP0zMXkHvdu7q3+EN^85mlET7V^E?bNGN=6i&hf>^gg}Pp0t)J~tLszdtMnJCtJ@eM@ahJ!- z%P;Oo7OT3-=;z!cde@J|!w`P81!-}ViL%|u*6OJ%?~fMjH0&MOiVbq@d_ znO$la9Xcol_-07kfXV{-_kToSy0U&hkl8OF-}cb@JSF3#9elI)Vn+ezLg{V5uO6Z` zCVplk?h(Om^kvf@R%ZQ4cW&N~t19i(lFH;XJ5&F8ZId*yM+niG*)F9+rh8yobrB!_ z@}Lug!I|*tu%>cFdyYb&LNAHO^6M?VUJyMl57jIqd#Ttr@)%_{V6_h$0-znL`7Ex>1imNQsavV0}-K~vMaz9+Qz1xaG%;(^dU z1Lnxak@O(%y7S3V$BuSH?p>lVyOY!!HtEqL#nxp~d15F*>;*bjG@YX4)ie|}5y3!e($|M)<(LU>AVqOid|oI5`eh|YF7M>L5_}xh{fjuFu`n!zXPifW)s@B- zHwjA41j%UnXxJ@)=5E4Sgu?|mH>kvpmK6gf-~)no~>JxrLe0`G{5-Qse1VUBV$WRi-6* zT<2wk3Pfptuy5}&2v;rRg}#dN0X8tNsY#0~tUXC^N{XmwN*q$Gh_AJ^#G*xwwCwr( z`p`}t=prz}0`l-{2EKOJqW4Zcz9Jd*iZ;<73G{Cy9^TQNiVSq!qeqvrY@c6HVx+El zwORy^WR)tHI;Ey%GlJKdfZ+$ZsI`DszMA0SdNdkkRd)E1)6O|`%`^HGRg&5zx97XwFCKw z2JgSUDj^yxL_wWM!$_Wz8tcD5FTKt6*SX)0AHIh~{S5}Ba6RpmlHgN&_R8#9t8M9Do z)vmPWVwC@;MMeO0q?ogQ*tKGNB2sG_`~!ZUP&{3EA#Aq(LU&_vo-p z<0FEd{)I+#PQUCW`l>U;fk;b6`H3*G2+{_;)IQ_%g#6Ymli&IP*?Fk~O6QpVc~%Bo ze(do_!q4&Nhi}g_u9_M*sZT=ajQP)xkH4tFDb#jMB0G6brUFxGuVrLBnwf{0QrC`h7c_a^x5;fTjJ`00wi zAnxkup-1-~MG-bDPfqb~lqRz)x+ArVn5;DycZjCdWu47Dy%?(Eb2fxPnM@}PN6Uel z0JR$_KLXB`3$$0)v&I$s<8!-@b4yd=mfNUEFxF_Xbp5Hv_94Ju(@O{&{bj)B2 zq{VRT2xju8LM9H?Je!!cdEP}^!yZ{vc!>vLFMNSgt07EIYB8a^_d;JCTp!%tL8)Dx z?BMJsyIck=81DLSlJXRG_9i?)yP@Ntsk~Xtt`b%v#-%wP!e_0z1Mwk*X-%#M@C2v{ z#tjQ0*uWn}4LQvmU?9`E{RM^fiS>HkDh;_gJ{k?xYz5_ue%C|^kd2Eg>w>~mQA(K2 z@SkuoVJ5vqfEG6y_$qzci z5+Of<=9iiupT)Jmn~XHZ-&=4ieK4)2=N>P-nYs>kxu2YTUDYBp;)ggm$za6SyG;a8 e+*a39!ZRbkg`I|Pg@^rq$>-rPCym=f{@&un|L{Ek literal 0 HcmV?d00001 From 988fcfad243f25fc0a53d2fcba0ba8821614a471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Wed, 15 Oct 2025 19:45:40 +0200 Subject: [PATCH 15/17] Delete ignored file --- .../xcshareddata/swiftpm/Package.resolved | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 Tests/Performance/GRDBPerformance/GRDBPerformance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/Tests/Performance/GRDBPerformance/GRDBPerformance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Tests/Performance/GRDBPerformance/GRDBPerformance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 95d315f336..0000000000 --- a/Tests/Performance/GRDBPerformance/GRDBPerformance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,42 +0,0 @@ -{ - "originHash" : "8d182a38fc35b0d50c198e0cbd39dc7fa5922eae5336ff3b0c73c2d51bcba752", - "pins" : [ - { - "identity" : "fmdb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ccgus/fmdb.git", - "state" : { - "revision" : "1227a3fa2b9916bfd75fe380eb45cd210e69e251", - "version" : "2.7.12" - } - }, - { - "identity" : "realm-core", - "kind" : "remoteSourceControl", - "location" : "https://github.com/realm/realm-core.git", - "state" : { - "revision" : "15493076ad9fef22c16cc64cbfbf9e5b65c385f9", - "version" : "20.1.0" - } - }, - { - "identity" : "realm-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/realm/realm-swift.git", - "state" : { - "revision" : "bae6c4be7df169fdb047d0ad63f902c1e2665e83", - "version" : "20.0.1" - } - }, - { - "identity" : "sqlite.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/stephencelis/SQLite.swift.git", - "state" : { - "revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8", - "version" : "0.15.3" - } - } - ], - "version" : 3 -} From c7b4ac507d0c82d181ea06005ac8a381a6e9913d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Fri, 17 Oct 2025 08:09:39 +0200 Subject: [PATCH 16/17] Support SQLCipher 4.11+ --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 77978ecf6c..6f3e165013 100644 --- a/Package.swift +++ b/Package.swift @@ -34,7 +34,7 @@ var cSettings: [CSetting] = [ ] var dependencies: [PackageDescription.Package.Dependency] = [ - .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", exact: "4.11.0") + .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.11.0") ] // Don't rely on those environment variables. They are ONLY testing conveniences: From 4683362cf87e14a09ea13a581d2be694f6d5e614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Sat, 18 Oct 2025 11:32:34 +0200 Subject: [PATCH 17/17] Remove Swiftlint rules that warn against our new SQLite import boilerplate --- Scripts/swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/swiftlint.yml b/Scripts/swiftlint.yml index c8a223f0b8..6f6b7cdbd9 100644 --- a/Scripts/swiftlint.yml +++ b/Scripts/swiftlint.yml @@ -5,6 +5,7 @@ disabled_rules: - comment_spacing - cyclomatic_complexity - duplicate_enum_cases + - duplicate_imports - file_length - for_where - force_cast @@ -62,7 +63,6 @@ opt_in_rules: - redundant_type_annotation - shorthand_optional_binding - sorted_first_last - - sorted_imports - toggle_bool - unhandled_throwing_task - vertical_parameter_alignment_on_call