github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/executor/executor_write.go (about) 1 // Copyright 2016 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package executor 15 16 import ( 17 "fmt" 18 "strings" 19 20 "github.com/insionng/yougam/libraries/juju/errors" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/ast" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 24 "github.com/insionng/yougam/libraries/pingcap/tidb/evaluator" 25 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/mysql" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx" 28 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/variable" 29 "github.com/insionng/yougam/libraries/pingcap/tidb/table" 30 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 31 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 32 ) 33 34 var ( 35 _ Executor = &UpdateExec{} 36 _ Executor = &DeleteExec{} 37 _ Executor = &InsertExec{} 38 ) 39 40 // UpdateExec represents an update executor. 41 type UpdateExec struct { 42 SelectExec Executor 43 OrderedList []*ast.Assignment 44 45 // Map for unique (Table, handle) pair. 46 updatedRowKeys map[table.Table]map[int64]struct{} 47 ctx context.Context 48 49 rows []*Row // The rows fetched from TableExec. 50 newRowsData [][]types.Datum // The new values to be set. 51 fetched bool 52 cursor int 53 } 54 55 // Next implements Executor Next interface. 56 func (e *UpdateExec) Next() (*Row, error) { 57 if !e.fetched { 58 err := e.fetchRows() 59 if err != nil { 60 return nil, errors.Trace(err) 61 } 62 e.fetched = true 63 } 64 65 columns, err := getUpdateColumns(e.OrderedList) 66 if err != nil { 67 return nil, errors.Trace(err) 68 } 69 if e.cursor >= len(e.rows) { 70 return nil, nil 71 } 72 if e.updatedRowKeys == nil { 73 e.updatedRowKeys = make(map[table.Table]map[int64]struct{}) 74 } 75 row := e.rows[e.cursor] 76 newData := e.newRowsData[e.cursor] 77 for _, entry := range row.RowKeys { 78 tbl := entry.Tbl 79 if e.updatedRowKeys[tbl] == nil { 80 e.updatedRowKeys[tbl] = make(map[int64]struct{}) 81 } 82 offset := e.getTableOffset(tbl) 83 handle := entry.Handle 84 oldData := row.Data[offset : offset+len(tbl.Cols())] 85 newTableData := newData[offset : offset+len(tbl.Cols())] 86 87 _, ok := e.updatedRowKeys[tbl][handle] 88 if ok { 89 // Each matching row is updated once, even if it matches the conditions multiple times. 90 continue 91 } 92 // Update row 93 err1 := updateRecord(e.ctx, handle, oldData, newTableData, columns, tbl, offset, false) 94 if err1 != nil { 95 return nil, errors.Trace(err1) 96 } 97 e.updatedRowKeys[tbl][handle] = struct{}{} 98 } 99 e.cursor++ 100 return &Row{}, nil 101 } 102 103 func getUpdateColumns(assignList []*ast.Assignment) (map[int]*ast.Assignment, error) { 104 m := make(map[int]*ast.Assignment, len(assignList)) 105 for i, v := range assignList { 106 m[i] = v 107 } 108 return m, nil 109 } 110 111 func (e *UpdateExec) fetchRows() error { 112 for { 113 row, err := e.SelectExec.Next() 114 if err != nil { 115 return errors.Trace(err) 116 } 117 if row == nil { 118 return nil 119 } 120 data := make([]types.Datum, len(e.SelectExec.Fields())) 121 newData := make([]types.Datum, len(e.SelectExec.Fields())) 122 for i, f := range e.SelectExec.Fields() { 123 data[i] = types.NewDatum(f.Expr.GetValue()) 124 newData[i] = data[i] 125 if e.OrderedList[i] != nil { 126 val, err := evaluator.Eval(e.ctx, e.OrderedList[i].Expr) 127 if err != nil { 128 return errors.Trace(err) 129 } 130 newData[i] = val 131 } 132 } 133 row.Data = data 134 e.rows = append(e.rows, row) 135 e.newRowsData = append(e.newRowsData, newData) 136 } 137 } 138 139 func (e *UpdateExec) getTableOffset(t table.Table) int { 140 fields := e.SelectExec.Fields() 141 i := 0 142 for i < len(fields) { 143 field := fields[i] 144 if field.Table.Name.L == t.Meta().Name.L { 145 return i 146 } 147 i += len(field.Table.Columns) 148 } 149 return 0 150 } 151 152 func updateRecord(ctx context.Context, h int64, oldData, newData []types.Datum, updateColumns map[int]*ast.Assignment, t table.Table, offset int, onDuplicateUpdate bool) error { 153 if err := t.LockRow(ctx, h, false); err != nil { 154 return errors.Trace(err) 155 } 156 157 cols := t.Cols() 158 touched := make(map[int]bool, len(cols)) 159 160 assignExists := false 161 var newHandle types.Datum 162 for i, asgn := range updateColumns { 163 if asgn == nil { 164 continue 165 } 166 if i < offset || i >= offset+len(cols) { 167 // The assign expression is for another table, not this. 168 continue 169 } 170 171 colIndex := i - offset 172 col := cols[colIndex] 173 if col.IsPKHandleColumn(t.Meta()) { 174 newHandle = newData[i] 175 } 176 if mysql.HasAutoIncrementFlag(col.Flag) { 177 if newData[i].Kind() == types.KindNull { 178 return errors.Errorf("Column '%v' cannot be null", col.Name.O) 179 } 180 val, err := newData[i].ToInt64() 181 if err != nil { 182 return errors.Trace(err) 183 } 184 t.RebaseAutoID(val, true) 185 } 186 187 touched[colIndex] = true 188 assignExists = true 189 } 190 191 // If no assign list for this table, no need to update. 192 if !assignExists { 193 return nil 194 } 195 196 // Check whether new value is valid. 197 if err := column.CastValues(ctx, newData, cols); err != nil { 198 return errors.Trace(err) 199 } 200 201 if err := column.CheckNotNull(cols, newData); err != nil { 202 return errors.Trace(err) 203 } 204 205 // If row is not changed, we should do nothing. 206 rowChanged := false 207 for i := range oldData { 208 if !touched[i] { 209 continue 210 } 211 212 n, err := newData[i].CompareDatum(oldData[i]) 213 if err != nil { 214 return errors.Trace(err) 215 } 216 if n != 0 { 217 rowChanged = true 218 break 219 } 220 } 221 if !rowChanged { 222 // See: https://dev.mysql.com/doc/refman/5.7/en/mysql-real-connect.html CLIENT_FOUND_ROWS 223 if variable.GetSessionVars(ctx).ClientCapability&mysql.ClientFoundRows > 0 { 224 variable.GetSessionVars(ctx).AddAffectedRows(1) 225 } 226 return nil 227 } 228 229 var err error 230 if newHandle.Kind() != types.KindNull { 231 err = t.RemoveRecord(ctx, h, oldData) 232 if err != nil { 233 return errors.Trace(err) 234 } 235 _, err = t.AddRecord(ctx, newData) 236 } else { 237 // Update record to new value and update index. 238 err = t.UpdateRecord(ctx, h, oldData, newData, touched) 239 } 240 if err != nil { 241 return errors.Trace(err) 242 } 243 244 // Record affected rows. 245 if !onDuplicateUpdate { 246 variable.GetSessionVars(ctx).AddAffectedRows(1) 247 } else { 248 variable.GetSessionVars(ctx).AddAffectedRows(2) 249 } 250 return nil 251 } 252 253 // Fields implements Executor Fields interface. 254 // Returns nil to indicate there is no output. 255 func (e *UpdateExec) Fields() []*ast.ResultField { 256 return nil 257 } 258 259 // Close implements Executor Close interface. 260 func (e *UpdateExec) Close() error { 261 return e.SelectExec.Close() 262 } 263 264 // DeleteExec represents a delete executor. 265 // See: https://dev.mysql.com/doc/refman/5.7/en/delete.html 266 type DeleteExec struct { 267 SelectExec Executor 268 269 ctx context.Context 270 Tables []*ast.TableName 271 IsMultiTable bool 272 273 finished bool 274 } 275 276 // Next implements Executor Next interface. 277 func (e *DeleteExec) Next() (*Row, error) { 278 if e.finished { 279 return nil, nil 280 } 281 defer func() { 282 e.finished = true 283 }() 284 if e.IsMultiTable && len(e.Tables) == 0 { 285 return &Row{}, nil 286 } 287 288 tblMap := make(map[int64][]string, len(e.Tables)) 289 // Get table alias map. 290 tblNames := make(map[string]string) 291 if e.IsMultiTable { 292 // Delete from multiple tables should consider table ident list. 293 fs := e.SelectExec.Fields() 294 for _, f := range fs { 295 if len(f.TableAsName.L) > 0 { 296 tblNames[f.TableAsName.L] = f.TableName.Name.L 297 } else { 298 tblNames[f.TableName.Name.L] = f.TableName.Name.L 299 } 300 } 301 for _, t := range e.Tables { 302 // Consider DBName. 303 _, ok := tblNames[t.Name.L] 304 if !ok { 305 return nil, errors.Errorf("Unknown table '%s' in MULTI DELETE", t.Name.O) 306 } 307 tblMap[t.TableInfo.ID] = append(tblMap[t.TableInfo.ID], t.Name.L) 308 } 309 } 310 311 // Map for unique (Table, handle) pair. 312 rowKeyMap := make(map[table.Table]map[int64]struct{}) 313 for { 314 row, err := e.SelectExec.Next() 315 if err != nil { 316 return nil, errors.Trace(err) 317 } 318 if row == nil { 319 break 320 } 321 322 for _, entry := range row.RowKeys { 323 if e.IsMultiTable && !isMatchTableName(entry, tblMap) { 324 continue 325 } 326 if rowKeyMap[entry.Tbl] == nil { 327 rowKeyMap[entry.Tbl] = make(map[int64]struct{}) 328 } 329 rowKeyMap[entry.Tbl][entry.Handle] = struct{}{} 330 } 331 } 332 for t, handleMap := range rowKeyMap { 333 for handle := range handleMap { 334 data, err := t.Row(e.ctx, handle) 335 if err != nil { 336 return nil, errors.Trace(err) 337 } 338 err = e.removeRow(e.ctx, t, handle, data) 339 if err != nil { 340 return nil, errors.Trace(err) 341 } 342 } 343 } 344 return nil, nil 345 } 346 347 func isMatchTableName(entry *RowKeyEntry, tblMap map[int64][]string) bool { 348 var name string 349 if entry.TableAsName != nil { 350 name = entry.TableAsName.L 351 } 352 if len(name) == 0 { 353 name = entry.Tbl.Meta().Name.L 354 } 355 356 names, ok := tblMap[entry.Tbl.Meta().ID] 357 if !ok { 358 return false 359 } 360 for _, n := range names { 361 if n == name { 362 return true 363 } 364 } 365 366 return false 367 } 368 369 func (e *DeleteExec) getTable(ctx context.Context, tableName *ast.TableName) (table.Table, error) { 370 return sessionctx.GetDomain(ctx).InfoSchema().TableByName(tableName.Schema, tableName.Name) 371 } 372 373 func (e *DeleteExec) removeRow(ctx context.Context, t table.Table, h int64, data []types.Datum) error { 374 err := t.RemoveRecord(ctx, h, data) 375 if err != nil { 376 return errors.Trace(err) 377 } 378 variable.GetSessionVars(ctx).AddAffectedRows(1) 379 return nil 380 } 381 382 // Fields implements Executor Fields interface. 383 // Returns nil to indicate there is no output. 384 func (e *DeleteExec) Fields() []*ast.ResultField { 385 return nil 386 } 387 388 // Close implements Executor Close interface. 389 func (e *DeleteExec) Close() error { 390 return e.SelectExec.Close() 391 } 392 393 // InsertValues is the data to insert. 394 type InsertValues struct { 395 currRow int 396 ctx context.Context 397 SelectExec Executor 398 399 Table table.Table 400 Columns []*ast.ColumnName 401 Lists [][]ast.ExprNode 402 Setlist []*ast.Assignment 403 IsPrepare bool 404 } 405 406 // InsertExec represents an insert executor. 407 type InsertExec struct { 408 *InsertValues 409 410 OnDuplicate []*ast.Assignment 411 fields []*ast.ResultField 412 413 Priority int 414 415 finished bool 416 } 417 418 // Next implements Executor Next interface. 419 func (e *InsertExec) Next() (*Row, error) { 420 if e.finished { 421 return nil, nil 422 } 423 cols, err := e.getColumns(e.Table.Cols()) 424 if err != nil { 425 return nil, errors.Trace(err) 426 } 427 txn, err := e.ctx.GetTxn(false) 428 if err != nil { 429 return nil, errors.Trace(err) 430 } 431 toUpdateColumns, err := getOnDuplicateUpdateColumns(e.OnDuplicate, e.Table) 432 if err != nil { 433 return nil, errors.Trace(err) 434 } 435 436 var rows [][]types.Datum 437 if e.SelectExec != nil { 438 rows, err = e.getRowsSelect(cols) 439 } else { 440 rows, err = e.getRows(cols) 441 } 442 if err != nil { 443 return nil, errors.Trace(err) 444 } 445 446 for _, row := range rows { 447 if len(e.OnDuplicate) == 0 { 448 txn.SetOption(kv.PresumeKeyNotExists, nil) 449 } 450 h, err := e.Table.AddRecord(e.ctx, row) 451 txn.DelOption(kv.PresumeKeyNotExists) 452 if err == nil { 453 continue 454 } 455 456 if len(e.OnDuplicate) == 0 || !terror.ErrorEqual(err, kv.ErrKeyExists) { 457 return nil, errors.Trace(err) 458 } 459 if err = e.onDuplicateUpdate(row, h, toUpdateColumns); err != nil { 460 return nil, errors.Trace(err) 461 } 462 } 463 e.finished = true 464 return nil, nil 465 } 466 467 // Fields implements Executor Fields interface. 468 // Returns nil to indicate there is no output. 469 func (e *InsertExec) Fields() []*ast.ResultField { 470 return nil 471 } 472 473 // Close implements Executor Close interface. 474 func (e *InsertExec) Close() error { 475 if e.SelectExec != nil { 476 return e.SelectExec.Close() 477 } 478 return nil 479 } 480 481 // There are three types of insert statements: 482 // 1 insert ... values(...) --> name type column 483 // 2 insert ... set x=y... --> set type column 484 // 3 insert ... (select ..) --> name type column 485 // See: https://dev.mysql.com/doc/refman/5.7/en/insert.html 486 func (e *InsertValues) getColumns(tableCols []*column.Col) ([]*column.Col, error) { 487 var cols []*column.Col 488 var err error 489 490 if len(e.Setlist) > 0 { 491 // Process `set` type column. 492 columns := make([]string, 0, len(e.Setlist)) 493 for _, v := range e.Setlist { 494 columns = append(columns, v.Column.Name.O) 495 } 496 497 cols, err = column.FindCols(tableCols, columns) 498 if err != nil { 499 return nil, errors.Errorf("INSERT INTO %s: %s", e.Table.Meta().Name.O, err) 500 } 501 502 if len(cols) == 0 { 503 return nil, errors.Errorf("INSERT INTO %s: empty column", e.Table.Meta().Name.O) 504 } 505 } else { 506 // Process `name` type column. 507 columns := make([]string, 0, len(e.Columns)) 508 for _, v := range e.Columns { 509 columns = append(columns, v.Name.O) 510 } 511 cols, err = column.FindCols(tableCols, columns) 512 if err != nil { 513 return nil, errors.Errorf("INSERT INTO %s: %s", e.Table.Meta().Name.O, err) 514 } 515 516 // If cols are empty, use all columns instead. 517 if len(cols) == 0 { 518 cols = tableCols 519 } 520 } 521 522 // Check column whether is specified only once. 523 err = column.CheckOnce(cols) 524 if err != nil { 525 return nil, errors.Trace(err) 526 } 527 528 return cols, nil 529 } 530 531 func (e *InsertValues) fillValueList() error { 532 if len(e.Setlist) > 0 { 533 if len(e.Lists) > 0 { 534 return errors.Errorf("INSERT INTO %s: set type should not use values", e.Table) 535 } 536 var l []ast.ExprNode 537 for _, v := range e.Setlist { 538 l = append(l, v.Expr) 539 } 540 e.Lists = append(e.Lists, l) 541 } 542 return nil 543 } 544 545 func (e *InsertValues) checkValueCount(insertValueCount, valueCount, num int, cols []*column.Col) error { 546 if insertValueCount != valueCount { 547 // "insert into t values (), ()" is valid. 548 // "insert into t values (), (1)" is not valid. 549 // "insert into t values (1), ()" is not valid. 550 // "insert into t values (1,2), (1)" is not valid. 551 // So the value count must be same for all insert list. 552 return errors.Errorf("Column count doesn't match value count at row %d", num+1) 553 } 554 if valueCount == 0 && len(e.Columns) > 0 { 555 // "insert into t (c1) values ()" is not valid. 556 return errors.Errorf("INSERT INTO %s: expected %d value(s), have %d", e.Table.Meta().Name.O, len(e.Columns), 0) 557 } else if valueCount > 0 && valueCount != len(cols) { 558 return errors.Errorf("INSERT INTO %s: expected %d value(s), have %d", e.Table.Meta().Name.O, len(cols), valueCount) 559 } 560 return nil 561 } 562 563 func (e *InsertValues) getColumnDefaultValues(cols []*column.Col) (map[string]types.Datum, error) { 564 defaultValMap := map[string]types.Datum{} 565 for _, col := range cols { 566 if value, ok, err := table.GetColDefaultValue(e.ctx, &col.ColumnInfo); ok { 567 if err != nil { 568 return nil, errors.Trace(err) 569 } 570 defaultValMap[col.Name.L] = value 571 } 572 } 573 return defaultValMap, nil 574 } 575 576 func (e *InsertValues) getRows(cols []*column.Col) (rows [][]types.Datum, err error) { 577 // process `insert|replace ... set x=y...` 578 if err = e.fillValueList(); err != nil { 579 return nil, errors.Trace(err) 580 } 581 582 defaultVals, err := e.getColumnDefaultValues(e.Table.Cols()) 583 if err != nil { 584 return nil, errors.Trace(err) 585 } 586 587 rows = make([][]types.Datum, len(e.Lists)) 588 length := len(e.Lists[0]) 589 for i, list := range e.Lists { 590 if err = e.checkValueCount(length, len(list), i, cols); err != nil { 591 return nil, errors.Trace(err) 592 } 593 e.currRow = i 594 rows[i], err = e.getRow(cols, list, defaultVals) 595 if err != nil { 596 return nil, errors.Trace(err) 597 } 598 } 599 return 600 } 601 602 func (e *InsertValues) getRow(cols []*column.Col, list []ast.ExprNode, defaultVals map[string]types.Datum) ([]types.Datum, error) { 603 vals := make([]types.Datum, len(list)) 604 var err error 605 for i, expr := range list { 606 if d, ok := expr.(*ast.DefaultExpr); ok { 607 cn := d.Name 608 if cn != nil { 609 var found bool 610 vals[i], found = defaultVals[cn.Name.L] 611 if !found { 612 return nil, errors.Errorf("default column not found - %s", cn.Name.O) 613 } 614 } else { 615 vals[i] = defaultVals[cols[i].Name.L] 616 } 617 } else { 618 var val types.Datum 619 val, err = evaluator.Eval(e.ctx, expr) 620 vals[i] = val 621 if err != nil { 622 return nil, errors.Trace(err) 623 } 624 } 625 } 626 return e.fillRowData(cols, vals) 627 } 628 629 func (e *InsertValues) getRowsSelect(cols []*column.Col) ([][]types.Datum, error) { 630 // process `insert|replace into ... select ... from ...` 631 if len(e.SelectExec.Fields()) != len(cols) { 632 return nil, errors.Errorf("Column count %d doesn't match value count %d", len(cols), len(e.SelectExec.Fields())) 633 } 634 var rows [][]types.Datum 635 for { 636 innerRow, err := e.SelectExec.Next() 637 if err != nil { 638 return nil, errors.Trace(err) 639 } 640 if innerRow == nil { 641 break 642 } 643 e.currRow = len(rows) 644 row, err := e.fillRowData(cols, innerRow.Data) 645 if err != nil { 646 return nil, errors.Trace(err) 647 } 648 rows = append(rows, row) 649 } 650 return rows, nil 651 } 652 653 func (e *InsertValues) fillRowData(cols []*column.Col, vals []types.Datum) ([]types.Datum, error) { 654 row := make([]types.Datum, len(e.Table.Cols())) 655 marked := make(map[int]struct{}, len(vals)) 656 for i, v := range vals { 657 offset := cols[i].Offset 658 row[offset] = v 659 marked[offset] = struct{}{} 660 } 661 err := e.initDefaultValues(row, marked) 662 if err != nil { 663 return nil, errors.Trace(err) 664 } 665 if err = column.CastValues(e.ctx, row, cols); err != nil { 666 return nil, errors.Trace(err) 667 } 668 if err = column.CheckNotNull(e.Table.Cols(), row); err != nil { 669 return nil, errors.Trace(err) 670 } 671 return row, nil 672 } 673 674 func (e *InsertValues) initDefaultValues(row []types.Datum, marked map[int]struct{}) error { 675 var defaultValueCols []*column.Col 676 for i, c := range e.Table.Cols() { 677 // It's used for retry. 678 if mysql.HasAutoIncrementFlag(c.Flag) && row[i].Kind() == types.KindNull && 679 variable.GetSessionVars(e.ctx).RetryInfo.Retrying { 680 id, err := variable.GetSessionVars(e.ctx).RetryInfo.GetCurrAutoIncrementID() 681 if err != nil { 682 return errors.Trace(err) 683 } 684 row[i].SetInt64(id) 685 } 686 if row[i].Kind() != types.KindNull { 687 // Column value isn't nil and column isn't auto-increment, continue. 688 if !mysql.HasAutoIncrementFlag(c.Flag) { 689 continue 690 } 691 val, err := row[i].ToInt64() 692 if err != nil { 693 return errors.Trace(err) 694 } 695 if val != 0 { 696 e.Table.RebaseAutoID(val, true) 697 continue 698 } 699 } 700 701 // If the nil value is evaluated in insert list, we will use nil except auto increment column. 702 if _, ok := marked[i]; ok && !mysql.HasAutoIncrementFlag(c.Flag) && !mysql.HasTimestampFlag(c.Flag) { 703 continue 704 } 705 706 if mysql.HasAutoIncrementFlag(c.Flag) { 707 recordID, err := e.Table.AllocAutoID() 708 if err != nil { 709 return errors.Trace(err) 710 } 711 row[i].SetInt64(recordID) 712 // Notes: incompatible with mysql 713 // MySQL will set last insert id to the first row, as follows: 714 // `t(id int AUTO_INCREMENT, c1 int, PRIMARY KEY (id))` 715 // `insert t (c1) values(1),(2),(3);` 716 // Last insert id will be 1, not 3. 717 variable.GetSessionVars(e.ctx).SetLastInsertID(uint64(recordID)) 718 // It's used for retry. 719 if !variable.GetSessionVars(e.ctx).RetryInfo.Retrying { 720 variable.GetSessionVars(e.ctx).RetryInfo.AddAutoIncrementID(recordID) 721 } 722 } else { 723 var err error 724 row[i], _, err = table.GetColDefaultValue(e.ctx, &c.ColumnInfo) 725 if err != nil { 726 return errors.Trace(err) 727 } 728 } 729 730 defaultValueCols = append(defaultValueCols, c) 731 } 732 if err := column.CastValues(e.ctx, row, defaultValueCols); err != nil { 733 return errors.Trace(err) 734 } 735 736 return nil 737 } 738 739 func (e *InsertExec) onDuplicateUpdate(row []types.Datum, h int64, cols map[int]*ast.Assignment) error { 740 // On duplicate key update the duplicate row. 741 // Evaluate the updated value. 742 // TODO: report rows affected and last insert id. 743 data, err := e.Table.Row(e.ctx, h) 744 if err != nil { 745 return errors.Trace(err) 746 } 747 // For evaluate ValuesExpr 748 // http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 749 for i, rf := range e.fields { 750 rf.Expr.SetValue(row[i].GetValue()) 751 } 752 // Evaluate assignment 753 newData := make([]types.Datum, len(data)) 754 for i, c := range row { 755 asgn, ok := cols[i] 756 if !ok { 757 newData[i] = c 758 continue 759 } 760 var val types.Datum 761 val, err = evaluator.Eval(e.ctx, asgn.Expr) 762 if err != nil { 763 return errors.Trace(err) 764 } 765 newData[i] = val 766 } 767 if err = updateRecord(e.ctx, h, data, newData, cols, e.Table, 0, true); err != nil { 768 return errors.Trace(err) 769 } 770 return nil 771 } 772 773 func findColumnByName(t table.Table, name string) (*column.Col, error) { 774 _, tableName, colName := splitQualifiedName(name) 775 if len(tableName) > 0 && tableName != t.Meta().Name.O { 776 return nil, errors.Errorf("unknown field %s.%s", tableName, colName) 777 } 778 779 c := column.FindCol(t.Cols(), colName) 780 if c == nil { 781 return nil, errors.Errorf("unknown field %s", colName) 782 } 783 return c, nil 784 } 785 786 func getOnDuplicateUpdateColumns(assignList []*ast.Assignment, t table.Table) (map[int]*ast.Assignment, error) { 787 m := make(map[int]*ast.Assignment, len(assignList)) 788 789 for _, v := range assignList { 790 col := v.Column 791 c, err := findColumnByName(t, joinQualifiedName("", col.Table.L, col.Name.L)) 792 if err != nil { 793 return nil, errors.Trace(err) 794 } 795 m[c.Offset] = v 796 } 797 return m, nil 798 } 799 800 // ReplaceExec represents a replace executor. 801 type ReplaceExec struct { 802 *InsertValues 803 Priority int 804 finished bool 805 } 806 807 // Fields implements Executor Fields interface. 808 // Returns nil to indicate there is no output. 809 func (e *ReplaceExec) Fields() []*ast.ResultField { 810 return nil 811 } 812 813 // Close implements Executor Close interface. 814 func (e *ReplaceExec) Close() error { 815 if e.SelectExec != nil { 816 return e.SelectExec.Close() 817 } 818 return nil 819 } 820 821 // Next implements Executor Next interface. 822 func (e *ReplaceExec) Next() (*Row, error) { 823 if e.finished { 824 return nil, nil 825 } 826 cols, err := e.getColumns(e.Table.Cols()) 827 if err != nil { 828 return nil, errors.Trace(err) 829 } 830 831 var rows [][]types.Datum 832 if e.SelectExec != nil { 833 rows, err = e.getRowsSelect(cols) 834 } else { 835 rows, err = e.getRows(cols) 836 } 837 if err != nil { 838 return nil, errors.Trace(err) 839 } 840 841 /* 842 * MySQL uses the following algorithm for REPLACE (and LOAD DATA ... REPLACE): 843 * 1. Try to insert the new row into the table 844 * 2. While the insertion fails because a duplicate-key error occurs for a primary key or unique index: 845 * 3. Delete from the table the conflicting row that has the duplicate key value 846 * 4. Try again to insert the new row into the table 847 * See: http://dev.mysql.com/doc/refman/5.7/en/replace.html 848 * 849 * For REPLACE statements, the affected-rows value is 2 if the new row replaced an old row, 850 * because in this case, one row was inserted after the duplicate was deleted. 851 * See: http://dev.mysql.com/doc/refman/5.7/en/mysql-affected-rows.html 852 */ 853 idx := 0 854 rowsLen := len(rows) 855 for { 856 if idx >= rowsLen { 857 break 858 } 859 row := rows[idx] 860 h, err1 := e.Table.AddRecord(e.ctx, row) 861 if err1 == nil { 862 idx++ 863 continue 864 } 865 if err1 != nil && !terror.ErrorEqual(err1, kv.ErrKeyExists) { 866 return nil, errors.Trace(err1) 867 } 868 oldRow, err1 := e.Table.Row(e.ctx, h) 869 if err1 != nil { 870 return nil, errors.Trace(err1) 871 } 872 rowUnchanged, err1 := types.EqualDatums(oldRow, row) 873 if err1 != nil { 874 return nil, errors.Trace(err1) 875 } 876 if rowUnchanged { 877 // If row unchanged, we do not need to do insert. 878 variable.GetSessionVars(e.ctx).AddAffectedRows(1) 879 idx++ 880 continue 881 } 882 // Remove current row and try replace again. 883 err1 = e.Table.RemoveRecord(e.ctx, h, oldRow) 884 if err1 != nil { 885 return nil, errors.Trace(err1) 886 } 887 variable.GetSessionVars(e.ctx).AddAffectedRows(1) 888 } 889 e.finished = true 890 return nil, nil 891 } 892 893 // SplitQualifiedName splits an identifier name to db, table and field name. 894 func splitQualifiedName(name string) (db string, table string, field string) { 895 seps := strings.Split(name, ".") 896 897 l := len(seps) 898 switch l { 899 case 1: 900 // `name` is field. 901 field = seps[0] 902 case 2: 903 // `name` is `table.field`. 904 table, field = seps[0], seps[1] 905 case 3: 906 // `name` is `db.table.field`. 907 db, table, field = seps[0], seps[1], seps[2] 908 default: 909 // `name` is `db.table.field`. 910 db, table, field = seps[l-3], seps[l-2], seps[l-1] 911 } 912 913 return 914 } 915 916 // JoinQualifiedName converts db, table, field to a qualified name. 917 func joinQualifiedName(db string, table string, field string) string { 918 if len(db) > 0 { 919 return fmt.Sprintf("%s.%s.%s", db, table, field) 920 } else if len(table) > 0 { 921 return fmt.Sprintf("%s.%s", table, field) 922 } else { 923 return field 924 } 925 }