Skip to content

Fix DELETE/WHERE maybe altering its own resultset

From the main commit:

core: Avoid flushing updates within delete+insert+where queries

Currently, we perform the insert/delete operations while iterating
a cursor dealing with the where clause. Performing updates while
performing select queries and iterating through cursors is usually
not an issue, but that is only true (with WAL) if this is performed
through different interfaces, so the readers can interact with the
unmodified database while updates are accumulated in the write-ahead
log. More information at https://www.sqlite.org/isolation.html.

But here, we are dealing with a cursor created from the update thread,
inside the same lock and seeing the same data than the latest update.

So, if a delete{}insert{}where{} query happens to be modifying data
that alter the results of the where{} clause, we might be getting the
cursor silently updated underneath, thus either missing data that
originally matched the where{} clause, or overreaching with brand
new data that happens to match the where{} clause.

As per the specs, the execution order is executing the where{}, obtaining
resultset, then apply delete+insert clauses on each result. We cannot
let these updates happen while iterating the resultset, so freeze/thaw
the flush mechanism to ensure that these update operations are accumulated
without effects on the database. After all the results are iterated, the
accumulated operations will be flushed at once.

Related: tracker-miners#327 (closed)

Merge request reports