batchUpdateDupRows updates multi-rows in batch if they are duplicate with rows in table.
(ctx context.Context, newRows [][]types.Datum)
| 224 | |
| 225 | // batchUpdateDupRows updates multi-rows in batch if they are duplicate with rows in table. |
| 226 | func (e *InsertExec) batchUpdateDupRows(ctx context.Context, newRows [][]types.Datum) error { |
| 227 | // Get keys need to be checked. |
| 228 | start := time.Now() |
| 229 | toBeCheckedRows, err := getKeysNeedCheck(e.Ctx(), e.Table, newRows) |
| 230 | if err != nil { |
| 231 | return err |
| 232 | } |
| 233 | |
| 234 | txn, err := e.Ctx().Txn(true) |
| 235 | if err != nil { |
| 236 | return err |
| 237 | } |
| 238 | |
| 239 | prefetchStart := time.Now() |
| 240 | // Use BatchGet to fill cache. |
| 241 | // It's an optimization and could be removed without affecting correctness. |
| 242 | if err = e.prefetchDataCache(ctx, txn, toBeCheckedRows); err != nil { |
| 243 | return err |
| 244 | } |
| 245 | if e.stats != nil { |
| 246 | e.stats.Prefetch += time.Since(prefetchStart) |
| 247 | } |
| 248 | |
| 249 | // Use `optimizeDupKeyCheckForUpdate` to determine the update operation when the row meets the conflict in |
| 250 | // `INSERT ... ON DUPLICATE KEY UPDATE` statement. |
| 251 | // Though it is in an insert statement, `ON DUP KEY UPDATE` follows the dup-key check behavior of update. |
| 252 | // For example, it will ignore variable `tidb_constraint_check_in_place`, see the test case: |
| 253 | // https://github.com/pingcap/tidb/blob/3117d3fae50bbb5dabcde7b9589f92bfbbda5dc6/pkg/executor/test/writetest/write_test.go#L419-L426 |
| 254 | updateDupKeyCheck := optimizeDupKeyCheckForUpdate(txn, e.ignoreErr) |
| 255 | // Do not use `updateDupKeyCheck` for `AddRecord` because it is not optimized for insert. |
| 256 | // It seems that we can just use `DupKeyCheckSkip` here because all constraints are checked. |
| 257 | // But we still use `optimizeDupKeyCheckForNormalInsert` to make the refactor same behavior with the original code. |
| 258 | // TODO: just use `DupKeyCheckSkip` here. |
| 259 | addRecordDupKeyCheck := optimizeDupKeyCheckForNormalInsert(e.Ctx().GetSessionVars(), txn) |
| 260 | |
| 261 | _, autoColIdx, found := findAutoIncrementColumn(e.Table) |
| 262 | if !found { |
| 263 | autoColIdx = -1 |
| 264 | } |
| 265 | |
| 266 | for i, r := range toBeCheckedRows { |
| 267 | if r.handleKey != nil { |
| 268 | handle, err := tablecodec.DecodeRowKey(r.handleKey.newKey) |
| 269 | if err != nil { |
| 270 | return err |
| 271 | } |
| 272 | |
| 273 | err = e.updateDupRow(ctx, i, txn, r, handle, e.OnDuplicate, updateDupKeyCheck, autoColIdx) |
| 274 | if err == nil { |
| 275 | continue |
| 276 | } |
| 277 | if !kv.IsErrNotFound(err) { |
| 278 | return err |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | for _, uk := range r.uniqueKeys { |
| 283 | _, handle, err := tables.FetchDuplicatedHandle(ctx, uk.newKey, true, txn) |
no test coverage detected