Skip to content

fix(plan): dedup PostgreSQL-style UPDATE ... FROM by target row_id - #25023

Merged
mergify[bot] merged 6 commits into
matrixorigin:mainfrom
ck89119:issue-23137-main
Jun 18, 2026
Merged

fix(plan): dedup PostgreSQL-style UPDATE ... FROM by target row_id#25023
mergify[bot] merged 6 commits into
matrixorigin:mainfrom
ck89119:issue-23137-main

Conversation

@ck89119

@ck89119 ck89119 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • BUG

Which issue(s) this PR fixes:

issue #23137

What this PR does / why we need it:

Port of #24932 (targeting 4.0-dev) to main.

When the source of a PostgreSQL-style UPDATE ... FROM matches a target row more than once, the target row was duplicated/updated multiple times. This PR dedups the duplicate source matches with a row_number() window partitioned on the target row's physical identity (row_id) instead of on the whole old target row.

Partitioning on every old target column was unsafe:

  • crashes on GEOMETRY32 (no comparator in pkg/compare),
  • misses dedup on float columns holding NaN (NaN != NaN),
  • wrongly merges distinct rows whose column values happen to be identical.

The row_id key is stable, has a comparator, has no NaN, and is physically unique.

Additional changes:

  • The join-target NULL-row filter (isnotnull(row_id)) is preserved on the fallback (buildTableUpdate) path even after the dedup is switched from any_value aggregation to the row_number() window.
  • pkg/partition gains the missing T_Rowid (and other fixed-size type) cases so the row_id partition key does not panic at runtime.
  • Planner UTs and BVT cases cover both planner paths, GEOMETRY32/vector/decimal256/enum update columns, generated/DEFAULT columns, LEFT-JOIN NULL-row protection, and no-PRIMARY-KEY tables.

Port of PR matrixorigin#24932 (issue matrixorigin#23137) to main.

When the source of an UPDATE ... FROM matches a target row more than once,
the target row was duplicated/updated multiple times. Dedup the duplicate
source matches with a row_number() window partitioned on the target row's
physical identity (row_id) instead of the whole old target row: partitioning
on every old column would crash on GEOMETRY32 (no comparator), miss dedup on
float columns holding NaN (NaN != NaN), and wrongly merge distinct rows whose
columns happen to match. The join-target NULL-row filter (isnotnull(row_id))
is preserved on the fallback path. Adds the missing T_Rowid (and other
fixed-size type) cases to pkg/partition so the row_id partition key does not
panic at runtime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

# Conflicts:
#	pkg/sql/plan/build_test.go
@mergify mergify Bot added the queued label Jun 18, 2026
@mergify

mergify Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-06-18 10:57 UTC · Rule: main
  • Checks passed · in-place
  • Merged2026-06-18 12:09 UTC · at 81cca8929100da912c32c99473e96072477b9790 · squash

This pull request spent 1 hour 11 minutes 32 seconds in the queue, including 1 hour 11 minutes 15 seconds running CI.

Required conditions to merge
  • #approved-reviews-by >= 1 [🛡 GitHub branch protection]
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-decision = APPROVED [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-neutral = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-skipped = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Ubuntu/x86
    • check-neutral = Matrixone CI / SCA Test on Ubuntu/x86
    • check-skipped = Matrixone CI / SCA Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-neutral = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-skipped = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage

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

Labels

kind/bug Something isn't working size/XL Denotes a PR that changes [1000, 1999] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants