github.com/dolthub/go-mysql-server@v0.18.0/memory/table_editor.go (about) 1 // Copyright 2020-2021 Dolthub, 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package memory 16 17 import ( 18 "fmt" 19 "reflect" 20 "strings" 21 22 "github.com/dolthub/go-mysql-server/internal/cmap" 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 // tableEditor manages the edits that a targetTable receives. 28 type tableEditor struct { 29 editedTable *Table 30 initialTable *Table 31 schema sql.Schema 32 33 discardChanges bool 34 ea tableEditAccumulator 35 36 // array of key ordinals for each unique index defined on the targetTable 37 uniqueIdxCols [][]int 38 prefixLengths [][]uint16 39 fkTable *Table 40 } 41 42 var _ sql.Table = (*tableEditor)(nil) 43 var _ sql.CommentedTable = (*tableEditor)(nil) 44 var _ sql.RowReplacer = (*tableEditor)(nil) 45 var _ sql.RowUpdater = (*tableEditor)(nil) 46 var _ sql.RowInserter = (*tableEditor)(nil) 47 var _ sql.RowDeleter = (*tableEditor)(nil) 48 var _ sql.AutoIncrementSetter = (*tableEditor)(nil) 49 var _ sql.ForeignKeyEditor = (*tableEditor)(nil) 50 51 func (t *tableEditor) Name() string { 52 return t.editedTable.name 53 } 54 55 func (t *tableEditor) String() string { 56 return t.editedTable.String() 57 } 58 59 func (t *tableEditor) Schema() sql.Schema { 60 return t.editedTable.Schema() 61 } 62 63 func (t *tableEditor) Collation() sql.CollationID { 64 return t.editedTable.Collation() 65 } 66 67 func (t *tableEditor) Comment() string { 68 return t.editedTable.Comment() 69 } 70 71 func (t *tableEditor) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 72 return t.editedTable.Partitions(ctx) 73 } 74 75 func (t *tableEditor) PartitionRows(ctx *sql.Context, part sql.Partition) (sql.RowIter, error) { 76 if t.fkTable != nil { 77 return t.fkTable.PartitionRows(ctx, part) 78 } 79 return t.editedTable.PartitionRows(ctx, part) 80 } 81 82 func (t *tableEditor) GetIndexes(ctx *sql.Context) ([]sql.Index, error) { 83 return t.editedTable.GetIndexes(ctx) 84 } 85 86 func (t *tableEditor) Close(ctx *sql.Context) error { 87 var sess *Session 88 if !t.editedTable.IgnoreSessionData() { 89 sess = SessionFromContext(ctx) 90 91 if t.discardChanges { 92 sess.putTable(t.initialTable.data) 93 return nil 94 } 95 } else { 96 if t.discardChanges { 97 t.editedTable.replaceData(t.initialTable.data) 98 return nil 99 } 100 } 101 102 // On the normal INSERT / UPDATE / DELETE path this happens at StatementComplete time, but for table rewrites it 103 // only happens at Close 104 err := t.ea.ApplyEdits(t.editedTable) 105 if err != nil { 106 return err 107 } 108 t.ea.Clear() 109 110 if !t.editedTable.IgnoreSessionData() { 111 sess.putTable(t.editedTable.data) 112 } 113 114 return nil 115 } 116 117 func (t *tableEditor) StatementBegin(ctx *sql.Context) { 118 t.initialTable = t.editedTable.copy() 119 } 120 121 func (t *tableEditor) DiscardChanges(ctx *sql.Context, errorEncountered error) error { 122 t.ea.Clear() 123 if _, ignore := errorEncountered.(sql.IgnorableError); !ignore { 124 t.editedTable.replaceData(t.initialTable.data) 125 t.discardChanges = true 126 } 127 return nil 128 } 129 130 func (t *tableEditor) StatementComplete(ctx *sql.Context) error { 131 err := t.ea.ApplyEdits(t.editedTable) 132 if err != nil { 133 return nil 134 } 135 t.ea.Clear() 136 137 if !t.editedTable.IgnoreSessionData() { 138 sess := SessionFromContext(ctx) 139 sess.putTable(t.editedTable.data) 140 } 141 142 return nil 143 } 144 145 // Insert inserts a new row into the table. 146 func (t *tableEditor) Insert(ctx *sql.Context, row sql.Row) error { 147 if err := checkRow(t.editedTable.data.schema.Schema, row); err != nil { 148 return err 149 } 150 151 partitionRow, added, err := t.ea.Get(row) 152 if err != nil { 153 return err 154 } 155 156 if added { 157 pkColIdxes := t.pkColumnIndexes() 158 return sql.NewUniqueKeyErr(formatRow(row, pkColIdxes), true, partitionRow) 159 } 160 161 for i, cols := range t.uniqueIdxCols { 162 if hasNullForAnyCols(row, cols) { 163 continue 164 } 165 prefixLengths := t.prefixLengths[i] 166 existing, found, err := t.ea.GetByCols(row, cols, prefixLengths) 167 if err != nil { 168 return err 169 } 170 171 if found { 172 return sql.NewUniqueKeyErr(formatRow(row, cols), false, existing) 173 } 174 } 175 176 err = t.ea.Insert(row) 177 if err != nil { 178 return err 179 } 180 181 idx := t.editedTable.data.autoColIdx 182 if idx >= 0 { 183 autoCol := t.editedTable.data.schema.Schema[idx] 184 cmp, err := autoCol.Type.Compare(row[idx], t.editedTable.data.autoIncVal) 185 if err != nil { 186 return err 187 } 188 if cmp > 0 { 189 // Provided value larger than autoIncVal, set autoIncVal to that value 190 v, _, err := types.Uint64.Convert(row[idx]) 191 if err != nil { 192 return err 193 } 194 t.editedTable.data.autoIncVal = v.(uint64) 195 t.editedTable.data.autoIncVal++ // Move onto next autoIncVal 196 } else if cmp == 0 { 197 // Provided value equal to autoIncVal 198 t.editedTable.data.autoIncVal++ // Move onto next autoIncVal 199 } 200 } 201 202 return nil 203 } 204 205 // Delete the given row from the table. 206 func (t *tableEditor) Delete(ctx *sql.Context, row sql.Row) error { 207 if err := checkRow(t.editedTable.Schema(), row); err != nil { 208 return err 209 } 210 211 err := t.ea.Delete(row) 212 if err != nil { 213 return err 214 } 215 216 return nil 217 } 218 219 // Update updates the given row in the table. 220 func (t *tableEditor) Update(ctx *sql.Context, oldRow sql.Row, newRow sql.Row) error { 221 if err := checkRow(t.editedTable.Schema(), oldRow); err != nil { 222 return err 223 } 224 if err := checkRow(t.editedTable.Schema(), newRow); err != nil { 225 return err 226 } 227 228 err := t.ea.Delete(oldRow) 229 if err != nil { 230 return err 231 } 232 233 if t.pkColsDiffer(oldRow, newRow) { 234 partitionRow, added, err := t.ea.Get(newRow) 235 if err != nil { 236 return err 237 } 238 239 if added { 240 pkColIdxes := t.pkColumnIndexes() 241 vals := make([]interface{}, len(pkColIdxes)) 242 for i := range pkColIdxes { 243 vals[i] = newRow[pkColIdxes[i]] 244 } 245 return sql.NewUniqueKeyErr(fmt.Sprint(vals), true, partitionRow) 246 } 247 } 248 249 // Throw a unique key error if any unique indexes are defined 250 for i, cols := range t.uniqueIdxCols { 251 if hasNullForAnyCols(newRow, cols) { 252 continue 253 } 254 prefixLengths := t.prefixLengths[i] 255 existing, found, err := t.ea.GetByCols(newRow, cols, prefixLengths) 256 if err != nil { 257 return err 258 } 259 260 if found { 261 return sql.NewUniqueKeyErr(formatRow(newRow, cols), false, existing) 262 } 263 } 264 265 err = t.ea.Insert(newRow) 266 if err != nil { 267 return err 268 } 269 270 return nil 271 } 272 273 // SetAutoIncrementValue sets a new AUTO_INCREMENT value 274 func (t *tableEditor) SetAutoIncrementValue(ctx *sql.Context, val uint64) error { 275 t.editedTable.data.autoIncVal = val 276 return nil 277 } 278 279 func (t *tableEditor) PreciseMatch() bool { 280 return true 281 } 282 283 func (t *tableEditor) IndexedAccess(lookup sql.IndexLookup) sql.IndexedTable { 284 // Before we return an indexed access for this table, we need to apply all the edits to the table 285 // TODO: optimize this, should create some struct that encloses the tableEditor and filters based on the lookup 286 err := t.ea.ApplyEdits(t.editedTable) 287 if err != nil { 288 return nil 289 } 290 t.ea.Clear() 291 292 // We mark this table as ignoring session data because the session won't have up to date data for it now 293 indexedTable := t.editedTable.copy() 294 indexedTable.ignoreSessionData = true 295 return &IndexedTable{Table: indexedTable, Lookup: lookup} 296 } 297 298 func (t *tableEditor) pkColumnIndexes() []int { 299 var pkColIdxes []int 300 for _, column := range t.editedTable.data.schema.Schema { 301 if column.PrimaryKey { 302 idx, _ := t.editedTable.data.getColumnOrdinal(column.Name) 303 pkColIdxes = append(pkColIdxes, idx) 304 } 305 } 306 return pkColIdxes 307 } 308 309 func (t *tableEditor) pkColsDiffer(row, row2 sql.Row) bool { 310 pkColIdxes := t.pkColumnIndexes() 311 return !columnsMatch(pkColIdxes, nil, row, row2) 312 } 313 314 // Returns whether the values for the columns given match in the two rows provided 315 func columnsMatch(colIndexes []int, prefixLengths []uint16, row sql.Row, row2 sql.Row) bool { 316 for i, idx := range colIndexes { 317 v1 := row[idx] 318 v2 := row2[idx] 319 if len(prefixLengths) > i && prefixLengths[i] > 0 { 320 prefixLength := prefixLengths[i] 321 switch v := v1.(type) { 322 case string: 323 if prefixLength > uint16(len(v)) { 324 prefixLength = uint16(len(v)) 325 } 326 v1 = v[:prefixLength] 327 case []byte: 328 if prefixLength > uint16(len(v)) { 329 prefixLength = uint16(len(v)) 330 } 331 v1 = v[:prefixLength] 332 } 333 prefixLength = prefixLengths[i] 334 switch v := v2.(type) { 335 case string: 336 if prefixLength > uint16(len(v)) { 337 prefixLength = uint16(len(v)) 338 } 339 v2 = v[:prefixLength] 340 case []byte: 341 if prefixLength > uint16(len(v)) { 342 prefixLength = uint16(len(v)) 343 } 344 v2 = v[:prefixLength] 345 } 346 } 347 if v, ok := v1.([]byte); ok { 348 v1 = string(v) 349 } 350 if v, ok := v2.([]byte); ok { 351 v2 = string(v) 352 } 353 if v1 != v2 { 354 return false 355 } 356 } 357 return true 358 } 359 360 // tableEditAccumulator tracks the set of inserts and deletes and applies those edits to a initialTable. 361 type tableEditAccumulator interface { 362 // Insert adds a row to the accumulator to be inserted in the future. Updates are modeled as a Delete then an insertPartIdx. 363 Insert(value sql.Row) error 364 // Delete adds a row to the accumulator to be deleted in the future. Updates are modeled as a Delete then an insertPartIdx. 365 Delete(value sql.Row) error 366 // Get returns a row if found along with a boolean added. Added is true if a row was inserted. 367 Get(value sql.Row) (sql.Row, bool, error) 368 // ApplyEdits updates the table provided with the inserts and deletes that have been added to the accumulator. 369 // Does not clear the accumulator. 370 ApplyEdits(table *Table) error 371 // GetByCols returns the row in the table, or the pending edits, matching the ones given 372 GetByCols(value sql.Row, cols []int, prefixLengths []uint16) (sql.Row, bool, error) 373 // Clear wipes all of the stored inserts and deletes that may or may not have been applied. 374 Clear() 375 } 376 377 // newTableEditAccumulator returns a tableEditAccumulator based on the schema. 378 func newTableEditAccumulator(t *TableData) tableEditAccumulator { 379 if sql.IsKeyless(t.schema.Schema) { 380 return &keylessTableEditAccumulator{ 381 tableData: t, 382 adds: make([]sql.Row, 0), 383 deletes: make([]sql.Row, 0), 384 } 385 } 386 387 return &pkTableEditAccumulator{ 388 tableData: t, 389 adds: cmap.NewMap[string, sql.Row](), 390 deletes: cmap.NewMap[string, sql.Row](), 391 } 392 } 393 394 // pkTableEditAccumulator manages the updates of keyed tables. It uses a map to efficiently toggle edits. 395 type pkTableEditAccumulator struct { 396 tableData *TableData 397 adds *cmap.Map[string, sql.Row] 398 deletes *cmap.Map[string, sql.Row] 399 } 400 401 var _ tableEditAccumulator = (*pkTableEditAccumulator)(nil) 402 403 // Insert implements the tableEditAccumulator interface. 404 func (pke *pkTableEditAccumulator) Insert(value sql.Row) error { 405 rowKey := pke.getRowKey(value) 406 pke.adds.Set(rowKey, value) 407 return nil 408 } 409 410 // Delete implements the tableEditAccumulator interface. 411 func (pke *pkTableEditAccumulator) Delete(value sql.Row) error { 412 rowKey := pke.getRowKey(value) 413 pke.adds.Del(rowKey) 414 pke.deletes.Set(rowKey, value) 415 416 return nil 417 } 418 419 // Get implements the tableEditAccumulator interface. 420 func (pke *pkTableEditAccumulator) Get(value sql.Row) (sql.Row, bool, error) { 421 rowKey := pke.getRowKey(value) 422 423 r, exists := pke.adds.Get(rowKey) 424 if exists { 425 return r, true, nil 426 } 427 428 r, exists = pke.deletes.Get(rowKey) 429 if exists { 430 return r, false, nil 431 } 432 433 pkColIdxes := pke.pkColumnIndexes() 434 for _, partition := range pke.tableData.partitions { 435 for _, partitionRow := range partition { 436 if columnsMatch(pkColIdxes, nil, partitionRow, value) { 437 return partitionRow, true, nil 438 } 439 } 440 } 441 442 return nil, false, nil 443 } 444 445 // GetByCols finds a row that has the same |cols| values as |value|. 446 func (pke *pkTableEditAccumulator) GetByCols(value sql.Row, cols []int, prefixLengths []uint16) (sql.Row, bool, error) { 447 // If we have this row in any delete, bail. 448 if _, _, exists := pke.deletes.FindForeach(func(key string, r sql.Row) bool { 449 return columnsMatch(cols, prefixLengths, r, value) 450 }); exists { 451 return nil, false, nil 452 } 453 454 if _, r, exists := pke.adds.FindForeach(func(key string, r sql.Row) bool { 455 return columnsMatch(cols, prefixLengths, r, value) 456 }); exists { 457 return r, true, nil 458 } 459 460 for _, partition := range pke.tableData.partitions { 461 for _, partitionRow := range partition { 462 if columnsMatch(cols, prefixLengths, partitionRow, value) { 463 return partitionRow, true, nil 464 } 465 } 466 } 467 468 return nil, false, nil 469 } 470 471 // ApplyEdits implements the tableEditAccumulator interface. 472 func (pke *pkTableEditAccumulator) ApplyEdits(table *Table) error { 473 474 if err := pke.deletes.Foreach(func(key string, val sql.Row) error { 475 return pke.deleteHelper(pke.tableData, val) 476 477 }); err != nil { 478 return err 479 } 480 481 if err := pke.adds.Foreach(func(key string, val sql.Row) error { 482 return pke.insertHelper(pke.tableData, val) 483 484 }); err != nil { 485 return err 486 } 487 488 pke.tableData.sortRows() 489 table.replaceData(pke.tableData) 490 491 return nil 492 } 493 494 // Clear implements the tableEditAccumulator interface. 495 func (pke *pkTableEditAccumulator) Clear() { 496 pke.adds = cmap.NewMap[string, sql.Row]() 497 pke.deletes = cmap.NewMap[string, sql.Row]() 498 } 499 500 // pkColumnIndexes returns the indexes of the primary partitionKeys in the initialized tableData. 501 func (pke *pkTableEditAccumulator) pkColumnIndexes() []int { 502 return pke.tableData.schema.PkOrdinals 503 } 504 505 // getRowKey returns a sql.Row of the primary partitionKeys a row in relation with the initialized tableData. 506 func (pke *pkTableEditAccumulator) getRowKey(r sql.Row) string { 507 var rowKey strings.Builder 508 for _, i := range pke.tableData.schema.PkOrdinals { 509 rowKey.WriteString(fmt.Sprintf("%v", r[i])) 510 } 511 return rowKey.String() 512 } 513 514 // deleteHelper deletes the given row from the tableData. 515 func (pke *pkTableEditAccumulator) deleteHelper(table *TableData, row sql.Row) error { 516 if err := checkRow(table.schema.Schema, row); err != nil { 517 return err 518 } 519 520 matches := false 521 var partKey string 522 var rowIdx int 523 for partName, partition := range table.partitions { 524 for partitionRowIndex, partitionRow := range partition { 525 matches = true 526 527 // For DELETE queries, we will have previously selected the row in order to delete it. For REPLACE, we will just 528 // have the row to be replaced, so we need to consider primary key information. 529 pkColIdxes := pke.pkColumnIndexes() 530 if len(pkColIdxes) > 0 { 531 if columnsMatch(pkColIdxes, nil, partitionRow, row) { 532 table.partitions[partName] = append(partition[:partitionRowIndex], partition[partitionRowIndex+1:]...) 533 partKey = partName 534 rowIdx = partitionRowIndex 535 break 536 } 537 } 538 539 var err error 540 matches, err = partitionRow.Equals(row, table.schema.PhysicalSchema()) 541 if err != nil { 542 return err 543 } 544 545 if matches { 546 table.partitions[partName] = append(partition[:partitionRowIndex], partition[partitionRowIndex+1:]...) 547 partKey = partName 548 rowIdx = partitionRowIndex 549 break 550 } 551 } 552 553 if matches { 554 break 555 } 556 } 557 558 deleteRowFromIndexes(table, partKey, rowIdx) 559 560 return nil 561 } 562 563 // deleteRowFromIndexes removes the row at the given partition and index from all indexes 564 func deleteRowFromIndexes(table *TableData, partKey string, rowIdx int) { 565 for _, idx := range table.indexes { 566 memIdx := idx.(*Index) 567 idxStorage := table.secondaryIndexStorage[indexName(memIdx.ID())] 568 // Iterate backwards so we can remove the trailing N elements without triggering range errors on multiple passes 569 // through the loop 570 for i := len(idxStorage) - 1; i >= 0; i-- { 571 idxRow := idxStorage[i] 572 rowLoc := idxRow[len(idxRow)-1].(primaryRowLocation) 573 if rowLoc.partition == partKey && rowLoc.idx == rowIdx { 574 idxStorage = append(idxStorage[:i], idxStorage[i+1:]...) 575 } else if rowLoc.partition == partKey && rowLoc.idx > rowIdx { 576 // For rows after the one we deleted, offset the row index by -1 577 idxRow[len(idxRow)-1] = primaryRowLocation{rowLoc.partition, rowLoc.idx - 1} 578 } 579 } 580 table.secondaryIndexStorage[indexName(memIdx.ID())] = idxStorage 581 } 582 } 583 584 // insertHelper inserts the given row into the given tableData. 585 func (pke *pkTableEditAccumulator) insertHelper(table *TableData, row sql.Row) error { 586 partIdx, err := table.partition(row) 587 if err != nil { 588 return err 589 } 590 key := string(table.partitionKeys[partIdx]) 591 592 pkColIdxes := pke.pkColumnIndexes() 593 savedPartitionIndex := "" 594 savedPartitionRowIndex := -1 595 if len(pkColIdxes) > 0 { 596 for partitionIndex, partition := range table.partitions { 597 for partitionRowIndex, partitionRow := range partition { 598 if columnsMatch(pkColIdxes, nil, partitionRow, row) { 599 // Instead of throwing a unique key error, we perform an update operation to essentially represent 600 // map semantics for the keyed table. 601 savedPartitionIndex = partitionIndex 602 savedPartitionRowIndex = partitionRowIndex 603 break 604 } 605 } 606 } 607 } 608 609 storageRow := pke.tableData.toStorageRow(row) 610 611 var partKey string 612 var rowIdx int 613 if savedPartitionRowIndex > -1 { 614 table.partitions[savedPartitionIndex][savedPartitionRowIndex] = storageRow 615 partKey = savedPartitionIndex 616 rowIdx = savedPartitionRowIndex 617 } else { 618 table.partitions[key] = append(table.partitions[key], storageRow) 619 partKey = key 620 rowIdx = len(table.partitions[key]) - 1 621 } 622 623 err = addRowToIndexes(table, row, partKey, rowIdx) 624 if err != nil { 625 return err 626 } 627 628 return nil 629 } 630 631 // addRowToIndexes adds the given row to all indexes 632 func addRowToIndexes(table *TableData, row sql.Row, partKey string, rowIdx int) error { 633 for _, idx := range table.indexes { 634 memIdx := idx.(*Index) 635 idxRow, err := memIdx.rowToIndexStorage(row, partKey, rowIdx) 636 if err != nil { 637 return err 638 } 639 table.secondaryIndexStorage[indexName(memIdx.ID())] = append(table.secondaryIndexStorage[indexName(memIdx.ID())], idxRow) 640 } 641 return nil 642 } 643 644 // keylessTableEditAccumulator manages updates for a keyless tableData. 645 type keylessTableEditAccumulator struct { 646 tableData *TableData 647 adds []sql.Row 648 deletes []sql.Row 649 } 650 651 var _ tableEditAccumulator = (*keylessTableEditAccumulator)(nil) 652 653 // Insert implements the tableEditAccumulator interface. 654 func (k *keylessTableEditAccumulator) Insert(value sql.Row) error { 655 for i, row := range k.deletes { 656 eq, err := value.Equals(row, k.tableData.schema.Schema.PhysicalSchema()) 657 if err != nil { 658 return err 659 } 660 661 if eq { 662 k.deletes = append(k.deletes[:i], k.deletes[i+1:]...) 663 return nil 664 } 665 } 666 667 k.adds = append(k.adds, value) 668 return nil 669 } 670 671 // Delete implements the tableEditAccumulator interface. 672 func (k *keylessTableEditAccumulator) Delete(value sql.Row) error { 673 for i, row := range k.adds { 674 eq, err := value.Equals(row, k.tableData.schema.Schema.PhysicalSchema()) 675 if err != nil { 676 return err 677 } 678 679 if eq { 680 k.adds = append(k.adds[:i], k.adds[i+1:]...) 681 return nil 682 } 683 684 } 685 686 k.deletes = append(k.deletes, value) 687 return nil 688 } 689 690 // Get implements the tableEditAccumulator interface. 691 func (k *keylessTableEditAccumulator) Get(value sql.Row) (sql.Row, bool, error) { 692 // Note: Keyless tables do not have to return an accurate answer here as any given row can be inserted or deleted 693 // multiple times. 694 return nil, false, nil 695 } 696 697 func (k *keylessTableEditAccumulator) GetByCols(value sql.Row, cols []int, prefixLengths []uint16) (sql.Row, bool, error) { 698 deleteCount := 0 699 for _, r := range k.deletes { 700 if columnsMatch(cols, prefixLengths, r, value) { 701 deleteCount++ 702 } 703 } 704 705 for _, partition := range k.tableData.partitions { 706 for _, partitionRow := range partition { 707 if columnsMatch(cols, prefixLengths, partitionRow, value) { 708 if deleteCount == 0 { 709 return partitionRow, true, nil 710 } 711 deleteCount-- 712 } 713 } 714 } 715 716 for _, r := range k.adds { 717 if columnsMatch(cols, prefixLengths, r, value) { 718 if deleteCount == 0 { 719 return r, true, nil 720 } 721 deleteCount-- 722 } 723 } 724 725 return nil, false, nil 726 } 727 728 // ApplyEdits implements the tableEditAccumulator interface. 729 func (k *keylessTableEditAccumulator) ApplyEdits(table *Table) error { 730 for _, val := range k.deletes { 731 err := k.deleteHelper(k.tableData, val) 732 if err != nil { 733 return err 734 } 735 } 736 737 for _, val := range k.adds { 738 err := k.insertHelper(k.tableData, val) 739 if err != nil { 740 return err 741 } 742 } 743 744 // The primary index is unsorted, but we still need to sort the secondary indexes 745 k.tableData.sortSecondaryIndexes() 746 747 table.replaceData(k.tableData) 748 return nil 749 } 750 751 // Clear implements the tableEditAccumulator interface. 752 func (k *keylessTableEditAccumulator) Clear() { 753 k.adds = make([]sql.Row, 0) 754 k.deletes = make([]sql.Row, 0) 755 } 756 757 // deleteHelper deletes a row from a keyless tableData, if it exists. 758 func (k *keylessTableEditAccumulator) deleteHelper(table *TableData, row sql.Row) error { 759 if err := checkRow(table.schema.Schema, row); err != nil { 760 return err 761 } 762 763 storageRow := k.tableData.toStorageRow(row) 764 765 matches := false 766 var partKey string 767 var rowIdx int 768 for partitionIndex, partition := range table.partitions { 769 for partitionRowIndex, partitionRow := range partition { 770 matches = true 771 var err error 772 matches, err = partitionRow.Equals(storageRow, table.schema.Schema.PhysicalSchema()) 773 if err != nil { 774 return err 775 } 776 777 if matches { 778 table.partitions[partitionIndex] = append(partition[:partitionRowIndex], partition[partitionRowIndex+1:]...) 779 partKey = partitionIndex 780 rowIdx = partitionRowIndex 781 break 782 } 783 } 784 if matches { 785 break 786 } 787 } 788 789 deleteRowFromIndexes(table, partKey, rowIdx) 790 791 return nil 792 } 793 794 // insertHelper inserts into a keyless tableData. 795 func (k *keylessTableEditAccumulator) insertHelper(table *TableData, row sql.Row) error { 796 partIdx, err := table.partition(row) 797 if err != nil { 798 return err 799 } 800 key := string(table.partitionKeys[partIdx]) 801 802 storageRow := k.tableData.toStorageRow(row) 803 table.partitions[key] = append(table.partitions[key], storageRow) 804 805 err = addRowToIndexes(table, row, key, len(table.partitions[key])-1) 806 if err != nil { 807 return err 808 } 809 810 return nil 811 } 812 813 func formatRow(r sql.Row, idxs []int) string { 814 b := &strings.Builder{} 815 b.WriteString("[") 816 var seenOne bool 817 for _, idx := range idxs { 818 if seenOne { 819 _, _ = fmt.Fprintf(b, ",") 820 } 821 _, _ = fmt.Fprintf(b, "%v", r[idx]) 822 } 823 b.WriteString("]") 824 return b.String() 825 } 826 827 func checkRow(schema sql.Schema, row sql.Row) error { 828 for i, value := range row { 829 c := schema[i] 830 if !c.Check(value) { 831 return sql.ErrInvalidType.New(value) 832 } 833 } 834 835 return verifyRowTypes(row, schema) 836 } 837 838 func verifyRowTypes(row sql.Row, schema sql.Schema) error { 839 if len(row) == len(schema) { 840 for i := range schema { 841 col := schema[i] 842 rowVal := row[i] 843 valType := reflect.TypeOf(rowVal) 844 expectedType := col.Type.ValueType() 845 if valType != expectedType && rowVal != nil && !valType.AssignableTo(expectedType) { 846 return fmt.Errorf("Actual Value Type: %s, Expected Value Type: %s", valType.String(), expectedType.String()) 847 } 848 } 849 } 850 return nil 851 }