[ddl] Indexed virtual generated columns can drift across session contexts and corrupt secondary indexes
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
### 1. Minimal reproduce step (Required)
**Environment**
TiDB nightly ed2376acc6; current TiDB master 05b396fb66; TiKV nightly 730be34f95
**Steps**
Strongest witness: create g INT AS (WEEK(d)) VIRTUAL with UNIQUE(g). Under default_week_format=0 insert id 1/date 2021-01-01; under mode 3 insert id 2/same date. Both source rows now project g=53, while the index contains 0->id1 and 53->id2. DELETE WHERE g=0 succeeds and affects 1; the source-owned twin affects 0. After success, the record store contains only id2/g53 while the covering index contains only stale id1/g0. ADMIN CHECK reports 8223. Explicit WEEK(d,3) rejects the second insert with 1062. A second witness uses DATE(TIMESTAMP) across time zones and deletes a predicate-false row.
### 2. What did you expect to see? (Required)
An indexed virtual generated column must map one base row to one stable key for every supported INSERT, UPDATE, DELETE, uniqueness-check, and read context. Successful DML must preserve a bijection between live records and index entries.
### 3. What did you see instead? (Required)
Before DELETE, source rows are id1:g53,id2:g53 while index entries are id1:g0,id2:g53; the g=0 index hit projects g=53 and predicate false. DELETE affects 1 versus source-owned 0. After success, source is id2:g53 and index is stale id1:g0. ADMIN CHECK reports 8223 before and after. The explicit-mode control stays consistent.
### 4. What is your TiDB version? (Required)
TiDB nightly ed2376acc6; current TiDB master 05b396fb66; TiKV nightly 730be34f95
Likely root cause and fix direction
**Likely root cause**
TiDB rejects direct context-sensitive expression indexes as unsafe under default config, but checkIllegalFn4Generated enforces the non-GA gate only for genType=typeIndex. A virtual generated column is admitted as typeColumn and an ordinary index does not revalidate its expression. Every row mutation reevaluates the virtual expression with the current session EvalContext, so a later DELETE can compute a different key from the one originally persisted.
**Fix direction**
Apply expression-index safety admission to every indexed generated-column composition. Reject implicit-context indexed expressions, canonicalize and persist their semantic context, or retain the original physical key needed by later mutations. Recheck base-row generated predicates before irreversible DML and make consistency checks compare both physical directions.
Contributor guide
Research direction
Start by running the WEEK virtual-column and UNIQUE reproduction, then use ADMIN CHECK to observe the index inconsistency. Read checkIllegalFn4Generated and trace the generated-column/index handling described in the report. Done means indexed virtual generated columns remain consistent across supported INSERT, UPDATE, DELETE, uniqueness checks, and reads.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100