oxidecomputer / oxidecomputer/omicron

crdb conditional upsert (`insert_into().on_conflict().filter_target()`) doesn't apply the `filter_target` predicate

Open
#5,047 0 comments 0 reactions 1 assignee View on GitHub

@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:

  1. ON CONFLICT ... WHERE ... DO UPDATE
  2. ON 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.)

See this gist for a repro.

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 ON CONFLICT ... DO UPDATE ... WHERE pattern -- not necessary because .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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.