Differential watched queries ignore pure reorders (same rows, new ORDER BY) so stale order is served
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 83/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- sql, typescript
- Ambito
- backend-api-design, database
Direzione di ricerca
Inizia in packages/shared-internals/src/client/watched/DifferentialQueryProcessor.ts e segui come differentiate() imposta hasChanged durante la creazione di diff.all. Usa la riproduzione nell’issue per confermare che invertire le stesse righe attualmente non segnala alcuna modifica, quindi aggiungi un test di regressione per questo caso. Il lavoro è completato quando un semplice riordino segnala una modifica ed emette le righe nel loro nuovo ordine.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
DifferentialQueryProcessor.differentiate() reports hasChanged: false when a query returns the same rows in a different order (e.g. the user switches ORDER BY, or a watched query's sort parameter changes while the row set and row contents stay identical). Because nothing is emitted, useQuery / differential watched queries keep serving the previous order indefinitely, until some row is added, removed, or updated.
diff.all is already built in the new order (the code comments say looping over the current result set "is important to preserve the ordering of the result set"), but it is never emitted because hasChanged only considers added / removed / updated rows.
Versions
@powersync/shared-internals1.3.1 and 1.4.0 (latest, pulled in by@powersync/react-native2.3.3); same code onmaininpackages/shared-internals/src/client/watched/DifferentialQueryProcessor.ts- Seen in practice with
@powersync/react-native2.3.1 +useQuerywith arowComparator(differential mode)
Minimal reproduction
import { DifferentialQueryProcessor } from '@powersync/shared-internals';
const self = { comparator: { keyBy: (r) => r.id, compareBy: (r) => JSON.stringify(r) } };
const first = DifferentialQueryProcessor.prototype.differentiate.call(self, [{ id: 'a' }, { id: 'b' }], new Map());
const reordered = DifferentialQueryProcessor.prototype.differentiate.call(self, [{ id: 'b' }, { id: 'a' }], first.map);
console.log(reordered.hasChanged); // false <- expected true
console.log(reordered.diff.all.map((r) => r.id)); // ['b', 'a'] (correct order, but never emitted)
App-level symptom: a list rendered from a differential useQuery whose SQL ORDER BY changes (same filter, same rows) keeps showing the old order.
Expected
A pure reorder should count as a change, so the new diff.all (in the new order) is emitted to onDiff / data.
Suggested fix
previousMap is a Map, so it already preserves the previous result's insertion order. Comparing keys positionally while iterating is O(n) with no extra allocation:
const removedTracker = new Set(previousMap.keys());
+ // previousMap keeps the previous result's row order. A pure reorder (same rows,
+ // new ORDER BY) must count as a change, or the old order is served forever.
+ const previousKeys = previousMap.keys();
...
const previousItem = previousMap.get(key);
+ if (previousKeys.next().value !== key) {
+ hasChanged = true;
+ }
if (!previousItem) {
We have been running this as a local patch with a regression test (rows [a, b] -> [b, a] must emit). Happy to open a PR if this approach looks right. One open question for maintainers: whether a reorder should also be surfaced somehow in the diff object (today it would show up only as all rows unchanged with a different all order).
- Lingua principale
- TypeScript
- Stelle
- 729
- Fork
- 96
- Merge medio
- 3g 11h
- PR unite (30g)
- 34
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di powersync-ja/powersync-js
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
powersync-ja/powersync-js#1165 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
powersync-ja/powersync-js#1159 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
AttachmentQueue runs a full pass on every status change while connected, not only on coming onlineAperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
powersync-ja/powersync-js#1167 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 54/100
powersync-ja/powersync-js#1164 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
powersync-ja/powersync-js#1161 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di powersync-ja/powersync-js
Issue simili
-
Difficoltà 2/5 Meno di un'ora Idoneità per principianti 86/100
WilliamSmithEdward/xlide_vscode#1564 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
a2ui-project/a2ui#3809 ·
I maintainer di solito rispondono entro 2 giorni
-
[Bug] A write skipped for exceeding the size limit leaves its finished temp file in the libraryAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 4 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
esphome/device-builder-frontend#2064 ·
I maintainer di solito rispondono entro 1 giorno
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 61/100
lingdojo/kana-dojo#33465 · 1 commento · 5 reazioni ·
I maintainer di solito rispondono entro 1 giorno