GRDB.swift: Queries fail with SQLCipher 3, but only in release mode

What did you do?

I recently migrated a project from GRDBCipher 3 to 4. I wanted to keep using SQLCipher 3 for now to avoid having to deal with conversions and compatibility modes, so I made the following change (which according to the docs is a supported configuration):

-    pod 'GRDBCipher', '3.3.1'
+    pod 'GRDB.swift/SQLCipher', '4.5.0'
+    pod 'SQLCipher', '3.4.2'

After I made the necessary code changes everything looked good when running locally, but when I deployed the build to TestFlight and installed it on a few devices I noticed that all SELECT queries were failing with this error:

SQLite error 7 with statement `SELECT rowid, json FROM task`: not an error

This particular query happens to be the first SELECT I do in one of the migration steps after creating the tables. The same error happens in other queries even if I’m using an existing database that was created/migrated with the previous GRDBCipher version.

As I mentioned before, this happens only in release builds (TestFlight or ad-hoc), while local builds running through Xcode (simulator or device) work fine.

What did you expect to happen?

Queries should work as before.

What happened instead?

All queries throw the mentioned error

Environment

GRDB flavor(s): GRDB.swift/SQLCipher 4.5.0 and SQLCipher 3.4.2 Installation method: Cocoapods Xcode version: 11.1 (11A1027) Swift version: 5.1 Platform(s) running GRDB: iOS macOS version running Xcode: 10.14.6 (18G103)

Demo Project

Unfortunately, it’s a bit tricky to come up with a demo project since the error only happens in release builds.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 18 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Hello @MrShafiee. This ticket is closed. Nobody works on it. Firebase comes with SQLite, and SQLite conflicts with SQLCipher. And GRDB can’t much about it. Ask Firebase how to use it with your build of SQLCipher, maybe?

Hey @MrShafiee, at some point my code started breaking in different non-deterministic ways even with the “workarounds” I previously posted here. The only sure-fire way to get rid of the issue was to add this to my podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    # Loop through the targets and remove explicit linking to the system SQLite framework. We do
    # that because SQLCipher embeds a copy of SQLite, and using both at the same time can cause
    # weird crashes. This will just force all dependencies to use the embedded one.
    target.build_configurations.each do |config|
      if (config != nil && config.base_configuration_reference != nil)
        xcconfig_path = config.base_configuration_reference.real_path
        xcconfig = File.read(xcconfig_path)
        new_xcconfig = xcconfig.sub('-l"sqlite3"', '')
        File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
      end
    end
  end
end

I never had time to raise an issue with Firebase, but I’m not sure if they’d be able to do something.

@groue I finally had some more time to play with this issue today, and I think I figured out a way to make your sample app crash in the same way as mine. Can you please try adding these lines inside the migration block (AppDelegate.swift:35):

let rows = try Row.fetchCursor(db, sql: "SELECT * FROM player")
while let row = try rows.next() {
}

It looks like the call to RowCursor.next inside a migration block somehow triggers this error. My assumption about the app group container having something to do with it was a red herring, the issue will happen regardless of the location of the database file.

Once the code is in that state, any of these following actions will get rid of the crash:

  • Removing the Firebase/Analytics pod
  • Replacing the cursor iteration with Row.fetchAll
  • Removing the @inlinable attribute from RowCursor.next

Upgrading Firebase to the latest version available also had no effect.

Yeah, sorry for the trouble, I ended up deleting my comment, but not soon enough.