oxidecomputer / oxidecomputer/omicron
crdb conditional upsert (`insert_into().on_conflict().filter_target()`) doesn't apply the `filter_target` predicate
@sunshowers is already working on this.
Since Feb 13, 2024.
- Dominant language
- Rust
- Stars
- 572
- Forks
- 97
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 96
Description
tl;dr: let's say you want to:
- upsert a row into a database
- but only update it if a particular condition matches
The most obvious way to do this is with Diesel's DecoratableTarget::filter_target, but if you try and use that, CockroachDB silently drops the condition associated with filter_target if this is a full index. This is pretty bad.
For a full explanation, see this comment.
More details
I discovered this while working on #5032.
The Postgres documentation on INSERT documents two possible formulations for a conditional upsert:
ON CONFLICT ... WHERE ... DO UPDATEON CONFLICT ... DO UPDATE ... WHERE
filter_target becomes 1, not 2. It is possible to write 2 in Diesel via manually importing the FilterDsl trait, though it's not part of rustdoc for some reason.
Pattern 1 is only present to support partial indexes. If the index is a full index, CockroachDB silently ignores the WHERE clause in queries like 1. (This behavior makes sense -- see the linked full explanation for why.)
As the comment there indicates, you can even pass in a completely non-existent column -- and Cockroach completely ignores that.
To do:
- Figure out whether the bug still exists in the latest version of Cockroach -- yes, it does with v23.2.0
- If so, file a bug upstream: https://github.com/cockroachdb/cockroach/issues/119117
-
Write a Diesel extension that implements the-- not necessary becauseON CONFLICT ... DO UPDATE ... WHEREpattern.filter()is supported, though it doesn't show up in the documentation - Define a replacement for
DecoratableTarget::filter_target, and add a clippy lint: https://github.com/oxidecomputer/omicron/pull/5052 - File an issue with Diesel (or rustdoc?) talking about the implementations not being visible in
FilterDsl. - File an issue with Cockroach about crashes if you pass in an invalid expression like
ON CONFLICT ... WHERE 'x' = 1
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.