WatermelonDB v0.24 Release Notes
Release Date: 2021-10-28 // about 3 years ago-
๐ฅ BREAKING CHANGES
Q.experimentalSortBy
,Q.experimentalSkip
,Q.experimentalTake
have been renamed toQ.sortBy
,Q.skip
,Q.take
respectively- โก๏ธ RxJS has been updated to 7.3.0. If you're not importing from
rxjs
in your app, this doesn't apply to you. If you are, read RxJS 7 breaking changes: https://rxjs.dev/deprecations/breaking-changes
๐ New features
- LocalStorage.
database.localStorage
is now available - sortBy, skip, take are now available in LokiJSAdapter as well
- Disposable records. Read-only records that cannot be saved in the database, updated, or deleted and only exist for as long as you keep a reference to them in memory can now be created using
collection.disposableFromDirtyRaw()
. This is useful when you're adding online-only features to an otherwise offline-first app. - ๐ [Sync]
experimentalRejectedIds
parameter now available in push response to allow partial rejection of an otherwise successful sync
๐ Fixes
- ๐ Fixes an issue when using Headless JS on Android with JSI mode enabled - pass
usesExclusiveLocking: true
to SQLiteAdapter to enable - ๐ Fixes Typescript annotations for Collection and adapters/sqlite
Previous changes from v0.23
-
๐ This is a big release to WatermelonDB with new advanced features, great performance improvements, and important fixes to JSI on Android.
โฌ๏ธ Please don't get scared off the long list of breaking changes - they are all either simple Find&Replace renames or changes to internals you probably don't use. It shouldn't take you more than 15 minutes to upgrade to 0.23.
๐ฅ BREAKING CHANGES
- iOS Installation change. You need to add this line to your Podfile:
pod 'simdjson', path: '../node_modules/@nozbe/simdjson'
- ๐ Deprecated
new Database({ actionsEnabled: false })
options is now removed. Actions are always enabled. - ๐ Deprecated
new SQLiteAdapter({ synchronous: true })
option is now removed. Use{ jsi: true }
instead. - ๐ Deprecated
Q.unsafeLokiFilter
is now removed. UseQ.unsafeLokiTransform((raws, loki) => raws.filter(raw => ...))
instead. - ๐ Deprecated
Query.hasJoins
is now removed - ๐ Changes to
LokiJSAdapter
constructor options:indexedDBSerializer
->extraIncrementalIDBOptions: { serializeChunk, deserializeChunk }
onIndexedDBFetchStart
->extraIncrementalIDBOptions: { onFetchStart }
onIndexedDBVersionChange
->extraIncrementalIDBOptions: { onversionchange }
autosave: false
->extraLokiOptions: { autosave: false }
- ๐ Changes to Internal APIs. These were never meant to be public, and so are unlikely to affect you:
Model._isCommited
,._hasPendingUpdate
,._hasPendingDelete
have been removed and changed toModel._pendingState
Collection.unsafeClearCache()
is no longer exposed
- Values passed to
adapter.setLocal()
are now validated to be strings. This is technically a bug fix, since local storage was always documented to only accept strings, however applications may have relied on this lack of validation. Adding this validation was necessary to achieve consistent behavior between SQLiteAdapter and LokiJSAdapter - ๐
unsafeSql
passed toappSchema
will now also be called when dropping and later recreating all database indices on large batches. A second argument was added so you can distinguish between these cases. See Schema docs for more details. - ๐ Changes to sync change tracking. The behavior of
record._raw._changed
andrecord._raw._status
(a.k.a.record.syncStatus
) has changed. This is unlikely to be a breaking change to you, unless you're writing your own sync engine or rely on these low-level details.- Previously, _changed was always empty when _status=created. Now, _changed is not populated during initial creation of a record, but a later update will add changed fields to _changed. This change was necessary to fix a long-standing Sync bug.
๐ Deprecations
- ๐
database.action(() => {})
is now deprecated. Usedb.write(() => {})
instead (ordb.read(() => {})
if you only need consistency but are not writing any changes to DB) - ๐
@action
is now deprecated. Use@writer
or@reader
instead - ๐
.subAction()
is now deprecated. Use.callReader()
or.callWriter()
instead - ๐
Collection.unsafeFetchRecordsWithSQL()
is now deprecated. Usecollection.query(Q.unsafeSqlQuery("select * from...")).fetch()
instead.
๐ New features
db.write(writer => { ... writer.batch() })
- you can now call batch on the interface passed to a writer block- Fetching record IDs and unsafe raws. You can now optimize fetching of queries that only require IDs, not full cached records:
await query.fetchIds()
will return an array of record idsawait query.unsafeFetchRaw()
will return an array of unsanitized, unsafe raw objects (use alongsideQ.unsafeSqlQuery
to exclude unnecessary or include extra columns)- advanced
adapter.queryIds()
,adapter.unsafeQueryRaw
are also available
- Raw SQL queries. New syntax for running unsafe raw SQL queries:
collection.query(Q.unsafeSqlQuery("select * from tasks where foo = ?", ['bar'])).fetch()
- You can now also run
.fetchCount()
,.fetchIds()
on SQL queries - You can now safely pass values for SQL placeholders by passing an array
- You can also observe an unsafe raw SQL query -- with some caveats! refer to documentation for more details
- Unsafe raw execute. You can now execute arbitrary SQL queries (SQLiteAdapter) or access Loki object directly (LokiJSAdapter) using
adapter.unsafeExecute
-- see docs for more details - Turbo Login. You can now speed up the initial (login) sync by up to 5.3x with Turbo Login. See Sync docs for more details.
- ๐จ New diagnostic tool - debugPrintChanges. See Sync documentation for more details
๐ Performance
- The order of Q. clauses in a query is now preserved - previously, the clauses could get rearranged and produce a suboptimal query
- โก๏ธ [SQLite]
adapter.batch()
with large numbers of created/updated/deleted records is now between 16-48% faster - [LokiJS] Querying and finding is now faster - unnecessary data copy is skipped
- [jsi] 15-30% faster querying on JSC (iOS) when the number of returned records is large
- [jsi] up to 52% faster batch creation (yes, that's on top of the improvement listed above!)
- ๐ Fixed a performance bug that caused observed items on a list observer with
.observeWithColumns()
to be unnecessarily re-rendered just before they were removed from the list
๐ Changes
- ๐ All Watermelon console logs are prepended with a ๐ tag
- Extra protections against improper use of writers/readers (formerly actions) have been added
- โ Queries with multiple top-level
Q.on('table', ...)
now produce a warning. UseQ.on('table', [condition1, condition2, ...])
syntax instead. - [jsi] WAL mode is now used
๐ Fixes
- [jsi] Fix a race condition where commands sent to the database right after instantiating SQLiteAdapter would fail
- [jsi] Fix incorrect error reporting on some sqlite errors
- [jsi] Fix issue where app would crash on Android/Hermes on reload
- [jsi] Fix IO errors on Android
- โก๏ธ [sync] Fixed a long-standing bug that would cause records that are created before a sync and updated during sync's push to lose their most recent changes on a subsequent sync
Internal
- Internal changes to SQLiteAdapter:
- .batch is no longer available on iOS implementation
- .batch/.batchJSON internal format has changed
- .getDeletedRecords, destroyDeletedRecords, setLocal, removeLocal is no longer available
- encoded SQLiteAdapter schema has changed
- LokiJSAdapter has had many internal changes
- iOS Installation change. You need to add this line to your Podfile: