Skip to content

planner/core: update missing virtual columns in update and insert (#58401)#66878

Merged
ti-chi-bot[bot] merged 6 commits intopingcap:release-7.5from
ti-chi-bot:cherry-pick-58401-to-release-7.5
Mar 23, 2026
Merged

planner/core: update missing virtual columns in update and insert (#58401)#66878
ti-chi-bot[bot] merged 6 commits intopingcap:release-7.5from
ti-chi-bot:cherry-pick-58401-to-release-7.5

Conversation

@ti-chi-bot
Copy link
Copy Markdown
Member

@ti-chi-bot ti-chi-bot commented Mar 10, 2026

This is an automated cherry-pick of #58401

What problem does this PR solve?

Issue Number: close #58400

Problem Summary:

In #58494, we fixed a problem related to virtual columns. But we haven't completely fixed it yet. There still have problems with virtual columns.

For Update:

In update statements, virtual columns will be added into UpdateLists if their dependent columns have changed. #55829 has fixed nested generated column.

// check if the column is modified
dependentColumns := expression.ExtractDependentColumns(newExpr)
var isModified bool
for _, col := range dependentColumns {
if dependentColumnsModified[col.UniqueID] {
isModified = true
break
}
}
if isModified {
dependentColumnsModified[col.UniqueID] = true
}

However, we still ignore the columns with OnUpdateNow flag when checking dependency. Since these columns may be updated in the execution stage too.

For Insert:

For SQL like INSERT INTO ... ON DUPLICATE KEY UPDATE ..., only virtual columns that directly depend on the assignments after UPDATE will be updated. Take the table in #58400 as example:

CREATE TABLE tmv (
  J1 json, J2 json GENERATED ALWAYS AS (j1) VIRTUAL,
  UNIQUE KEY i1 ((cast(j1 as signed array))),
  KEY i2 ((cast(j2 as signed array)))
);

INSERT INTO tmv SET j1 = '[1]' ON DUPLICATE KEY UPDATE j1 = '[2]';

The dependencies of each column are listed below. Only j2 and _V$_i1_0 are updated since they depends on j1. We should handle it the same way as what we do in #55829.

j2 <-- j1
_V$_i1_0 <-- j1
_V$_i2_0 <-- j2

What changed and how does it work?

In summary, when extracting generated columns, we have to consider both chain dependencies and on-update-now flag too.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation and consistency checks for time-based generated columns in UPDATE operations.
    • Enhanced ON DUPLICATE KEY UPDATE behavior with generated columns to properly track column modifications.
  • Tests

    • Added test coverage for ON UPDATE CURRENT_TIMESTAMP columns during data import operations.
    • Expanded test validation for generated columns with duplicate key updates across different index configurations.

@ti-chi-bot ti-chi-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/L Denotes a PR that changes 100-499 lines, ignoring generated files. type/cherry-pick-for-release-7.5 This PR is cherry-picked to release-7.5 from a source PR. labels Mar 10, 2026
@ti-chi-bot
Copy link
Copy Markdown
Member Author

@joechenrh This PR has conflicts, I have hold it.
Please resolve them or ask others to resolve them, then comment /unhold to remove the hold label.

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 10, 2026

@ti-chi-bot: ## If you want to know how to resolve it, please read the guide in TiDB Dev Guide.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

This pull request fixes a bug where UPDATE and INSERT ON DUPLICATE KEY UPDATE statements fail to properly update indexes containing generated columns. The fix modifies the planner's column dependency tracking to detect when dependent columns with OnUpdateNow flags may be modified and propagates this information during ON DUPLICATE KEY UPDATE processing. Tests are added to validate the corrections.

Changes

Cohort / File(s) Summary
Planner Core Logic
pkg/planner/core/logical_plan_builder.go, pkg/planner/core/planbuilder.go
Modified column dependency tracking: renamed isModified to mayModified and added OnUpdateNow flag detection. Updated resolveGeneratedColumns function signature and added on-duplicate propagation logic for generated column dependencies. These changes ensure indexes with generated columns are marked for update when their base columns have OnUpdateNow semantics.
Executor Tests
pkg/executor/update_test.go, pkg/executor/test/issuetest/executor_issue_test.go
Added validation tests that verify UPDATE and INSERT ON DUPLICATE KEY UPDATE operations properly update indexes with generated columns. Tests include toggling tidb_enable_fast_table_check and running admin check table to confirm consistency.
Integration Tests
tests/realtikvtest/importintotest/import_into_test.go
Added TestOnUpdateColumn test case to validate IMPORT INTO behavior with ON UPDATE CURRENT_TIMESTAMP columns.
Build Configuration
pkg/executor/test/issuetest/BUILD.bazel
Incremented test shard count from 22 to 23 for parallel test execution.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

type/cherry-pick-for-release-8.5, approved, lgtm

Suggested reviewers

  • Benjamin2037
  • D3Hunter
  • hawkingrei

Poem

🐰 A hop and a skip through indexes we go,
Generated columns now properly flow,
OnUpdateNow flags caught with care,
Duplicates handled, consistency fair! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main change: updating missing virtual columns in update and insert statements.
Description check ✅ Passed The PR description includes issue number, problem summary, what changed, test coverage confirmation, and follows the template structure with all critical sections addressed.
Linked Issues check ✅ Passed The code changes directly address the virtual column consistency issues in #58400 by handling chain dependencies and OnUpdateNow flags in both UPDATE and INSERT operations.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing virtual column handling in UPDATE and INSERT statements, with supporting tests and Bazel configuration updates that are in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.3)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
@ti-chi-bot ti-chi-bot force-pushed the cherry-pick-58401-to-release-7.5 branch from 179b81f to 89b54b6 Compare March 10, 2026 12:02
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/executor/update_test.go (1)

695-697: Avoid wall-clock sleep in this regression test.

SELECT sleep(1) makes the test slower and timing-dependent. You can force distinct CURRENT_TIMESTAMP values deterministically with the session timestamp variable and keep the same coverage.

♻️ Suggested change
-	tk.MustExec("INSERT INTO ttime SET id = 1")
-	tk.MustExec("SELECT sleep(1)")
-	tk.MustExec("UPDATE ttime SET id = 2")
+	tk.MustExec("SET @@timestamp = 1700000000")
+	tk.MustExec("INSERT INTO ttime SET id = 1")
+	tk.MustExec("SET @@timestamp = 1700000001")
+	tk.MustExec("UPDATE ttime SET id = 2")
+	tk.MustExec("SET @@timestamp = 0")

As per coding guidelines, **/{*_test.go,testdata/**}: Keep test changes minimal and deterministic; avoid broad golden/testdata churn unless required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/executor/update_test.go` around lines 695 - 697, Replace the wall-clock
sleep between the two statements: instead of tk.MustExec("SELECT sleep(1)"), set
the session timestamp variable to a different deterministic value so
CURRENT_TIMESTAMP advances (e.g. call tk.MustExec("SET @@session.timestamp =
<new_unix_ts>") or similar) between tk.MustExec("INSERT INTO ttime SET id = 1")
and tk.MustExec("UPDATE ttime SET id = 2"); this keeps the test deterministic
and fast while preserving coverage of CURRENT_TIMESTAMP changes (refer to
tk.MustExec and the session 'timestamp' variable).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/planner/core/planbuilder.go`:
- Around line 3883-3892: Remove the merge conflict markers and adopt the HEAD
signature for resolveGeneratedColumns: use the local type LogicalPlan (no
package prefix) for the mockPlan parameter and keep the original comment
wording; ensure the function declaration matches "func (b *PlanBuilder)
resolveGeneratedColumns(ctx context.Context, columns []*table.Column, onDups
map[string]struct{}, mockPlan LogicalPlan) (igc InsertGeneratedColumns, err
error)" and delete the alternate "base.LogicalPlan" variant so the file
compiles.

---

Nitpick comments:
In `@pkg/executor/update_test.go`:
- Around line 695-697: Replace the wall-clock sleep between the two statements:
instead of tk.MustExec("SELECT sleep(1)"), set the session timestamp variable to
a different deterministic value so CURRENT_TIMESTAMP advances (e.g. call
tk.MustExec("SET @@session.timestamp = <new_unix_ts>") or similar) between
tk.MustExec("INSERT INTO ttime SET id = 1") and tk.MustExec("UPDATE ttime SET id
= 2"); this keeps the test deterministic and fast while preserving coverage of
CURRENT_TIMESTAMP changes (refer to tk.MustExec and the session 'timestamp'
variable).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 498286bd-37de-45ff-9ae8-784a50947129

📥 Commits

Reviewing files that changed from the base of the PR and between 293331c and 89b54b6.

📒 Files selected for processing (4)
  • pkg/executor/insert_test.go
  • pkg/executor/update_test.go
  • pkg/planner/core/logical_plan_builder.go
  • pkg/planner/core/planbuilder.go

Comment thread pkg/planner/core/planbuilder.go Outdated
Signed-off-by: Ruihao Chen <joechenrh@gmail.com>
Signed-off-by: Ruihao Chen <joechenrh@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/realtikvtest/importintotest/import_into_test.go`:
- Around line 253-267: The current TestOnUpdateColumn doesn't exercise the
planner/core generated-column transitive OnUpdateNow bug because it uses IMPORT
INTO; rewrite TestOnUpdateColumn to create a table with a primary key (or unique
index), a column with ON UPDATE CURRENT_TIMESTAMP, and a dependent VIRTUAL
generated column that is indexed (to trigger the dependency path), then perform
an UPDATE or INSERT ... ON DUPLICATE KEY UPDATE that changes the ON UPDATE
column (use s.tk.MustExec to run the statement), assert the row values
(s.tk.MustQuery) and run ADMIN CHECK TABLE to validate integrity; ensure the
test uses the same setup helpers (s.prepareAndUseDB, s.server.CreateObject if
needed) and that the sequence fails on the pre-fix behavior and passes after the
fix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b0d97fb6-1468-405a-b555-fbd44c46b136

📥 Commits

Reviewing files that changed from the base of the PR and between 89b54b6 and c4b63c3.

📒 Files selected for processing (3)
  • pkg/planner/core/logical_plan_builder.go
  • pkg/planner/core/planbuilder.go
  • tests/realtikvtest/importintotest/import_into_test.go

Comment thread pkg/planner/core/logical_plan_builder.go
Comment thread tests/realtikvtest/importintotest/import_into_test.go
@joechenrh
Copy link
Copy Markdown
Contributor

/retest

@joechenrh
Copy link
Copy Markdown
Contributor

/retest

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (release-7.5@293331c). Learn more about missing BASE report.

Additional details and impacted files
@@               Coverage Diff                @@
##             release-7.5     #66878   +/-   ##
================================================
  Coverage               ?   72.2022%           
================================================
  Files                  ?       1422           
  Lines                  ?     415289           
  Branches               ?          0           
================================================
  Hits                   ?     299848           
  Misses                 ?      95391           
  Partials               ?      20050           
Flag Coverage Δ
unit 72.2022% <100.0000%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 52.9400% <0.0000%> (?)
parser ∅ <0.0000%> (?)
br 53.6446% <0.0000%> (?)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@joechenrh joechenrh removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 18, 2026
@ti-chi-bot ti-chi-bot Bot added cherry-pick-approved Cherry pick PR approved by release team. and removed do-not-merge/cherry-pick-not-approved labels Mar 19, 2026
Signed-off-by: Ruihao Chen <joechenrh@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/executor/test/issuetest/executor_issue_test.go (1)

776-810: LGTM! Test properly validates generated column index consistency fix.

The test covers both scenarios from issue #58400:

  1. tmv table: Tests INSERT ... ON DUPLICATE KEY UPDATE where a virtual column j2 depends on updated column j1.
  2. ttime table: Tests chained virtual column dependencies (t2→t1, t3→t2, t4→t2) with ON UPDATE CURRENT_TIMESTAMP semantics.

Both are validated with admin check table under both fast and slow table check modes, ensuring index consistency.

💡 Optional: Add DROP TABLE statements for consistency with other tests

Other tests in this file include DROP TABLE IF EXISTS before creating tables. While not strictly necessary with a fresh mock store, adding them would improve consistency:

 func TestInsertDuplicateToGeneratedColumns(t *testing.T) {
 	store := testkit.CreateMockStore(t)
 	tk := testkit.NewTestKit(t, store)
 	tk.MustExec("use test")
+	tk.MustExec("drop table if exists tmv, ttime")
 	tk.MustExec(`
 		CREATE TABLE tmv (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/executor/test/issuetest/executor_issue_test.go` around lines 776 - 810,
Add DROP TABLE IF EXISTS statements for tables used in
TestInsertDuplicateToGeneratedColumns to match the surrounding tests' pattern;
specifically, before the CREATE TABLE tmv and CREATE TABLE ttime statements in
the TestInsertDuplicateToGeneratedColumns function, insert DROP TABLE IF EXISTS
tmv and DROP TABLE IF EXISTS ttime respectively so the test is consistent and
resilient even if run in non-fresh environments.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/executor/test/issuetest/executor_issue_test.go`:
- Around line 776-810: Add DROP TABLE IF EXISTS statements for tables used in
TestInsertDuplicateToGeneratedColumns to match the surrounding tests' pattern;
specifically, before the CREATE TABLE tmv and CREATE TABLE ttime statements in
the TestInsertDuplicateToGeneratedColumns function, insert DROP TABLE IF EXISTS
tmv and DROP TABLE IF EXISTS ttime respectively so the test is consistent and
resilient even if run in non-fresh environments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e70a4ef2-7880-417e-afff-aa77dc3b8b57

📥 Commits

Reviewing files that changed from the base of the PR and between c4b63c3 and a4647f0.

📒 Files selected for processing (2)
  • pkg/executor/test/issuetest/BUILD.bazel
  • pkg/executor/test/issuetest/executor_issue_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/executor/test/issuetest/BUILD.bazel

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Mar 20, 2026
@ti-chi-bot ti-chi-bot Bot added the approved label Mar 20, 2026
Copy link
Copy Markdown
Collaborator

@Benjamin2037 Benjamin2037 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Mar 20, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 20, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Benjamin2037, qw4990

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 20, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-03-20 08:47:09.920815809 +0000 UTC m=+519557.008473356: ☑️ agreed by qw4990.
  • 2026-03-20 08:55:10.794070576 +0000 UTC m=+520037.881728113: ☑️ agreed by Benjamin2037.

@joechenrh
Copy link
Copy Markdown
Contributor

/retest

1 similar comment
@joechenrh
Copy link
Copy Markdown
Contributor

/retest

@joechenrh
Copy link
Copy Markdown
Contributor

/test?

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 23, 2026

@joechenrh: The following commands are available to trigger required jobs:

/test build
/test check-dev
/test check-dev2
/test mysql-test
/test unit-test

The following commands are available to trigger optional jobs:

/test pull-br-integration-test
/test pull-check-deps
/test pull-common-test
/test pull-e2e-test
/test pull-integration-binlog-test
/test pull-integration-common-test
/test pull-integration-copr-test
/test pull-integration-ddl-test
/test pull-integration-jdbc-test
/test pull-integration-mysql-test
/test pull-integration-nodejs-test
/test pull-integration-python-orm-test
/test pull-integration-tidb-tools-test
/test pull-mysql-client-test
/test pull-sqllogic-test
/test pull-tiflash-test

Use /test all to run the following jobs that were automatically triggered:

pingcap/tidb/release-7.5/ghpr_build
pingcap/tidb/release-7.5/ghpr_check
pingcap/tidb/release-7.5/ghpr_check2
pingcap/tidb/release-7.5/ghpr_mysql_test
pingcap/tidb/release-7.5/ghpr_unit_test
pull-check-deps
Details

In response to this:

/test?

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@tiprow
Copy link
Copy Markdown

tiprow Bot commented Mar 23, 2026

@joechenrh: No presubmit jobs available for pingcap/tidb@release-7.5

Details

In response to this:

/test?

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@joechenrh
Copy link
Copy Markdown
Contributor

/test check-dev2

@tiprow
Copy link
Copy Markdown

tiprow Bot commented Mar 23, 2026

@joechenrh: No presubmit jobs available for pingcap/tidb@release-7.5

Details

In response to this:

/test check-dev2

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@joechenrh
Copy link
Copy Markdown
Contributor

/retest

1 similar comment
@joechenrh
Copy link
Copy Markdown
Contributor

/retest

@ti-chi-bot ti-chi-bot Bot merged commit edcf353 into pingcap:release-7.5 Mar 23, 2026
19 checks passed
@ti-chi-bot ti-chi-bot Bot deleted the cherry-pick-58401-to-release-7.5 branch March 23, 2026 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved cherry-pick-approved Cherry pick PR approved by release team. lgtm release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/L Denotes a PR that changes 100-499 lines, ignoring generated files. type/cherry-pick-for-release-7.5 This PR is cherry-picked to release-7.5 from a source PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants