(ctx context.Context, rows [][]types.Datum)
| 56 | } |
| 57 | |
| 58 | func (e *InsertExec) exec(ctx context.Context, rows [][]types.Datum) error { |
| 59 | defer trace.StartRegion(ctx, "InsertExec").End() |
| 60 | logutil.Eventf(ctx, "insert %d rows into table `%s`", len(rows), stringutil.StringerFunc(func() string { |
| 61 | var tblName string |
| 62 | if meta := e.Table.Meta(); meta != nil { |
| 63 | tblName = meta.Name.L |
| 64 | } |
| 65 | return tblName |
| 66 | })) |
| 67 | // If tidb_batch_insert is ON and not in a transaction, we could use BatchInsert mode. |
| 68 | sessVars := e.Ctx().GetSessionVars() |
| 69 | defer sessVars.CleanBuffers() |
| 70 | |
| 71 | txn, err := e.Ctx().Txn(true) |
| 72 | if err != nil { |
| 73 | return err |
| 74 | } |
| 75 | setOptionForTopSQL(sessVars.StmtCtx, txn) |
| 76 | if e.collectRuntimeStatsEnabled() { |
| 77 | if snapshot := txn.GetSnapshot(); snapshot != nil { |
| 78 | snapshot.SetOption(kv.CollectRuntimeStats, e.stats.SnapshotRuntimeStats) |
| 79 | defer snapshot.SetOption(kv.CollectRuntimeStats, nil) |
| 80 | } |
| 81 | } |
| 82 | sessVars.StmtCtx.AddRecordRows(uint64(len(rows))) |
| 83 | // If you use the IGNORE keyword, duplicate-key error that occurs while executing the INSERT statement are ignored. |
| 84 | // For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in |
| 85 | // the table causes a duplicate-key error and the statement is aborted. With IGNORE, the row is discarded and no error occurs. |
| 86 | // However, if the `on duplicate update` is also specified, the duplicated row will be updated. |
| 87 | // Using BatchGet in insert ignore to mark rows as duplicated before we add records to the table. |
| 88 | // If `ON DUPLICATE KEY UPDATE` is specified, and no `IGNORE` keyword, |
| 89 | // the to-be-insert rows will be check on duplicate keys and update to the new rows. |
| 90 | if len(e.OnDuplicate) > 0 { |
| 91 | err := e.batchUpdateDupRows(ctx, rows) |
| 92 | if err != nil { |
| 93 | return err |
| 94 | } |
| 95 | } else if e.ignoreErr { |
| 96 | err := e.batchCheckAndInsert(ctx, rows, e.addRecord, false) |
| 97 | if err != nil { |
| 98 | return err |
| 99 | } |
| 100 | } else { |
| 101 | start := time.Now() |
| 102 | dupKeyCheck := optimizeDupKeyCheckForNormalInsert(sessVars, txn) |
| 103 | for i, row := range rows { |
| 104 | var err error |
| 105 | sizeHintStep := int(sessVars.ShardAllocateStep) |
| 106 | if i%sizeHintStep == 0 { |
| 107 | sizeHint := sizeHintStep |
| 108 | remain := len(rows) - i |
| 109 | if sizeHint > remain { |
| 110 | sizeHint = remain |
| 111 | } |
| 112 | err = e.addRecordWithAutoIDHint(ctx, row, sizeHint, dupKeyCheck) |
| 113 | } else { |
| 114 | err = e.addRecord(ctx, row, dupKeyCheck) |
| 115 | } |
nothing calls this directly
no test coverage detected