-
Can't finds docs or examples about this use case so asking here - if I do:
Does it only observe 0-100 rows? If I lazily increase my load to add 101-200, 201-300, how to properly observe them as well? Additionally, when I observe 0-100 and insert 1 row at 0, does that mean the observed value becomes the new row + original 0-99 and the old 100th is ignored? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Hello @hyouuu,
You can't use The doc does not indeed provide a self-contained description of "what is observed, exactly?". There is a beginning of a description in ValueObservation Performance:
The
I understand that it is not trivial to group those descriptions in a single idea. Also, there is this "rowid" word that is not known by everyone (SQLite doc: Rowid Tables). Key to the understanding is the fact that GRDB does not observe. Instead, SQLite notifies changes. To understand how SQLite is the only major player in the picture, consider that database observation works just as well for people who write raw SQL by hand. GRDB plays no role here, because GRDB does not parse SQL (it is hard, and the SQL grammar evolves with SQLite versions, meaning that parsing SQL creates a maintenance burden - it's not in anyone's interest for GRDB to start parsing SQL): // Observation setup: raw SQL is just fine.
let notesObservation = ValueObservation.tracking { db in
try Note.fetchAll(db, sql: "SELECT * FROM notes LIMIT 100")
}
// Some changes that trigger the observation. Again, raw SQL is welcome.
try dbQueue.write { db in
try db.execute(sql: """
-- May impact the 100 first notes
INSERT INTO note VALUES (...);
-- May impact the 100 first notes
UPDATE note SET ... = ... WHERE ...;
-- May impact the 100 first notes
DELETE FROM note WHERE ...;
-- May impact the 100 first notes, if there is a foreign key
-- from noteOwner to note that deletes notes when their
-- owner is deleted.
DELETE FROM noteOwner WHERE ...;
""")
} Observation is thus entirely driven by SQLite Data Change Notification Callbacks, which notify individual insertions, updates, and deletions, and are totally unaware that your app is interested in the first 100 notes (or the maximum player score, or whatever). GRDB does something, of course. Is is akin to "since the application performs an observation, I must trigger a refresh whenever SQLite notifies a change that may have an impact on the fetched values, in order to make sure that 1. the app never misses a change, 2. people keep on trusting the library, and 3. the GRDB GitHub repository is not flooded with bug reports":
To understand why the limit is ignored, why we don't care about the exact list of 100 notes, consider that this information is not useful:
Since the observed region is the full database table, it considers that any inserted, updated, or deleted note must trigger a refresh. Changes in notes that are beyond the first 100 will trigger a refresh (and notify the same previous list of 100 notes). As the ValueObservation documentation says: "ValueObservation may notify consecutive identical values."
The observed region does not change: it remains the full list of notes. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the thorough explanation @groue ! A quick follow up: Although any change in the table triggers the observation callback, the callback only returns the first 100 notes (if I understand correctly). For my use case where I increasingly query for 0-100, 101-200, 201-300, do I need to keep 3 observations in order to get the changes properly? Or should I change it so that initially it queries for 0-100, then increase it to 0-200 and cancel the original observation? |
Beta Was this translation helpful? Give feedback.
Hello @hyouuu,
You can't use
ValueObservation.tracking
improperly. 😉The doc does not indeed provide a self-contained description of "what is observed, exactly?".
There is a beginning of a description in ValueObservation Performance: