fix: restore v19 per-shard UPDATE+LIMIT behavior - #837
Closed
sbaker617 wants to merge 3 commits into
Closed
Conversation
v22 changed UPDATE+LIMIT to use a two-phase DMLWithInput plan (SELECT PKs first, then UPDATE by PK) which requires schema tracking to know the PrimaryKey columns. This broke UPDATE+LIMIT on tables without schema tracking, returning VT09015 instead of planning the query. This restores the v19 behavior conditionally: when PrimaryKey info is not available, the LIMIT is embedded directly on the Update operator (as v19 did) so it pushes under the Route without needing DMLWithInput. When PrimaryKey IS available, the v22 DMLWithInput path is preserved. Root cause: PR vitessio#15107 replaced the Update struct's direct Limit field with a separate Limit operator, and renamed the deleteWithInput phase to dmlWithInput (now covering UPDATEs too). The separate Limit operator between Update and Route prevents tryPushUpdate from pushing the Update under the Route, forcing the dmlWithInput phase which requires PK. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Signed-off-by: Steve Baker <s.baker@slack-corp.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## slack-22.0 #837 +/- ##
==============================================
+ Coverage 67.53% 69.52% +1.99%
==============================================
Files 1600 1606 +6
Lines 261782 214260 -47522
==============================================
- Hits 176786 148964 -27822
+ Misses 84996 65296 -19700 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Switch from conditional (PK check) to unconditional v19-style LIMIT embedding on the Update operator. This avoids the DMLWithInput two-phase plan (SELECT PKs then UPDATE) for all UPDATE+LIMIT queries, matching v19 per-shard LIMIT semantics. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Signed-off-by: Steve Baker <s.baker@slack-corp.com>
- TestUniqueLookupDuplicateEntries: vindex update without ORDER BY now errors at plan time (VT12001) instead of execution time - TestUpdateWithLimit: skip, validates v22 DMLWithInput total-count LIMIT which our fork doesn't use Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Signed-off-by: Steve Baker <s.baker@slack-corp.com>
|
This PR is being marked as stale because it has been open for 30 days with no activity. To rectify, you may do any of the following:
If no action is taken within 7 days, this PR will be closed. |
|
This PR was closed because it has been stale for 7 days with no activity. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's this?
Restores v19 per-shard LIMIT behavior for all
UPDATE ... LIMIT Nqueries. v22 introduced a two-phase DMLWithInput plan (SELECT PKs then UPDATE by PK) for UPDATE+LIMIT, but we don't want that — v19's per-shard LIMIT is the expected behavior for our fork (withMULTI_SHARD_AUTOCOMMIT=1/ALLOW_SCATTER).How it works
v22 changed UPDATE+LIMIT to create a separate Limit operator above the Route, which triggers the
dmlWithInputphase requiring PrimaryKey metadata. This change unconditionally reverts to v19's approach: embed the LIMIT directly on the Update operator so it pushes under the Route. No DMLWithInput, no PK select-then-update — LIMIT applies per-shard.This means
UPDATE ... LIMIT 10across 10 shards may update up to 100 rows total (10 per shard), which is the intended behavior.Changes
update.go: AddLimitfield to Update struct, embed LIMIT unconditionally (no separate Limit operator)SQL_builder.go: Include embedded Limit in generated SQLunknown_schema_cases.json: 2 regression tests (UPDATE+LIMIT without PK)dml_cases.json: Updated 2 existing test expectationsdml_test.go: Updated e2e tests —TestUniqueLookupDuplicateEntrieserror expectation, skipTestUpdateWithLimit(validates v22 total-count LIMIT)Root cause
PR vitessio#15107 replaced Update's direct Limit field with a separate Limit operator and renamed
deleteWithInput→dmlWithInput(now covering UPDATEs). The Limit operator between Update and Route preventstryPushUpdatefrom pushing Update under Route, forcing thedmlWithInputphase which requires PK.Most of this was written by Claude Code — I provided direction and review.