func (d *ddl) backfillColumn(ctx context.Context, t table.Table, columnInfo *model.ColumnInfo, handles []int64, reorgInfo *reorgInfo) error { var defaultVal types.Datum var err error if columnInfo.DefaultValue != nil { defaultVal, _, err = table.GetColDefaultValue(ctx, columnInfo) if err != nil { return errors.Trace(err) } } else if mysql.HasNotNullFlag(columnInfo.Flag) { defaultVal = table.GetZeroValue(columnInfo) } colMap := make(map[int64]*types.FieldType) for _, col := range t.Meta().Columns { colMap[col.ID] = &col.FieldType } var endIdx int for len(handles) > 0 { if len(handles) >= defaultSmallBatchCnt { endIdx = defaultSmallBatchCnt } else { endIdx = len(handles) } err = kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { if err := d.isReorgRunnable(txn, ddlJobFlag); err != nil { return errors.Trace(err) } nextHandle, err1 := d.backfillColumnInTxn(t, columnInfo.ID, handles[:endIdx], colMap, defaultVal, txn) if err1 != nil { return errors.Trace(err1) } return errors.Trace(reorgInfo.UpdateHandle(txn, nextHandle)) }) if err != nil { return errors.Trace(err) } handles = handles[endIdx:] } return nil }
func (d *ddl) backfillColumnData(t table.Table, columnInfo *model.ColumnInfo, handles []int64, reorgInfo *reorgInfo) error { var ( defaultVal types.Datum err error ) if columnInfo.DefaultValue != nil { defaultVal, _, err = table.GetColDefaultValue(nil, columnInfo) if err != nil { return errors.Trace(err) } } else if mysql.HasNotNullFlag(columnInfo.Flag) { defaultVal = table.GetZeroValue(columnInfo) } colMap := make(map[int64]*types.FieldType) for _, col := range t.Meta().Columns { colMap[col.ID] = &col.FieldType } for _, handle := range handles { log.Info("[ddl] backfill column...", handle) err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { if err := d.isReorgRunnable(txn); err != nil { return errors.Trace(err) } rowKey := t.RecordKey(handle) rowVal, err := txn.Get(rowKey) if terror.ErrorEqual(err, kv.ErrNotExist) { // If row doesn't exist, skip it. return nil } if err != nil { return errors.Trace(err) } rowColumns, err := tablecodec.DecodeRow(rowVal, colMap) if err != nil { return errors.Trace(err) } if _, ok := rowColumns[columnInfo.ID]; ok { // The column is already added by update or insert statement, skip it. return nil } newColumnIDs := make([]int64, 0, len(rowColumns)+1) newRow := make([]types.Datum, 0, len(rowColumns)+1) for colID, val := range rowColumns { newColumnIDs = append(newColumnIDs, colID) newRow = append(newRow, val) } newColumnIDs = append(newColumnIDs, columnInfo.ID) newRow = append(newRow, defaultVal) newRowVal, err := tablecodec.EncodeRow(newRow, newColumnIDs) if err != nil { return errors.Trace(err) } err = txn.Set(rowKey, newRowVal) if err != nil { return errors.Trace(err) } return errors.Trace(reorgInfo.UpdateHandle(txn, handle)) }) if err != nil { return errors.Trace(err) } } return nil }