Skip to content

TransactWriteItems: a removal-only Update on a missing key creates a key-only item #510

Open

Description

@LeeroyHannigan

What ExtendDB does

A TransactWriteItems request with an Update whose actions are all REMOVE or DELETE, on a key that holds no item, creates an item holding only the key. Reproduced on SQLite: REMOVE a, REMOVE a, b, DELETE s :v and REMOVE a with attribute_not_exists(pk) each answer 200, and GetItem then returns {"pk": ...}. In a transaction with a removal-only update on one key and a SET on another, both keys end up holding an item.

The transaction update path is separate code in each backend (crates/storage-sqlite/src/data/transactions.rs, crates/storage-postgres/src/data/transactions.rs, crates/storage-cassandra/src/data/transactions.rs, and the transaction path in crates/storage-mongodb/src/data_engine.rs), so the single-item fix in #508 does not reach it.

What DynamoDB does

Measured 2026-10-24 in us-east-1, on a hash table and a hash and range table, client retries off. For each of the four updates above on a missing key, TransactWriteItems answers 200 and GetItem afterwards returns no item. A transaction with a removal-only update on one key and a SET on another creates only the SET item. ReturnConsumedCapacity TOTAL reports 2.0 capacity units and 2.0 write capacity units for the removal-only update, the same as for the SET control.

Fix

Apply extenddb_core::expression::removes_only from #508 in each backend's transaction update path: when the item is absent and the actions only remove, write nothing for that update, keep its condition check and its capacity charge, and leave the other items of the transaction unchanged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions