secantus-mdb 0.5.3-beta.187 refuses a duplicate document _id and keeps a document a $merge could not replace
Summary: secantus-mdb 0.5.3-beta.187 fixes two bugs that left the wrong documents in a collection: a duplicate _id written as a different number type, and a $merge replacement that deleted the document it could not replace.
Upgrade if you run secantusd-rs. This release fixes two bugs that left
the wrong documents in a collection.
- Two documents could share one
_id. After{_id: {a: 1}}, the server accepted{_id: {a: 1.0}}and{_id: {a: NumberLong(1)}}.mongodcompares the values and refuses both as duplicates. This affected an_idthat is a document; a number or a string was already compared by value. - A
$mergecould lose a document. WithwhenMatched: "replace", the server deleted the matched document and then inserted the new one. If a unique index refused the new one, neither was left.mongodkeeps the original, and so does this server now. A replaced document also keeps its place in the collection, where it used to move to the end.
The fix for the first does not change anything already on disk. A store
written by an earlier version opens and reads as before. The first time
this version opens a store it records the _id of every document already
there, so a duplicate of an older document is refused too. That happens
once and reads only the documents whose _id is a document. If an earlier
version already stored two documents with one _id, both stay.
We found both by sending 905 insert, delete, count and distinct
commands to the server and to mongod 8.2.11, and comparing each reply
and the documents left behind. The previous release differed on 162. This
one differs on 32.
The same comparison found other writes that touched the wrong documents:
- A delete statement with no
limitremoved every match.mongodrefuses the command, and nothing is removed. deleteran the statements ahead of one it then refused. It now checks every statement first.- A
limit: 1delete ignored itshint. With{$natural: -1},mongodremoves the newest match. This server removed whichever one it met first. findwith$inover an index returned documents in the order of the list.mongodreturns them in the index's order. Alimit: 1delete with the same query removed a different document.insertstored documentsmongodrefuses: a$-prefixed field inside an_idbelow its top level, and a document nested deeper than 180 levels.
Some replies changed too. A duplicate-key error printed a date, a
sub-document, binary data or a timestamp as Rust debug text; it prints
them as mongod does. insert, delete, count and distinct refuse
fields they do not take. Forty commands that take no writeConcern
refuse one.
What this release does not do. $where is not run. The message for a
hint that names no index is worded differently from mongod's. When a
document repeats the keys of two unique indexes, the index named in the
error can differ.
We ran the pymongo, Go and Node driver suites against this code. Each gave the same result as the release before.
This is a server for tests. It is single-node and it is a beta.
cargo install secantus-mdb --version 0.5.3-beta.187 builds it from crates.io.
Binaries for Linux x86_64, macOS arm64 and Windows x86_64 are on the release.
Rust MongoDB server · secantus-mdb on crates.io · MongoDB binaries