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  }