Fix Sync Streams NOT null semantics#643
Conversation
🦋 Changeset detectedLatest commit: e7ccf58 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The change looks good in principle, but there is a significant risk of breaking existing queries that rely on I think we'd need to introduce a new compatibility option here to avoid changing behavior in existing queries. |
I wonder if it could make sense to add an (experimental) compatibility option to actually use the SQLite-based evaluator instead of our JavaScript re-implementation. That should hopefully fix all of these issues at once. The main reason I haven't explored this further so far is that we might need to refactor how we manage loaded sync rules to close the underlying SQLite database once we're done with them. But since we'll only use in-memory databases as an evaluator, a finalizer would probably work. SQLite in node also technically isn't stable yet, so the option would have to be experimental until that happens (I don't think the trouble of including better-sqlite3 in the OCI image for different architectures is worth it). |
50602ac to
e4bf2da
Compare
|
Pushed an update addressing the compatibility concern: the SQLite-compatible NULL boolean behavior is now behind a new |
e4bf2da to
e7ccf58
Compare
simolus3
left a comment
There was a problem hiding this comment.
I've verified that unstable_sqlite_expression_engine: true also covers this, so I'm not sure if we should add another compatibility option here (to be fair, this one wouldn't be unstable). I'll let @rkistner make that call.
| import { compileToSyncPlanWithoutErrors } from '../../compiler/utils.js'; | ||
| import { TestSourceTable } from '../../util.js'; | ||
|
|
||
| function prepareSyncStreams(yaml: string) { |
There was a problem hiding this comment.
This can probably use the syncTest helper
Summary
This fixes Sync Streams JavaScript/static evaluator divergences from SQLite around
NULLin boolean expressions.SQLite uses three-valued logic:
NOT NULLevaluates toNULLNULL NOT IN (...)evaluates toNULL0 OR NULLevaluates toNULL1 AND NULLevaluates toNULLIn a
WHEREclause,NULLshould not admit the row. The current JavaScript/static evaluator paths collapseNULLto false too early in a few places, which can turn expressions such asNOT nullable_flag,state NOT IN (...), orNOT (nullable_flag OR 0)into matches that SQLite would filter out.Changes
NULLfor unaryNOTin the shared SQL support helper.AND/ORin the JavaScript evaluator operator implementation.NULLsemantics.WHERE NOT nullable_flagwith a null valueWHERE state NOT IN '[...]'with a null left operandWHERE NOT (nullable_flag OR 0)with a null operandAND/ORwithNULL.Verification
Passed locally:
Note: the local
node:sqliteengine half ofengine.test.tsfails on my Node 23 runtime becausestmt.all()returns named row objects / parameter binding behavior that does not match the existing test expectations. The JavaScript evaluator path and new Sync Streams regressions pass.