2

I was wondering, does SQLite.swift have the capability, to detect & notify table data change? (Similar to what is offered by NSFetchedResultsController, to detect & notify entity data change)


For GRDB.swift, it offers the capability to observe table data change.

https://github.com/groue/GRDB.swift/blob/master/Documentation/DemoApps/GRDBDemoiOS/GRDBDemoiOS/ViewControllers/PlayerListViewController.swift#L98

private func configureDataSourceContent() {
    switch playerOrdering {
    case .byName:
        playersCancellable = AppDatabase.shared.observePlayersOrderedByName(
            onError: { error in fatalError("Unexpected error: \(error)") },
            onChange: { [weak self] players in
                guard let self = self else { return }
                self.updateDataSourceContent(with: players)
            })
    case .byScore:
        playersCancellable = AppDatabase.shared.observePlayersOrderedByScore(
            onError: { error in fatalError("Unexpected error: \(error)") },
            onChange: { [weak self] players in
                guard let self = self else { return }
                self.updateDataSourceContent(with: players)
            })
    }
}

SQLite itself does provide low level Data Change Notification Callbacks (https://www.sqlite.org/c3ref/update_hook.html).

Does SQLite.swift offer anything out of the box, by building on the top of sqlite3_update_hook? If not, is it possible for us to custom build such solution?

Thanks.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • 1
    GRDB has put **a lot** of efforts in making SQLite observation as easy as possible for applications. You can look at the GRDB source code and use the [various hooks exposed by SQLite.swift](https://github.com/stephencelis/SQLite.swift/blob/0.12.2/Sources/SQLite/Core/Connection.swift#L456-L531) in order to reproduce the same behavior. I do not think you'll find a ready-made answer. – Gwendal Roué Jan 01 '21 at 11:50
  • 1
    In a nutshell, GRDB uses 1. SQLite update, commit and rollback hooks in order to track the committed changes, 2. SQLite authorizer in order to track save points, so that rollbacked changes are not notified, 3. SQLite authorizer in order to know which tables and columns are involved in a tracked request, 4. SQLite authorizer in order to spot which statements have an opportunity to impact a tracked request, 5. SQLite WAL mode in order to efficiently fetch updated values after a tracked request has been impacted by a transaction, 6. A robust concurrency model that SQLite.swift lacks entirely. – Gwendal Roué Jan 01 '21 at 12:08
  • 1
    Maybe... you're just looking after GRDB, after all ;-) – Gwendal Roué Jan 01 '21 at 12:09

2 Answers2

0

Is this something that could be helpful?

SQift/hook.swift

From - SQift

nishith Singh
  • 2,968
  • 1
  • 15
  • 25
0

I believe, you are looking for this functionality (reproduced below for ready reference):

/// Registers a callback to be invoked whenever a row is inserted, updated,
    /// or deleted in a rowid table.
    ///
    /// - Parameter callback: A callback invoked with the `Operation` (one of
    ///   `.Insert`, `.Update`, or `.Delete`), database name, table name, and
    ///   rowid.
    public func updateHook(_ callback: ((_ operation: Operation, _ db: String, _ table: String, _ rowid: Int64) -> Void)?) {
        guard let callback = callback else {
            sqlite3_update_hook(handle, nil, nil)
            updateHook = nil
            return
        }

        let box: UpdateHook = {
            callback(
                Operation(rawValue: $0),
                String(cString: $1),
                String(cString: $2),
                $3
            )
        }
        sqlite3_update_hook(handle, { callback, operation, db, table, rowid in
            unsafeBitCast(callback, to: UpdateHook.self)(operation, db!, table!, rowid)
        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
        updateHook = box
    }
    fileprivate typealias UpdateHook = @convention(block) (Int32, UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> Void
    fileprivate var updateHook: UpdateHook?

However, there seems to be an attempt to include what you are looking for. Have a look at this SQLite.swift issue. This is from 2017 and may have evolved!

anurag
  • 1,715
  • 1
  • 8
  • 28