github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/table/tables/tables.go (about) 1 // Copyright 2013 The ql Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSES/QL-LICENSE file. 4 5 // Copyright 2015 PingCAP, Inc. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package tables 19 20 import ( 21 "strings" 22 "time" 23 24 "github.com/insionng/yougam/libraries/juju/errors" 25 "github.com/insionng/yougam/libraries/ngaut/log" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 28 "github.com/insionng/yougam/libraries/pingcap/tidb/evaluator" 29 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 30 "github.com/insionng/yougam/libraries/pingcap/tidb/meta/autoid" 31 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 32 "github.com/insionng/yougam/libraries/pingcap/tidb/mysql" 33 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/variable" 34 "github.com/insionng/yougam/libraries/pingcap/tidb/table" 35 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 36 "github.com/insionng/yougam/libraries/pingcap/tidb/util" 37 "github.com/insionng/yougam/libraries/pingcap/tidb/util/codec" 38 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 39 ) 40 41 // TablePrefix is the prefix for table record and index key. 42 var TablePrefix = []byte{'t'} 43 44 // Table implements table.Table interface. 45 type Table struct { 46 ID int64 47 Name model.CIStr 48 Columns []*column.Col 49 50 publicColumns []*column.Col 51 writableColumns []*column.Col 52 indices []*column.IndexedCol 53 recordPrefix kv.Key 54 indexPrefix kv.Key 55 alloc autoid.Allocator 56 meta *model.TableInfo 57 } 58 59 // MockTableFromMeta only serves for test. 60 func MockTableFromMeta(tableInfo *model.TableInfo) table.Table { 61 return &Table{ID: 0, meta: tableInfo} 62 } 63 64 // TableFromMeta creates a Table instance from model.TableInfo. 65 func TableFromMeta(alloc autoid.Allocator, tblInfo *model.TableInfo) (table.Table, error) { 66 if tblInfo.State == model.StateNone { 67 return nil, errors.Errorf("table %s can't be in none state", tblInfo.Name) 68 } 69 70 columns := make([]*column.Col, 0, len(tblInfo.Columns)) 71 for _, colInfo := range tblInfo.Columns { 72 if colInfo.State == model.StateNone { 73 return nil, errors.Errorf("column %s can't be in none state", colInfo.Name) 74 } 75 76 col := &column.Col{ColumnInfo: *colInfo} 77 columns = append(columns, col) 78 } 79 80 t := newTable(tblInfo.ID, columns, alloc) 81 82 for _, idxInfo := range tblInfo.Indices { 83 if idxInfo.State == model.StateNone { 84 return nil, errors.Errorf("index %s can't be in none state", idxInfo.Name) 85 } 86 87 idx := &column.IndexedCol{ 88 IndexInfo: *idxInfo, 89 } 90 91 idx.X = kv.NewKVIndex(t.IndexPrefix(), idxInfo.Name.L, idxInfo.ID, idxInfo.Unique) 92 93 t.indices = append(t.indices, idx) 94 } 95 96 t.meta = tblInfo 97 return t, nil 98 } 99 100 // newTable constructs a Table instance. 101 func newTable(tableID int64, cols []*column.Col, alloc autoid.Allocator) *Table { 102 t := &Table{ 103 ID: tableID, 104 recordPrefix: genTableRecordPrefix(tableID), 105 indexPrefix: genTableIndexPrefix(tableID), 106 alloc: alloc, 107 Columns: cols, 108 } 109 110 t.publicColumns = t.Cols() 111 t.writableColumns = t.writableCols() 112 return t 113 } 114 115 // Indices implements table.Table Indices interface. 116 func (t *Table) Indices() []*column.IndexedCol { 117 return t.indices 118 } 119 120 // Meta implements table.Table Meta interface. 121 func (t *Table) Meta() *model.TableInfo { 122 return t.meta 123 } 124 125 // Cols implements table.Table Cols interface. 126 func (t *Table) Cols() []*column.Col { 127 if len(t.publicColumns) > 0 { 128 return t.publicColumns 129 } 130 131 t.publicColumns = make([]*column.Col, 0, len(t.Columns)) 132 for _, col := range t.Columns { 133 if col.State == model.StatePublic { 134 t.publicColumns = append(t.publicColumns, col) 135 } 136 } 137 138 return t.publicColumns 139 } 140 141 func (t *Table) writableCols() []*column.Col { 142 if len(t.writableColumns) > 0 { 143 return t.writableColumns 144 } 145 146 t.writableColumns = make([]*column.Col, 0, len(t.Columns)) 147 for _, col := range t.Columns { 148 if col.State == model.StateDeleteOnly || col.State == model.StateDeleteReorganization { 149 continue 150 } 151 152 t.writableColumns = append(t.writableColumns, col) 153 } 154 155 return t.writableColumns 156 } 157 158 // RecordPrefix implements table.Table RecordPrefix interface. 159 func (t *Table) RecordPrefix() kv.Key { 160 return t.recordPrefix 161 } 162 163 // IndexPrefix implements table.Table IndexPrefix interface. 164 func (t *Table) IndexPrefix() kv.Key { 165 return t.indexPrefix 166 } 167 168 // RecordKey implements table.Table RecordKey interface. 169 func (t *Table) RecordKey(h int64, col *column.Col) kv.Key { 170 colID := int64(0) 171 if col != nil { 172 colID = col.ID 173 } 174 return encodeRecordKey(t.recordPrefix, h, colID) 175 } 176 177 // FirstKey implements table.Table FirstKey interface. 178 func (t *Table) FirstKey() kv.Key { 179 return t.RecordKey(0, nil) 180 } 181 182 // Truncate implements table.Table Truncate interface. 183 func (t *Table) Truncate(ctx context.Context) error { 184 txn, err := ctx.GetTxn(false) 185 if err != nil { 186 return errors.Trace(err) 187 } 188 err = util.DelKeyWithPrefix(txn, t.RecordPrefix()) 189 if err != nil { 190 return errors.Trace(err) 191 } 192 return util.DelKeyWithPrefix(txn, t.IndexPrefix()) 193 } 194 195 // UpdateRecord implements table.Table UpdateRecord interface. 196 func (t *Table) UpdateRecord(ctx context.Context, h int64, oldData []types.Datum, newData []types.Datum, touched map[int]bool) error { 197 // We should check whether this table has on update column which state is write only. 198 currentData := make([]types.Datum, len(t.writableCols())) 199 copy(currentData, newData) 200 201 // If they are not set, and other data are changed, they will be updated by current timestamp too. 202 err := t.setOnUpdateData(ctx, touched, currentData) 203 if err != nil { 204 return errors.Trace(err) 205 } 206 207 txn, err := ctx.GetTxn(false) 208 if err != nil { 209 return errors.Trace(err) 210 } 211 212 bs := kv.NewBufferStore(txn) 213 defer bs.Release() 214 215 // set new value 216 if err = t.setNewData(bs, h, touched, currentData); err != nil { 217 return errors.Trace(err) 218 } 219 220 // rebuild index 221 if err = t.rebuildIndices(bs, h, touched, oldData, currentData); err != nil { 222 return errors.Trace(err) 223 } 224 225 err = bs.SaveTo(txn) 226 if err != nil { 227 return errors.Trace(err) 228 } 229 230 return nil 231 } 232 233 func (t *Table) setOnUpdateData(ctx context.Context, touched map[int]bool, data []types.Datum) error { 234 ucols := column.FindOnUpdateCols(t.writableCols()) 235 for _, col := range ucols { 236 if !touched[col.Offset] { 237 value, err := evaluator.GetTimeValue(ctx, evaluator.CurrentTimestamp, col.Tp, col.Decimal) 238 if err != nil { 239 return errors.Trace(err) 240 } 241 242 data[col.Offset] = value 243 touched[col.Offset] = true 244 } 245 } 246 return nil 247 } 248 func (t *Table) setNewData(rm kv.RetrieverMutator, h int64, touched map[int]bool, data []types.Datum) error { 249 for _, col := range t.Cols() { 250 if !touched[col.Offset] { 251 continue 252 } 253 254 k := t.RecordKey(h, col) 255 if err := SetColValue(rm, k, data[col.Offset]); err != nil { 256 return errors.Trace(err) 257 } 258 } 259 260 return nil 261 } 262 263 func (t *Table) rebuildIndices(rm kv.RetrieverMutator, h int64, touched map[int]bool, oldData []types.Datum, newData []types.Datum) error { 264 for _, idx := range t.Indices() { 265 idxTouched := false 266 for _, ic := range idx.Columns { 267 if touched[ic.Offset] { 268 idxTouched = true 269 break 270 } 271 } 272 if !idxTouched { 273 continue 274 } 275 276 oldVs, err := idx.FetchValues(oldData) 277 if err != nil { 278 return errors.Trace(err) 279 } 280 281 if t.removeRowIndex(rm, h, oldVs, idx); err != nil { 282 return errors.Trace(err) 283 } 284 285 newVs, err := idx.FetchValues(newData) 286 if err != nil { 287 return errors.Trace(err) 288 } 289 290 if err := t.buildIndexForRow(rm, h, newVs, idx); err != nil { 291 return errors.Trace(err) 292 } 293 } 294 return nil 295 } 296 297 // AddRecord implements table.Table AddRecord interface. 298 func (t *Table) AddRecord(ctx context.Context, r []types.Datum) (recordID int64, err error) { 299 var hasRecordID bool 300 for _, col := range t.Cols() { 301 if col.IsPKHandleColumn(t.meta) { 302 recordID = r[col.Offset].GetInt64() 303 hasRecordID = true 304 break 305 } 306 } 307 if !hasRecordID { 308 recordID, err = t.alloc.Alloc(t.ID) 309 if err != nil { 310 return 0, errors.Trace(err) 311 } 312 } 313 txn, err := ctx.GetTxn(false) 314 if err != nil { 315 return 0, errors.Trace(err) 316 } 317 bs := kv.NewBufferStore(txn) 318 defer bs.Release() 319 // Insert new entries into indices. 320 h, err := t.addIndices(ctx, recordID, r, bs) 321 if err != nil { 322 return h, errors.Trace(err) 323 } 324 325 if err = t.LockRow(ctx, recordID, false); err != nil { 326 return 0, errors.Trace(err) 327 } 328 // Set public and write only column value. 329 for _, col := range t.writableCols() { 330 if col.IsPKHandleColumn(t.meta) { 331 continue 332 } 333 if col.DefaultValue == nil && r[col.Offset].Kind() == types.KindNull { 334 // Save storage space by not storing null value. 335 continue 336 } 337 var value types.Datum 338 if col.State == model.StateWriteOnly || col.State == model.StateWriteReorganization { 339 // if col is in write only or write reorganization state, we must add it with its default value. 340 value, _, err = table.GetColDefaultValue(ctx, &col.ColumnInfo) 341 if err != nil { 342 return 0, errors.Trace(err) 343 } 344 value, err = value.ConvertTo(&col.FieldType) 345 if err != nil { 346 return 0, errors.Trace(err) 347 } 348 } else { 349 value = r[col.Offset] 350 } 351 352 key := t.RecordKey(recordID, col) 353 err = SetColValue(txn, key, value) 354 if err != nil { 355 return 0, errors.Trace(err) 356 } 357 } 358 if err = bs.SaveTo(txn); err != nil { 359 return 0, errors.Trace(err) 360 } 361 362 variable.GetSessionVars(ctx).AddAffectedRows(1) 363 return recordID, nil 364 } 365 366 // Generate index content string representation. 367 func (t *Table) genIndexKeyStr(colVals []types.Datum) (string, error) { 368 // Pass pre-composed error to txn. 369 strVals := make([]string, 0, len(colVals)) 370 for _, cv := range colVals { 371 cvs := "NULL" 372 var err error 373 if cv.Kind() != types.KindNull { 374 cvs, err = types.ToString(cv.GetValue()) 375 if err != nil { 376 return "", errors.Trace(err) 377 } 378 } 379 strVals = append(strVals, cvs) 380 } 381 return strings.Join(strVals, "-"), nil 382 } 383 384 // Add data into indices. 385 func (t *Table) addIndices(ctx context.Context, recordID int64, r []types.Datum, bs *kv.BufferStore) (int64, error) { 386 txn, err := ctx.GetTxn(false) 387 if err != nil { 388 return 0, errors.Trace(err) 389 } 390 // Clean up lazy check error environment 391 defer txn.DelOption(kv.PresumeKeyNotExistsError) 392 if t.meta.PKIsHandle { 393 // Check key exists. 394 recordKey := t.RecordKey(recordID, nil) 395 e := kv.ErrKeyExists.Gen("Duplicate entry '%d' for key 'PRIMARY'", recordID) 396 txn.SetOption(kv.PresumeKeyNotExistsError, e) 397 _, err = txn.Get(recordKey) 398 if err == nil { 399 return recordID, errors.Trace(e) 400 } else if !terror.ErrorEqual(err, kv.ErrNotExist) { 401 return 0, errors.Trace(err) 402 } 403 txn.DelOption(kv.PresumeKeyNotExistsError) 404 } 405 406 for _, v := range t.indices { 407 if v == nil || v.State == model.StateDeleteOnly || v.State == model.StateDeleteReorganization { 408 // if index is in delete only or delete reorganization state, we can't add it. 409 continue 410 } 411 colVals, _ := v.FetchValues(r) 412 var dupKeyErr error 413 if v.Unique || v.Primary { 414 entryKey, err1 := t.genIndexKeyStr(colVals) 415 if err1 != nil { 416 return 0, errors.Trace(err1) 417 } 418 dupKeyErr = kv.ErrKeyExists.Gen("Duplicate entry '%s' for key '%s'", entryKey, v.Name) 419 txn.SetOption(kv.PresumeKeyNotExistsError, dupKeyErr) 420 } 421 if err = v.X.Create(bs, colVals, recordID); err != nil { 422 if terror.ErrorEqual(err, kv.ErrKeyExists) { 423 // Get the duplicate row handle 424 // For insert on duplicate syntax, we should update the row 425 iter, _, err1 := v.X.Seek(bs, colVals) 426 if err1 != nil { 427 return 0, errors.Trace(err1) 428 } 429 _, h, err1 := iter.Next() 430 if err1 != nil { 431 return 0, errors.Trace(err1) 432 } 433 return h, errors.Trace(dupKeyErr) 434 } 435 return 0, errors.Trace(err) 436 } 437 txn.DelOption(kv.PresumeKeyNotExistsError) 438 } 439 return 0, nil 440 } 441 442 // RowWithCols implements table.Table RowWithCols interface. 443 func (t *Table) RowWithCols(ctx context.Context, h int64, cols []*column.Col) ([]types.Datum, error) { 444 txn, err := ctx.GetTxn(false) 445 if err != nil { 446 return nil, errors.Trace(err) 447 } 448 v := make([]types.Datum, len(cols)) 449 for i, col := range cols { 450 if col == nil { 451 continue 452 } 453 if col.State != model.StatePublic { 454 return nil, errors.Errorf("Cannot use none public column - %v", cols) 455 } 456 if col.IsPKHandleColumn(t.meta) { 457 if mysql.HasUnsignedFlag(col.Flag) { 458 v[i].SetUint64(uint64(h)) 459 } else { 460 v[i].SetInt64(h) 461 } 462 continue 463 } 464 465 k := t.RecordKey(h, col) 466 data, err := txn.Get(k) 467 if terror.ErrorEqual(err, kv.ErrNotExist) && !mysql.HasNotNullFlag(col.Flag) { 468 continue 469 } else if err != nil { 470 return nil, errors.Trace(err) 471 } 472 473 v[i], err = DecodeValue(data, &col.FieldType) 474 if err != nil { 475 return nil, errors.Trace(err) 476 } 477 } 478 return v, nil 479 } 480 481 // Row implements table.Table Row interface. 482 func (t *Table) Row(ctx context.Context, h int64) ([]types.Datum, error) { 483 // TODO: we only interested in mentioned cols 484 r, err := t.RowWithCols(ctx, h, t.Cols()) 485 if err != nil { 486 return nil, errors.Trace(err) 487 } 488 return r, nil 489 } 490 491 // LockRow implements table.Table LockRow interface. 492 func (t *Table) LockRow(ctx context.Context, h int64, forRead bool) error { 493 txn, err := ctx.GetTxn(false) 494 if err != nil { 495 return errors.Trace(err) 496 } 497 // Get row lock key 498 lockKey := t.RecordKey(h, nil) 499 if forRead { 500 err = txn.LockKeys(lockKey) 501 } else { 502 // set row lock key to current txn 503 err = txn.Set(lockKey, []byte(txn.String())) 504 } 505 return errors.Trace(err) 506 } 507 508 // RemoveRecord implements table.Table RemoveRecord interface. 509 func (t *Table) RemoveRecord(ctx context.Context, h int64, r []types.Datum) error { 510 err := t.removeRowData(ctx, h) 511 if err != nil { 512 return errors.Trace(err) 513 } 514 515 err = t.removeRowIndices(ctx, h, r) 516 if err != nil { 517 return errors.Trace(err) 518 } 519 520 return nil 521 } 522 523 func (t *Table) removeRowData(ctx context.Context, h int64) error { 524 if err := t.LockRow(ctx, h, false); err != nil { 525 return errors.Trace(err) 526 } 527 txn, err := ctx.GetTxn(false) 528 if err != nil { 529 return errors.Trace(err) 530 } 531 // Remove row's colume one by one 532 for _, col := range t.Columns { 533 k := t.RecordKey(h, col) 534 err = txn.Delete([]byte(k)) 535 if err != nil { 536 if col.State != model.StatePublic && terror.ErrorEqual(err, kv.ErrNotExist) { 537 // If the column is not in public state, we may have not added the column, 538 // or already deleted the column, so skip ErrNotExist error. 539 continue 540 } 541 542 return errors.Trace(err) 543 } 544 } 545 // Remove row lock 546 err = txn.Delete([]byte(t.RecordKey(h, nil))) 547 if err != nil { 548 return errors.Trace(err) 549 } 550 return nil 551 } 552 553 // removeRowAllIndex removes all the indices of a row. 554 func (t *Table) removeRowIndices(ctx context.Context, h int64, rec []types.Datum) error { 555 for _, v := range t.indices { 556 vals, err := v.FetchValues(rec) 557 if vals == nil { 558 // TODO: check this 559 continue 560 } 561 txn, err := ctx.GetTxn(false) 562 if err != nil { 563 return errors.Trace(err) 564 } 565 if err = v.X.Delete(txn, vals, h); err != nil { 566 if v.State != model.StatePublic && terror.ErrorEqual(err, kv.ErrNotExist) { 567 // If the index is not in public state, we may have not created the index, 568 // or already deleted the index, so skip ErrNotExist error. 569 continue 570 } 571 572 return errors.Trace(err) 573 } 574 } 575 return nil 576 } 577 578 // RemoveRowIndex implements table.Table RemoveRowIndex interface. 579 func (t *Table) removeRowIndex(rm kv.RetrieverMutator, h int64, vals []types.Datum, idx *column.IndexedCol) error { 580 if err := idx.X.Delete(rm, vals, h); err != nil { 581 return errors.Trace(err) 582 } 583 return nil 584 } 585 586 // BuildIndexForRow implements table.Table BuildIndexForRow interface. 587 func (t *Table) buildIndexForRow(rm kv.RetrieverMutator, h int64, vals []types.Datum, idx *column.IndexedCol) error { 588 if idx.State == model.StateDeleteOnly || idx.State == model.StateDeleteReorganization { 589 // If the index is in delete only or write reorganization state, we can not add index. 590 return nil 591 } 592 593 if err := idx.X.Create(rm, vals, h); err != nil { 594 return errors.Trace(err) 595 } 596 return nil 597 } 598 599 // IterRecords implements table.Table IterRecords interface. 600 func (t *Table) IterRecords(ctx context.Context, startKey kv.Key, cols []*column.Col, 601 fn table.RecordIterFunc) error { 602 txn, err := ctx.GetTxn(false) 603 if err != nil { 604 return errors.Trace(err) 605 } 606 it, err := txn.Seek(startKey) 607 if err != nil { 608 return errors.Trace(err) 609 } 610 defer it.Close() 611 612 if !it.Valid() { 613 return nil 614 } 615 616 log.Debugf("startKey:%q, key:%q, value:%q", startKey, it.Key(), it.Value()) 617 618 prefix := t.RecordPrefix() 619 for it.Valid() && it.Key().HasPrefix(prefix) { 620 // first kv pair is row lock information. 621 // TODO: check valid lock 622 // get row handle 623 handle, err := DecodeRecordKeyHandle(it.Key()) 624 if err != nil { 625 return errors.Trace(err) 626 } 627 628 data, err := t.RowWithCols(ctx, handle, cols) 629 if err != nil { 630 return errors.Trace(err) 631 } 632 more, err := fn(handle, data, cols) 633 if !more || err != nil { 634 return errors.Trace(err) 635 } 636 637 rk := t.RecordKey(handle, nil) 638 err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)) 639 if err != nil { 640 return errors.Trace(err) 641 } 642 } 643 644 return nil 645 } 646 647 // AllocAutoID implements table.Table AllocAutoID interface. 648 func (t *Table) AllocAutoID() (int64, error) { 649 return t.alloc.Alloc(t.ID) 650 } 651 652 // RebaseAutoID implements table.Table RebaseAutoID interface. 653 func (t *Table) RebaseAutoID(newBase int64, isSetStep bool) error { 654 return t.alloc.Rebase(t.ID, newBase, isSetStep) 655 } 656 657 // Seek implements table.Table Seek interface. 658 func (t *Table) Seek(ctx context.Context, h int64) (int64, bool, error) { 659 seekKey := EncodeRecordKey(t.ID, h, 0) 660 txn, err := ctx.GetTxn(false) 661 if err != nil { 662 return 0, false, errors.Trace(err) 663 } 664 iter, err := txn.Seek(seekKey) 665 if !iter.Valid() || !iter.Key().HasPrefix(t.RecordPrefix()) { 666 // No more records in the table, skip to the end. 667 return 0, false, nil 668 } 669 handle, err := DecodeRecordKeyHandle(iter.Key()) 670 if err != nil { 671 return 0, false, errors.Trace(err) 672 } 673 return handle, true, nil 674 } 675 676 var ( 677 recordPrefixSep = []byte("_r") 678 indexPrefixSep = []byte("_i") 679 ) 680 681 // record prefix is "t[tableID]_r" 682 func genTableRecordPrefix(tableID int64) kv.Key { 683 buf := make([]byte, 0, len(TablePrefix)+8+len(recordPrefixSep)) 684 buf = append(buf, TablePrefix...) 685 buf = codec.EncodeInt(buf, tableID) 686 buf = append(buf, recordPrefixSep...) 687 return buf 688 } 689 690 // index prefix is "t[tableID]_i" 691 func genTableIndexPrefix(tableID int64) kv.Key { 692 buf := make([]byte, 0, len(TablePrefix)+8+len(indexPrefixSep)) 693 buf = append(buf, TablePrefix...) 694 buf = codec.EncodeInt(buf, tableID) 695 buf = append(buf, indexPrefixSep...) 696 return buf 697 } 698 699 func encodeRecordKey(recordPrefix kv.Key, h int64, columnID int64) kv.Key { 700 buf := make([]byte, 0, len(recordPrefix)+16) 701 buf = append(buf, recordPrefix...) 702 buf = codec.EncodeInt(buf, h) 703 704 if columnID != 0 { 705 buf = codec.EncodeInt(buf, columnID) 706 } 707 return buf 708 } 709 710 // EncodeRecordKey encodes the record key for a table column. 711 func EncodeRecordKey(tableID int64, h int64, columnID int64) kv.Key { 712 prefix := genTableRecordPrefix(tableID) 713 return encodeRecordKey(prefix, h, columnID) 714 } 715 716 // DecodeRecordKey decodes the key and gets the tableID, handle and columnID. 717 func DecodeRecordKey(key kv.Key) (tableID int64, handle int64, columnID int64, err error) { 718 k := key 719 if !key.HasPrefix(TablePrefix) { 720 return 0, 0, 0, errors.Errorf("invalid record key - %q", k) 721 } 722 723 key = key[len(TablePrefix):] 724 key, tableID, err = codec.DecodeInt(key) 725 if err != nil { 726 return 0, 0, 0, errors.Trace(err) 727 } 728 729 if !key.HasPrefix(recordPrefixSep) { 730 return 0, 0, 0, errors.Errorf("invalid record key - %q", k) 731 } 732 733 key = key[len(recordPrefixSep):] 734 735 key, handle, err = codec.DecodeInt(key) 736 if err != nil { 737 return 0, 0, 0, errors.Trace(err) 738 } 739 if len(key) == 0 { 740 return 741 } 742 743 key, columnID, err = codec.DecodeInt(key) 744 if err != nil { 745 return 0, 0, 0, errors.Trace(err) 746 } 747 748 return 749 } 750 751 // EncodeValue encodes a go value to bytes. 752 func EncodeValue(raw types.Datum) ([]byte, error) { 753 v, err := flatten(raw) 754 if err != nil { 755 return nil, errors.Trace(err) 756 } 757 b, err := codec.EncodeValue(nil, v) 758 return b, errors.Trace(err) 759 } 760 761 // DecodeValue implements table.Table DecodeValue interface. 762 func DecodeValue(data []byte, tp *types.FieldType) (types.Datum, error) { 763 values, err := codec.Decode(data) 764 if err != nil { 765 return types.Datum{}, errors.Trace(err) 766 } 767 return unflatten(values[0], tp) 768 } 769 770 func flatten(data types.Datum) (types.Datum, error) { 771 switch data.Kind() { 772 case types.KindMysqlTime: 773 // for mysql datetime, timestamp and date type 774 b, err := data.GetMysqlTime().Marshal() 775 if err != nil { 776 return types.NewDatum(nil), errors.Trace(err) 777 } 778 return types.NewDatum(b), nil 779 case types.KindMysqlDuration: 780 // for mysql time type 781 data.SetInt64(int64(data.GetMysqlDuration().Duration)) 782 return data, nil 783 case types.KindMysqlDecimal: 784 data.SetString(data.GetMysqlDecimal().String()) 785 return data, nil 786 case types.KindMysqlEnum: 787 data.SetUint64(data.GetMysqlEnum().Value) 788 return data, nil 789 case types.KindMysqlSet: 790 data.SetUint64(data.GetMysqlSet().Value) 791 return data, nil 792 case types.KindMysqlBit: 793 data.SetUint64(data.GetMysqlBit().Value) 794 return data, nil 795 case types.KindMysqlHex: 796 data.SetInt64(data.GetMysqlHex().Value) 797 return data, nil 798 default: 799 return data, nil 800 } 801 } 802 803 func unflatten(datum types.Datum, tp *types.FieldType) (types.Datum, error) { 804 if datum.Kind() == types.KindNull { 805 return datum, nil 806 } 807 switch tp.Tp { 808 case mysql.TypeFloat: 809 datum.SetFloat32(float32(datum.GetFloat64())) 810 return datum, nil 811 case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, 812 mysql.TypeDouble, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, 813 mysql.TypeVarchar, mysql.TypeString: 814 return datum, nil 815 case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: 816 var t mysql.Time 817 t.Type = tp.Tp 818 t.Fsp = tp.Decimal 819 err := t.Unmarshal(datum.GetBytes()) 820 if err != nil { 821 return datum, errors.Trace(err) 822 } 823 datum.SetValue(t) 824 return datum, nil 825 case mysql.TypeDuration: 826 dur := mysql.Duration{Duration: time.Duration(datum.GetInt64())} 827 datum.SetValue(dur) 828 return datum, nil 829 case mysql.TypeNewDecimal, mysql.TypeDecimal: 830 dec, err := mysql.ParseDecimal(datum.GetString()) 831 if err != nil { 832 return datum, errors.Trace(err) 833 } 834 datum.SetValue(dec) 835 return datum, nil 836 case mysql.TypeEnum: 837 enum, err := mysql.ParseEnumValue(tp.Elems, datum.GetUint64()) 838 if err != nil { 839 return datum, errors.Trace(err) 840 } 841 datum.SetValue(enum) 842 return datum, nil 843 case mysql.TypeSet: 844 set, err := mysql.ParseSetValue(tp.Elems, datum.GetUint64()) 845 if err != nil { 846 return datum, errors.Trace(err) 847 } 848 datum.SetValue(set) 849 return datum, nil 850 case mysql.TypeBit: 851 bit := mysql.Bit{Value: datum.GetUint64(), Width: tp.Flen} 852 datum.SetValue(bit) 853 return datum, nil 854 } 855 log.Error(tp.Tp, datum) 856 return datum, nil 857 } 858 859 // SetColValue implements table.Table SetColValue interface. 860 func SetColValue(rm kv.RetrieverMutator, key []byte, data types.Datum) error { 861 v, err := EncodeValue(data) 862 if err != nil { 863 return errors.Trace(err) 864 } 865 if err := rm.Set(key, v); err != nil { 866 return errors.Trace(err) 867 } 868 return nil 869 } 870 871 // DecodeRecordKeyHandle decodes the key and gets the record handle. 872 func DecodeRecordKeyHandle(key kv.Key) (int64, error) { 873 _, handle, _, err := DecodeRecordKey(key) 874 return handle, errors.Trace(err) 875 } 876 877 // FindIndexByColName implements table.Table FindIndexByColName interface. 878 func FindIndexByColName(t table.Table, name string) *column.IndexedCol { 879 for _, idx := range t.Indices() { 880 // only public index can be read. 881 if idx.State != model.StatePublic { 882 continue 883 } 884 885 if len(idx.Columns) == 1 && strings.EqualFold(idx.Columns[0].Name.L, name) { 886 return idx 887 } 888 } 889 return nil 890 } 891 892 func init() { 893 table.TableFromMeta = TableFromMeta 894 table.MockTableFromMeta = MockTableFromMeta 895 }