Skip to content

Latest commit

 

History

History
259 lines (240 loc) · 17 KB

TODO.md

File metadata and controls

259 lines (240 loc) · 17 KB

Cleanup

Documentation

  • Enhance the introduction to SQLRequest, based on the feedback in #617
  • Association: document how to use aggregates with inner join (testAnnotatedWithHasManyDefaultMaxJoiningRequired)
  • Should we document that PRAGMA locking_mode = EXCLUSIVE improves performances? https://sqlite.org/forum/forumpost/866bf3407a

Features

  • Detect when ColumnExpression.noOverwrite excludes a non-existing column. Code is in DOA.upsertStatement()`. We should not silently ignore non-existing columns, as demonstrated by #1539.

  • Can Swift 5.5 help us with select(.all) (request of RowDecoder), select(.id) (request of RowDecoder.ID), select(.rowid) (request of Int64)?

  • Direct access to statement for bindings

  • Property wrapper that decodes dictionaries (but how to tell the key column?)

  • See if SQLITE_FCNTL_DATA_VERSION could help working around the lack of snapshots in order to avoid double initial fetch of ValueObservation. Result: no, it does not look it returns values that are comparable between two distinct SQLite connections (from the initial reader, and from the writer thhat starts the observation)

  • Grab all FTS tokens in a string

  • [NO] Can we generate EXISTS with association? Team.annotated(with: Team.players.exists) No. We already have Team.annotated(with: Team.players.isEmpty == false). It does not use an EXISTS expression, but a JOIN, and this is better for the internal consistency of the query interface, and the rules that deal with association keys.

  • GRDB 6: have DatabaseRegionObservation produce DatabaseCancellable just as ValueObservation.

  • RangeReplaceableCollection should have append(contentsOf: cursor)

  • GRDB 6: choose persistence table

  • GRDB 6: decoding errors

    • throwing FetchableRecord initializer FIRST
    • throwing Decodable FetchableRecord initializer SECOND
    • deal with as much value decoding error as possible
    • [?] expose throwing row accessors
  • GRDB 6: Batch insert & Batch insert RETURNING - https://stackoverflow.com/questions/1609637/is-it-possible-to-insert-multiple-rows-at-a-time-in-an-sqlite-database

  • GRDB 6: INSERT or UPDATE columns to their default value

  • GRDB 6: afterNextTransactionCommit -> afterNextTransaction(onCommit:onRollback:)

  • GRDB 6: encoding errors for record (EncodableRecord.encode(to:))

    • throwing EncodableRecord.encode FIRST
  • [?] GRDB 6: protocol-based record container? This could avoid computing & encoding values we do not need.

  • GRDB 6: encoding & statement binding errors for database values (conversion to DatabaseValue, statement binding, etc)

    • Prevent Date > 9999 from being encoded
  • GRDB 6: Swift 5.7

  • GRDB 6: any / some

  • GRDB 6: primary associated types (cursor, requests, ...)

  • GRDB 6: remove existential/generic duplicated methods

  • GRDB 6: remove useless AnyXXX Type erasers

  • GRDB 6: conflict resolution in persistence methods

  • GRDB 6: UPSERT

  • GRDB 6: support for RETURNING

    • Support for default values: Player.insert(db, as: FullPlayer.self)
  • [?] GRDB 6: allow mutating update (for timestamps)

  • [?] GRDB 6: let record choose persistence table (insert(into:) ?)

  • [?] GRDB 6: Support opaque return types (macOS Catalina, iOS 13, tvOS 13, watchOS 6 and later: https://stackoverflow.com/questions/56518406)

  • Long run edition. Use case: user edits the database (CRUD) but the application wants to commit and the end of the editing session.

    • Create an edition SQLite connection with an open transaction (a new kind of DatabaseWriter with a save() method)
    • All other writes will fail with SQLITE_BUSY. Unless they are schedules in a target dispatch queue which is paused during the edition.
  • Can we use generated columns to makes it convenient to index on inserted JSON objects? swiftlang/swift-package-manager#3090 (comment)

  • Look at @FetchRequest: managed object context is stored in the environment, and error processing happens somewhere else (where?).

  • Handle SQLITE_LIMIT_VARIABLE_NUMBER in deleteAll(_:keys:) and similar APIs. https://www.sqlite.org/limits.html

  • Subqueries: request.isEmpty / [X] request.exists()

  • Subqueries: request.count

  • Extract one row from a hasMany association (the one with the maximum date, the one with a flag set, etc.) https://stackoverflow.com/questions/43188771/sqlite-join-query-most-recent-posts-by-each-user (failed PR: #767)

  • Turn a hasMany to hasOne without first/last : hasMany(Book.self).filter(Column("isBest") /* assume a single book is flagged best */).asOne()

  • Support for more kinds of joins: #740

  • HasAndBelongsToMany: #711

  • Support UNION #671 (https://www.sqlite.org/lang_select.html#compound)

  • Measure the duration of transactions

  • Improve SQL generation for Player.....fetchCount(db), especially with distinct. Try to avoid SELECT COUNT(*) FROM (SELECT DISTINCT player.* ...)

  • Alternative technique for custom SQLite builds: see the Podfile at CocoaPods/CocoaPods#9104, and https://github.com/clemensg/sqlite3pod

  • Attach databases. Interesting question: what happens when one attaches a non-WAL db to a databasePool?

  • SQL Generation

  • Allow concurrent reads from a snapshot

  • Check https://sqlite.org/sqlar.html

  • More schema alterations

  • Database.clearSchemaCache() is fine, but what about dbPool readers? Can we invalidate the cache for a whole pool?

  • What can we do with cross-module-optimization? See https://github.com/apple/swift-homomorphic-encryption

  • GRDB7/BREAKING: insertAndFetch, saveAndFetch, and updateAndFetch no longer return optionals (32f41472)

  • GRDB7/BREAKING: AsyncValueObservation does not need any scheduler (83c0e643)

  • GRDB7/BREAKING: Stop exporting SQLite (679d6463)

  • GRDB7/BREAKING: Remove Configuration.defaultTransactionKind (2661ff46)

  • GRDB7: Replace LockedBox with Mutex (00ccab06)

  • GRDB7: Sendable: BusyCallback (e0d8e20b)

  • GRDB7: Sendable: BusyMode (e0d8e20b)

  • GRDB7: Sendable: TransactionClock (f7dc72a5)

  • GRDB7: Sendable: Configuration (54ffb21f)

  • GRDB7: Sendable: DatabaseDataEncodingStrategy (264d7fb5)

  • GRDB7: Sendable: DatabaseDateEncodingStrategy (264d7fb5)

  • GRDB7: Sendable: DatabaseColumnEncodingStrategy (264d7fb5)

  • GRDB7: Sendable: DatabaseDataDecodingStrategy (264d7fb5)

  • GRDB7: Sendable: DatabaseDateDecodingStrategy (264d7fb5)

  • GRDB7: Sendable: DatabaseColumnDecodingStrategy (264d7fb5)

  • GRDB7/BREAKING: Remove DatabaseFuture and concurrentRead (05f7d3c8)

  • GRDB7: Sendable: DatabaseFunction (6e691fe7)

  • GRDB7: Sendable: DatabaseMigrator (22114ad4)

  • GRDB7: Not Sendable: FilterCursor (b26e9709)

  • GRDB7: Sendable: RowAdapter (d138af26)

  • GRDB7: Sendable: ValueObservationScheduler (8429eb68)

  • GRDB7: Sendable: DatabaseCollation (4d9d67dd)

  • GRDB7: Sendable: LogErrorFunction (f362518d)

  • GRDB7: Sendable: ReadWriteBox (57a86a0e)

  • GRDB7: Sendable: Pool (f13b2d2e)

  • GRDB7: Sendable: OnDemandFuture fulfill (2aabc4c1)

  • GRDB7: Sendable: WALSnapshotTransaction (7fd34012)

  • [-] GRDB7: sending closures for SerializedDatabase

  • [-] GRDB7: sending closures for ValueObservationScheduler

  • GRDB7: Sendable closures for ValueObservation.handleEvents

  • GRDB7: Not Sendable: Record (make it explicit if subclasses can be made sendable)

  • GRDB7: Not Sendable: databasepublishers/databaseregion, migrate, read, value, write

  • GRDB7: Sendable closures for writePublisher

  • GRDB7: Sendable closures for readPublisher

  • [-] GRDB7: Not Sendable: fts5customtokenizer, fts5tokenizer, fts5wrappertokenizer

  • GRDB7: Sendable: DatabasePromise (05899228, 5a2c15b8)

  • GRDB7: Sendable: TableAlias (f2b0b186)

  • GRDB7: Sendable: SQLRelation (9545bf70)

  • GRDB7: Sendable: SQL (ac33856f)

  • GRDB7: Split Row.swift (2ce8a619)

  • GRDB7: Cleanup ValueReducer (6c73b1c5)

  • GRDB7: DatabaseCursor has a primary associated type (b11c5dd2)

  • GRDB7: Enable Strict Concurrency Checks (6aa43ded)

  • GRDB7: Sendable: OrderedDictionary (e022c35b)

  • GRDB7: Rename ReadWriteBox to ReadWriteLock (7f5205ef)

  • GRDB7: Sendable: DatabaseRegionConvertible (b4677ded)

  • GRDB7: Sendable: ValueConcurrentObserver (87b9db65, 5465d056)

  • GRDB7: Sendable: ValueWriteOnlyObserver (ff2a7548)

  • GRDB7: Sendable: DatabaseCancellable (2f93f00b, 8f486a5e)

  • GRDB7: ValueObservation closures

  • [?] GRDB7: DatabasePublishers.ValueSubscription

  • GRDB7: Sendable: ValueObservation (93f6f982)

  • [?] GRDB7: Not Sendable: SharedValueObservation

  • GRDB7: doc (c0838cf9)

  • GRDB7/BREAKING: PersistenceContainer is Sendable (50eefa8c)

  • GRDB7: TableRecord.databaseSelection must be declared as a computed property (24d232aa)

    • Doc
    • Migration Guide
  • GRDB7: Sendable: Association (b06aaee4)

  • GRDB7/Tests: Sendable: ValueObservationRecorder (2947b3d7)

  • GRDB7: ValueObservation.print cautiously uses its stream argument (5f8b39b7)

  • GRDB7/Tests: use a single and Sendable test TextOutputStream (bbb1a736)

  • GRDB7: ValueObservation needs a ValueReducer, not a _ValueReducer (08733108)

  • GRDB7: Database support for cancellation (4ddf4bca)

  • GRDB7: SerializedDatabase support for async db access with support for Task cancellation (737cb149)

  • GRDB7: DatabaseWriter async methods support Task cancellation (a5226501)

  • GRDB7: DatabaseReader async methods support Task cancellation (10c9d311)

  • GRDB7: Document that async methods can throw CancellationError (8df18fb8)

  • [-] GRDB7: Sendable: AssociationAggregate (48ad10ae)

  • GRDB7: Sendable: AsyncValueObservation (necessary for async algorithm) (ce63cdfa)

  • GRDB7: Sendable: DatabaseRegionObservation (b4ff52fb)

  • [-] GRDB7: DispatchQueue.asyncSending (7b075e6b)

  • GRDB7: Replace sequences with collection (e.g. tidal-music/tidal-sdk-ios#39)

  • GRDB7: Replace some DatabaseReader/Writer with any where possible, in order to avoid issues with accessing DatabaseContext from GRDBQuery (if the problem exists in Xcode 16)

  • GRDB7: bump to iOS 13, macOS 10.15, tvOS 13 (for ValueObservation support for MainActor)

  • GRDB7: DatabasePublishers.Value should carry the type of the Scheduler, so that we can rely on main-actor-isolated callbacks.

  • GRDB7: Remove warning about "products" in Package.swift

  • GRDB7: Fixits

    • defaultTransactionKind
    • concurrentRead
  • GRDB7: Swift Concurrency recommendations

    • Record classe(s)
    • InferSendableFromCaptures
  • GRDB7: stop fostering the Record class

    • Remove all mentions from the README
    • Warn about it in the documentation of the class.
  • GRDB7: Breaking changes documentation

    • [BREAKING] Xcode 16+, Swift 6+
    • [BREAKING] iOS 13+
    • [BREAKING] macOS 10.15+
    • [BREAKING] tvOS 13+
    • [BREAKING] watchOS 7+
    • [-] insertAndFetch, updateAndFetch, saveAndFetch
    • CSQLite renamed to GRDBCSQLite
    • CSQLite is not exported
    • defaultTransactionKind
    • concurrentRead
    • record column strategies:
      • databaseDataEncodingStrategy
      • databaseDateEncodingStrategy
      • databaseUUIDEncodingStrategy
      • databaseDataDecodingStrategy
      • databaseDateDecodingStrategy
    • PersistenceContainer subscript no longer returns its input value
    • cancellation of async database access
    • Async sequences built from ValueObservation schedule values and errors on the cooperative thread pool by default.
    • TableRecord.databaseSelection should be declared as a computed static property
    • [-] databaseDecodingUserInfo and databaseEncodingUserInfo must be declared as a computed property
  • GRDB7: Review experimental apis

  • [?] GRDB7: Change ValueObservation callback argument so that it could expose snapshots? #1523 (reply in thread)

Unsure if necessary

Unsure how

  • Association limits: Author.including(optional: Author.books.order(date.desc).first)

  • Joins and full-text tables

  • UPSERT https://www.sqlite.org/lang_UPSERT.html

  • Support for "INSERT INTO ... SELECT ...".

  • Look at the jazzy configuration of https://github.com/bignerdranch/Deferred

  • Predicates, so that a filter can be evaluated both on the database, and on a record instance.

    After investigation, we can't do it reliably without knowing the collation used by a column. And SQLite does not provide this information elsewhere than in the full CREATE TABLE statement stored in sqlite_master.

  • ValueObservation erasure

    // Do better than this
    observation.mapReducer { _, reducer in AnyValueReducer(reducer) }
    
  • new.updateChanges(from: old) vs. old.updateChanges(with: { old.a = new.a }). This is confusing.

Reading list