// UpdateRecord implements table.Table UpdateRecord interface. func (t *Table) UpdateRecord(ctx context.Context, h int64, oldData []types.Datum, newData []types.Datum, touched map[int]bool) error { // We should check whether this table has on update column which state is write only. currentData := make([]types.Datum, len(t.WritableCols())) copy(currentData, newData) // If they are not set, and other data are changed, they will be updated by current timestamp too. err := t.setOnUpdateData(ctx, touched, currentData) if err != nil { return errors.Trace(err) } txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } bs := kv.NewBufferStore(txn) // Compose new row t.composeNewData(touched, currentData, oldData) colIDs := make([]int64, 0, len(t.WritableCols())) for i, col := range t.WritableCols() { if col.State != model.StatePublic && currentData[i].IsNull() { defaultVal, _, err1 := table.GetColDefaultValue(ctx, col.ToInfo()) if err1 != nil { return errors.Trace(err1) } currentData[i] = defaultVal } colIDs = append(colIDs, col.ID) } // Set new row data into KV. key := t.RecordKey(h) value, err := tablecodec.EncodeRow(currentData, colIDs) if err = txn.Set(key, value); err != nil { return errors.Trace(err) } if err = bs.SaveTo(txn); err != nil { return errors.Trace(err) } // rebuild index if err = t.rebuildIndices(bs, h, touched, oldData, currentData); err != nil { return errors.Trace(err) } err = bs.SaveTo(txn) if err != nil { return errors.Trace(err) } if shouldWriteBinlog(ctx) { t.addUpdateBinlog(ctx, h, oldData, value, colIDs) } return nil }
// UpdateRecord implements table.Table UpdateRecord interface. func (t *Table) UpdateRecord(ctx context.Context, h int64, oldData []types.Datum, newData []types.Datum, touched map[int]bool) error { // We should check whether this table has on update column which state is write only. currentData := make([]types.Datum, len(t.writableCols())) copy(currentData, newData) // If they are not set, and other data are changed, they will be updated by current timestamp too. err := t.setOnUpdateData(ctx, touched, currentData) if err != nil { return errors.Trace(err) } txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } bs := kv.NewBufferStore(txn) defer bs.Release() // Compose new row t.composeNewData(touched, currentData, oldData) colIDs := make([]int64, 0, len(t.writableCols())) for _, col := range t.writableCols() { colIDs = append(colIDs, col.ID) } // Set new row data into KV. key := t.RecordKey(h) value, err := tablecodec.EncodeRow(currentData, colIDs) if err = txn.Set(key, value); err != nil { return errors.Trace(err) } if err = bs.SaveTo(txn); err != nil { return errors.Trace(err) } // rebuild index if err = t.rebuildIndices(bs, h, touched, oldData, currentData); err != nil { return errors.Trace(err) } err = bs.SaveTo(txn) if err != nil { return errors.Trace(err) } return nil }
// UpdateRecord implements table.Table UpdateRecord interface. func (t *Table) UpdateRecord(ctx context.Context, h int64, oldData []interface{}, newData []interface{}, touched map[int]bool) error { // We should check whether this table has on update column which state is write only. currentData := make([]interface{}, len(t.writableCols())) copy(currentData, newData) // If they are not set, and other data are changed, they will be updated by current timestamp too. err := t.setOnUpdateData(ctx, touched, currentData) if err != nil { return errors.Trace(err) } txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } bs := kv.NewBufferStore(txn) defer bs.Release() // set new value if err = t.setNewData(bs, h, touched, currentData); err != nil { return errors.Trace(err) } // rebuild index if err = t.rebuildIndices(bs, h, touched, oldData, currentData); err != nil { return errors.Trace(err) } err = bs.SaveTo(txn) if err != nil { return errors.Trace(err) } return nil }
// AddRecord implements table.Table AddRecord interface. func (t *Table) AddRecord(ctx context.Context, r []interface{}) (recordID int64, err error) { var hasRecordID bool for _, col := range t.Cols() { if col.IsPKHandleColumn(t.meta) { recordID, err = types.ToInt64(r[col.Offset]) if err != nil { return 0, errors.Trace(err) } hasRecordID = true break } } if !hasRecordID { recordID, err = t.alloc.Alloc(t.ID) if err != nil { return 0, errors.Trace(err) } } txn, err := ctx.GetTxn(false) if err != nil { return 0, errors.Trace(err) } bs := kv.NewBufferStore(txn) defer bs.Release() // Insert new entries into indices. h, err := t.addIndices(ctx, recordID, r, bs) if err != nil { return h, errors.Trace(err) } if err = t.LockRow(ctx, recordID); err != nil { return 0, errors.Trace(err) } // Set public and write only column value. for _, col := range t.writableCols() { if col.IsPKHandleColumn(t.meta) { continue } var value interface{} if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization { // if col is in write only or write reorganization state, we must add it with its default value. value, _, err = GetColDefaultValue(ctx, &col.ColumnInfo) if err != nil { return 0, errors.Trace(err) } value, err = types.Convert(value, &col.FieldType) if err != nil { return 0, errors.Trace(err) } } else { value = r[col.Offset] } key := t.RecordKey(recordID, col) err = t.SetColValue(txn, key, value) if err != nil { return 0, errors.Trace(err) } } if err = bs.SaveTo(txn); err != nil { return 0, errors.Trace(err) } variable.GetSessionVars(ctx).AddAffectedRows(1) return recordID, nil }
// AddRecord implements table.Table AddRecord interface. func (t *Table) AddRecord(ctx context.Context, r []types.Datum) (recordID int64, err error) { var hasRecordID bool for _, col := range t.Cols() { if col.IsPKHandleColumn(t.meta) { recordID = r[col.Offset].GetInt64() hasRecordID = true break } } if !hasRecordID { recordID, err = t.alloc.Alloc(t.ID) if err != nil { return 0, errors.Trace(err) } } txn, err := ctx.GetTxn(false) if err != nil { return 0, errors.Trace(err) } bs := kv.NewBufferStore(txn) // Insert new entries into indices. h, err := t.addIndices(ctx, recordID, r, bs) if err != nil { return h, errors.Trace(err) } colIDs := make([]int64, 0, len(r)) row := make([]types.Datum, 0, len(r)) // Set public and write only column value. for _, col := range t.WritableCols() { if col.IsPKHandleColumn(t.meta) { continue } var value types.Datum if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization { // if col is in write only or write reorganization state, we must add it with its default value. value, _, err = table.GetColDefaultValue(ctx, col.ToInfo()) if err != nil { return 0, errors.Trace(err) } } else { value = r[col.Offset] if col.DefaultValue == nil && r[col.Offset].IsNull() { // Save storage space by not storing null value. continue } } colIDs = append(colIDs, col.ID) row = append(row, value) } key := t.RecordKey(recordID) value, err := tablecodec.EncodeRow(row, colIDs) if err != nil { return 0, errors.Trace(err) } if err = txn.Set(key, value); err != nil { return 0, errors.Trace(err) } if err = bs.SaveTo(txn); err != nil { return 0, errors.Trace(err) } if shouldWriteBinlog(ctx) { mutation := t.getMutation(ctx) // prepend handle to the row value handleVal, _ := codec.EncodeValue(nil, types.NewIntDatum(recordID)) bin := append(handleVal, value...) mutation.InsertedRows = append(mutation.InsertedRows, bin) mutation.Sequence = append(mutation.Sequence, binlog.MutationType_Insert) } ctx.GetSessionVars().StmtCtx.AddAffectedRows(1) return recordID, nil }
// AddRecord implements table.Table AddRecord interface. func (t *Table) AddRecord(ctx context.Context, r []types.Datum) (recordID int64, err error) { var hasRecordID bool for _, col := range t.Cols() { if col.IsPKHandleColumn(t.meta) { recordID = r[col.Offset].GetInt64() hasRecordID = true break } } if !hasRecordID { recordID, err = t.alloc.Alloc(t.ID) if err != nil { return 0, errors.Trace(err) } } txn, err := ctx.GetTxn(false) if err != nil { return 0, errors.Trace(err) } bs := kv.NewBufferStore(txn) defer bs.Release() // Insert new entries into indices. h, err := t.addIndices(ctx, recordID, r, bs) if err != nil { return h, errors.Trace(err) } colIDs := make([]int64, 0, len(r)) row := make([]types.Datum, 0, len(r)) // Set public and write only column value. for _, col := range t.writableCols() { if col.IsPKHandleColumn(t.meta) { continue } if col.DefaultValue == nil && r[col.Offset].IsNull() { // Save storage space by not storing null value. continue } var value types.Datum if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization { // if col is in write only or write reorganization state, we must add it with its default value. value, _, err = table.GetColDefaultValue(ctx, &col.ColumnInfo) if err != nil { return 0, errors.Trace(err) } } else { value = r[col.Offset] } colIDs = append(colIDs, col.ID) row = append(row, value) } key := t.RecordKey(recordID) value, err := tablecodec.EncodeRow(row, colIDs) if err != nil { return 0, errors.Trace(err) } if err = txn.Set(key, value); err != nil { return 0, errors.Trace(err) } if err = bs.SaveTo(txn); err != nil { return 0, errors.Trace(err) } variable.GetSessionVars(ctx).AddAffectedRows(1) return recordID, nil }
// AddRecord implements table.Table AddRecord interface. func (t *Table) AddRecord(ctx context.Context, r []interface{}) (recordID int64, err error) { var hasRecordID bool for _, col := range t.Cols() { if col.IsPKHandleColumn(t.meta) { recordID, err = types.ToInt64(r[col.Offset]) if err != nil { return 0, errors.Trace(err) } hasRecordID = true break } } if !hasRecordID { recordID, err = t.alloc.Alloc(t.ID) if err != nil { return 0, errors.Trace(err) } } txn, err := ctx.GetTxn(false) if err != nil { return 0, errors.Trace(err) } bs := kv.NewBufferStore(txn) defer bs.Release() if t.meta.PKIsHandle { // Check key exists. recordKey := t.RecordKey(recordID, nil) _, err = txn.Get(recordKey) if err == nil { return recordID, kv.ErrKeyExists } else if !terror.ErrorEqual(err, kv.ErrNotExist) { return 0, errors.Trace(err) } } for _, v := range t.indices { if v == nil || v.State == model.StateDeleteOnly || v.State == model.StateDeleteReorganization { // if index is in delete only or delete reorganization state, we can't add it. continue } colVals, _ := v.FetchValues(r) if err = v.X.Create(bs, colVals, recordID); err != nil { if terror.ErrorEqual(err, kv.ErrKeyExists) { // Get the duplicate row handle // For insert on duplicate syntax, we should update the row iter, _, err1 := v.X.Seek(bs, colVals) if err1 != nil { return 0, errors.Trace(err1) } _, h, err1 := iter.Next() if err1 != nil { return 0, errors.Trace(err1) } return h, errors.Trace(err) } return 0, errors.Trace(err) } } if err = t.LockRow(ctx, recordID); err != nil { return 0, errors.Trace(err) } // Set public and write only column value. for _, col := range t.writableCols() { if col.IsPKHandleColumn(t.meta) { continue } var value interface{} if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization { // if col is in write only or write reorganization state, we must add it with its default value. value, _, err = GetColDefaultValue(ctx, &col.ColumnInfo) if err != nil { return 0, errors.Trace(err) } value, err = types.Convert(value, &col.FieldType) if err != nil { return 0, errors.Trace(err) } } else { value = r[col.Offset] } key := t.RecordKey(recordID, col) err = t.SetColValue(txn, key, value) if err != nil { return 0, errors.Trace(err) } } if err = bs.SaveTo(txn); err != nil { return 0, errors.Trace(err) } variable.GetSessionVars(ctx).AddAffectedRows(1) return recordID, nil }