github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/doltdb/table.go (about)

     1  // Copyright 2019 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 doltdb
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"fmt"
    21  	"unicode"
    22  
    23  	"github.com/dolthub/go-mysql-server/sql"
    24  	gmstypes "github.com/dolthub/go-mysql-server/sql/types"
    25  
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/conflict"
    27  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb/durable"
    28  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    29  	"github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo"
    30  	"github.com/dolthub/dolt/go/store/hash"
    31  	"github.com/dolthub/dolt/go/store/prolly/tree"
    32  	"github.com/dolthub/dolt/go/store/types"
    33  )
    34  
    35  var ErrNoConflictsResolved = errors.New("no conflicts resolved")
    36  
    37  const dolt_row_hash_tag = 0
    38  
    39  // IsValidTableName checks if name is a valid identifer, and doesn't end with space characters
    40  func IsValidTableName(name string) bool {
    41  	if len(name) == 0 || unicode.IsSpace(rune(name[len(name)-1])) {
    42  		return false
    43  	}
    44  	return IsValidIdentifier(name)
    45  }
    46  
    47  // IsValidIdentifier returns true according to MySQL's quoted identifier rules.
    48  // Docs here: https://dev.mysql.com/doc/refman/8.0/en/identifiers.html
    49  func IsValidIdentifier(name string) bool {
    50  	// Ignore all leading digits
    51  	if len(name) == 0 {
    52  		return false
    53  	}
    54  	for _, c := range name {
    55  		if c == 0x0000 || c > 0xFFFF {
    56  			return false
    57  		}
    58  	}
    59  	return true
    60  }
    61  
    62  // Table is a struct which holds row data, as well as a reference to its schema.
    63  type Table struct {
    64  	table            durable.Table
    65  	overriddenSchema schema.Schema
    66  }
    67  
    68  // NewNomsTable creates a noms Struct which stores row data, index data, and schema.
    69  // Deprecated: use NewTable instead.
    70  func NewNomsTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema, rows types.Map, indexes durable.IndexSet, autoIncVal types.Value) (*Table, error) {
    71  	dt, err := durable.NewNomsTable(ctx, vrw, ns, sch, rows, indexes, autoIncVal)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	return &Table{table: dt}, nil
    77  }
    78  
    79  // NewTable creates a durable object which stores row data, index data, and schema.
    80  func NewTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema, rows durable.Index, indexes durable.IndexSet, autoIncVal types.Value) (*Table, error) {
    81  	dt, err := durable.NewTable(ctx, vrw, ns, sch, rows, indexes, autoIncVal)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return &Table{table: dt}, nil
    86  }
    87  
    88  // NewTableFromDurable creates a table from the given durable object.
    89  func NewTableFromDurable(table durable.Table) *Table {
    90  	return &Table{table: table}
    91  }
    92  
    93  func NewEmptyTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema) (*Table, error) {
    94  	rows, err := durable.NewEmptyIndex(ctx, vrw, ns, sch)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	indexes, err := durable.NewIndexSetWithEmptyIndexes(ctx, vrw, ns, sch)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	dt, err := durable.NewTable(ctx, vrw, ns, sch, rows, indexes, nil)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	return &Table{table: dt}, nil
   108  }
   109  
   110  // Format returns the NomsBinFormat for this table.
   111  func (t *Table) Format() *types.NomsBinFormat {
   112  	return t.ValueReadWriter().Format()
   113  }
   114  
   115  // ValueReadWriter returns the ValueReadWriter for this table.
   116  func (t *Table) ValueReadWriter() types.ValueReadWriter {
   117  	return durable.VrwFromTable(t.table)
   118  }
   119  
   120  func (t *Table) NodeStore() tree.NodeStore {
   121  	return durable.NodeStoreFromTable(t.table)
   122  }
   123  
   124  // OverrideSchema sets |sch| as the schema for this table, causing rows from this table to be transformed
   125  // into that schema when they are read from this table.
   126  func (t *Table) OverrideSchema(sch schema.Schema) {
   127  	t.overriddenSchema = sch
   128  }
   129  
   130  // GetOverriddenSchema returns the overridden schema if one has been set, otherwise it returns nil.
   131  func (t *Table) GetOverriddenSchema() schema.Schema {
   132  	return t.overriddenSchema
   133  }
   134  
   135  // SetConflicts sets the merge conflicts for this table.
   136  func (t *Table) SetConflicts(ctx context.Context, schemas conflict.ConflictSchema, conflictData durable.ConflictIndex) (*Table, error) {
   137  	table, err := t.table.SetConflicts(ctx, schemas, conflictData)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	return &Table{table: table}, nil
   142  }
   143  
   144  // GetConflicts returns a map built from ValueReadWriter when there are no conflicts in table.
   145  func (t *Table) GetConflicts(ctx context.Context) (conflict.ConflictSchema, durable.ConflictIndex, error) {
   146  	if t.Format() == types.Format_DOLT {
   147  		panic("should use artifacts")
   148  	}
   149  
   150  	return t.table.GetConflicts(ctx)
   151  }
   152  
   153  // HasConflicts returns true if this table contains merge conflicts.
   154  func (t *Table) HasConflicts(ctx context.Context) (bool, error) {
   155  	if t.Format() == types.Format_DOLT {
   156  		art, err := t.GetArtifacts(ctx)
   157  		if err != nil {
   158  			return false, err
   159  		}
   160  
   161  		return art.HasConflicts(ctx)
   162  	}
   163  	return t.table.HasConflicts(ctx)
   164  }
   165  
   166  // GetArtifacts returns the merge artifacts for this table.
   167  func (t *Table) GetArtifacts(ctx context.Context) (durable.ArtifactIndex, error) {
   168  	return t.table.GetArtifacts(ctx)
   169  }
   170  
   171  // SetArtifacts sets the merge artifacts for this table.
   172  func (t *Table) SetArtifacts(ctx context.Context, artifacts durable.ArtifactIndex) (*Table, error) {
   173  	table, err := t.table.SetArtifacts(ctx, artifacts)
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	return &Table{table: table}, nil
   178  }
   179  
   180  // NumRowsInConflict returns the number of rows with merge conflicts for this table.
   181  func (t *Table) NumRowsInConflict(ctx context.Context) (uint64, error) {
   182  	if t.Format() == types.Format_DOLT {
   183  		artIdx, err := t.table.GetArtifacts(ctx)
   184  		if err != nil {
   185  			return 0, err
   186  		}
   187  		return artIdx.ConflictCount(ctx)
   188  	}
   189  
   190  	ok, err := t.table.HasConflicts(ctx)
   191  	if err != nil {
   192  		return 0, err
   193  	}
   194  	if !ok {
   195  		return 0, nil
   196  	}
   197  
   198  	_, cons, err := t.table.GetConflicts(ctx)
   199  	if err != nil {
   200  		return 0, err
   201  	}
   202  
   203  	return cons.Count(), nil
   204  }
   205  
   206  // NumConstraintViolations returns the number of constraint violations for this table.
   207  func (t *Table) NumConstraintViolations(ctx context.Context) (uint64, error) {
   208  	if t.Format() == types.Format_DOLT {
   209  		artIdx, err := t.table.GetArtifacts(ctx)
   210  		if err != nil {
   211  			return 0, err
   212  		}
   213  		return artIdx.ConstraintViolationCount(ctx)
   214  	}
   215  
   216  	cvs, err := t.table.GetConstraintViolations(ctx)
   217  	if err != nil {
   218  		return 0, err
   219  	}
   220  
   221  	return cvs.Len(), nil
   222  }
   223  
   224  // ClearConflicts deletes all merge conflicts for this table.
   225  func (t *Table) ClearConflicts(ctx context.Context) (*Table, error) {
   226  	if t.Format() == types.Format_DOLT {
   227  		return t.clearArtifactConflicts(ctx)
   228  	}
   229  
   230  	return t.clearConflicts(ctx)
   231  }
   232  
   233  func (t *Table) clearArtifactConflicts(ctx context.Context) (*Table, error) {
   234  	artIdx, err := t.table.GetArtifacts(ctx)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	artIdx, err = artIdx.ClearConflicts(ctx)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	table, err := t.table.SetArtifacts(ctx, artIdx)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  	return &Table{table: table}, nil
   247  }
   248  
   249  func (t *Table) clearConflicts(ctx context.Context) (*Table, error) {
   250  	table, err := t.table.ClearConflicts(ctx)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	return &Table{table: table}, nil
   255  }
   256  
   257  // GetConflictSchemas returns the merge conflict schemas for this table.
   258  func (t *Table) GetConflictSchemas(ctx context.Context, tblName string) (base, sch, mergeSch schema.Schema, err error) {
   259  	if t.Format() == types.Format_DOLT {
   260  		return t.getProllyConflictSchemas(ctx, tblName)
   261  	}
   262  
   263  	return t.getNomsConflictSchemas(ctx)
   264  }
   265  
   266  // The conflict schema is implicitly determined based on the first conflict in the artifacts table.
   267  // For now, we will enforce that all conflicts in the artifacts table must have the same schema set (base, ours, theirs).
   268  // In the future, we may be able to display conflicts in a way that allows different conflict schemas to coexist.
   269  func (t *Table) getProllyConflictSchemas(ctx context.Context, tblName string) (base, sch, mergeSch schema.Schema, err error) {
   270  	arts, err := t.GetArtifacts(ctx)
   271  	if err != nil {
   272  		return nil, nil, nil, err
   273  	}
   274  
   275  	ourSch, err := t.GetSchema(ctx)
   276  	if err != nil {
   277  		return nil, nil, nil, err
   278  	}
   279  
   280  	if has, err := arts.HasConflicts(ctx); err != nil {
   281  		return nil, nil, nil, err
   282  	} else if !has {
   283  		return ourSch, ourSch, ourSch, nil
   284  	}
   285  
   286  	m := durable.ProllyMapFromArtifactIndex(arts)
   287  
   288  	itr, err := m.IterAllConflicts(ctx)
   289  	if err != nil {
   290  		return nil, nil, nil, err
   291  	}
   292  
   293  	art, err := itr.Next(ctx)
   294  	if err != nil {
   295  		return nil, nil, nil, err
   296  	}
   297  
   298  	baseTbl, baseOk, err := tableFromRootIsh(ctx, t.ValueReadWriter(), t.NodeStore(), art.Metadata.BaseRootIsh, tblName)
   299  	if err != nil {
   300  		return nil, nil, nil, err
   301  	}
   302  	theirTbl, theirOK, err := tableFromRootIsh(ctx, t.ValueReadWriter(), t.NodeStore(), art.TheirRootIsh, tblName)
   303  	if err != nil {
   304  		return nil, nil, nil, err
   305  	}
   306  	if !theirOK {
   307  		return nil, nil, nil, fmt.Errorf("could not find tbl %s in right root value", tblName)
   308  	}
   309  
   310  	theirSch, err := theirTbl.GetSchema(ctx)
   311  	if err != nil {
   312  		return nil, nil, nil, err
   313  	}
   314  
   315  	// If the table does not exist in the ancestor, pretend it existed and that
   316  	// it was completely empty.
   317  	if !baseOk {
   318  		if schema.SchemasAreEqual(ourSch, theirSch) {
   319  			return ourSch, ourSch, theirSch, nil
   320  		} else {
   321  			return nil, nil, nil, fmt.Errorf("expected our schema to equal their schema since the table did not exist in the ancestor")
   322  		}
   323  	}
   324  
   325  	baseSch, err := baseTbl.GetSchema(ctx)
   326  	if err != nil {
   327  		return nil, nil, nil, err
   328  	}
   329  
   330  	return baseSch, ourSch, theirSch, nil
   331  }
   332  
   333  func tableFromRootIsh(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, h hash.Hash, tblName string) (*Table, bool, error) {
   334  	rv, err := LoadRootValueFromRootIshAddr(ctx, vrw, ns, h)
   335  	if err != nil {
   336  		return nil, false, err
   337  	}
   338  	tbl, ok, err := rv.GetTable(ctx, TableName{Name: tblName})
   339  	if err != nil {
   340  		return nil, false, err
   341  	}
   342  	return tbl, ok, nil
   343  }
   344  
   345  func (t *Table) getNomsConflictSchemas(ctx context.Context) (base, sch, mergeSch schema.Schema, err error) {
   346  	cs, _, err := t.table.GetConflicts(ctx)
   347  	if err != nil {
   348  		return nil, nil, nil, err
   349  	}
   350  	return cs.Base, cs.Schema, cs.MergeSchema, nil
   351  }
   352  
   353  // GetConstraintViolationsSchema returns this table's dolt_constraint_violations system table schema.
   354  func (t *Table) GetConstraintViolationsSchema(ctx context.Context) (schema.Schema, error) {
   355  	sch, err := t.GetSchema(ctx)
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  
   360  	typeType, err := typeinfo.FromSqlType(
   361  		gmstypes.MustCreateEnumType([]string{"foreign key", "unique index", "check constraint", "not null"}, sql.Collation_Default))
   362  	if err != nil {
   363  		return nil, err
   364  	}
   365  	typeCol, err := schema.NewColumnWithTypeInfo("violation_type", schema.DoltConstraintViolationsTypeTag, typeType, true, "", false, "")
   366  	if err != nil {
   367  		return nil, err
   368  	}
   369  	infoCol, err := schema.NewColumnWithTypeInfo("violation_info", schema.DoltConstraintViolationsInfoTag, typeinfo.JSONType, false, "", false, "")
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  
   374  	colColl := schema.NewColCollection()
   375  
   376  	// the commit hash or working set hash of the right side during merge
   377  	colColl = colColl.Append(schema.NewColumn("from_root_ish", 0, types.StringKind, false))
   378  	colColl = colColl.Append(typeCol)
   379  	if schema.IsKeyless(sch) {
   380  		// If this is a keyless table, we need to add a new column for the keyless table's generated row hash.
   381  		// We need to add this internal row hash value, in order to guarantee a unique primary key in the
   382  		// constraint violations table.
   383  		colColl = colColl.Append(schema.NewColumn("dolt_row_hash", dolt_row_hash_tag, types.BlobKind, true))
   384  	} else {
   385  		colColl = colColl.Append(sch.GetPKCols().GetColumns()...)
   386  	}
   387  	colColl = colColl.Append(sch.GetNonPKCols().GetColumns()...)
   388  	colColl = colColl.Append(infoCol)
   389  
   390  	return schema.SchemaFromCols(colColl)
   391  }
   392  
   393  // GetConstraintViolations returns a map of all constraint violations for this table, along with a bool indicating
   394  // whether the table has any violations.
   395  func (t *Table) GetConstraintViolations(ctx context.Context) (types.Map, error) {
   396  	if t.Format() == types.Format_DOLT {
   397  		panic("should use artifacts")
   398  	}
   399  	return t.table.GetConstraintViolations(ctx)
   400  }
   401  
   402  // SetConstraintViolations sets this table's violations to the given map. If the map is empty, then the constraint
   403  // violations entry on the embedded struct is removed.
   404  func (t *Table) SetConstraintViolations(ctx context.Context, violationsMap types.Map) (*Table, error) {
   405  	if t.Format() == types.Format_DOLT {
   406  		panic("should use artifacts")
   407  	}
   408  	table, err := t.table.SetConstraintViolations(ctx, violationsMap)
   409  	if err != nil {
   410  		return nil, err
   411  	}
   412  	return &Table{table: table}, nil
   413  }
   414  
   415  // GetSchema returns the schema.Schema for this Table.
   416  func (t *Table) GetSchema(ctx context.Context) (schema.Schema, error) {
   417  	return t.table.GetSchema(ctx)
   418  }
   419  
   420  // GetSchemaHash returns the hash of this table's schema.
   421  func (t *Table) GetSchemaHash(ctx context.Context) (hash.Hash, error) {
   422  	return t.table.GetSchemaHash(ctx)
   423  }
   424  
   425  func SchemaHashesEqual(ctx context.Context, t1, t2 *Table) (bool, error) {
   426  	t1Hash, err := t1.GetSchemaHash(ctx)
   427  	if err != nil {
   428  		return false, err
   429  	}
   430  	t2Hash, err := t2.GetSchemaHash(ctx)
   431  	if err != nil {
   432  		return false, err
   433  	}
   434  	return t1Hash == t2Hash, nil
   435  }
   436  
   437  // UpdateSchema updates the table with the schema given and returns the updated table. The original table is unchanged.
   438  // This method only updates the schema of a table; the row data is unchanged. Schema alterations that require rebuilding
   439  // the table (e.g. adding a column in the middle, adding a new non-null column, adding a column in the middle of a
   440  // schema) must account for these changes separately.
   441  func (t *Table) UpdateSchema(ctx context.Context, sch schema.Schema) (*Table, error) {
   442  	table, err := t.table.SetSchema(ctx, sch)
   443  	if err != nil {
   444  		return nil, err
   445  	}
   446  	return &Table{table: table}, nil
   447  }
   448  
   449  // HashOf returns the hash of the underlying table struct.
   450  func (t *Table) HashOf() (hash.Hash, error) {
   451  	return t.table.HashOf()
   452  }
   453  
   454  // UpdateNomsRows replaces the current row data and returns and updated Table.
   455  // Calls to UpdateNomsRows will not be written to the database.  The root must
   456  // be updated with the updated table, and the root must be committed or written.
   457  // Deprecated: use Table.UpdateRows() instead.
   458  func (t *Table) UpdateNomsRows(ctx context.Context, updatedRows types.Map) (*Table, error) {
   459  	table, err := t.table.SetTableRows(ctx, durable.IndexFromNomsMap(updatedRows, t.ValueReadWriter(), t.NodeStore()))
   460  	if err != nil {
   461  		return nil, err
   462  	}
   463  	return &Table{table: table}, nil
   464  }
   465  
   466  // UpdateRows replaces the current row data and returns and updated Table.
   467  // Calls to UpdateRows will not be written to the database. The root must
   468  // be updated with the updated table, and the root must be committed or written.
   469  func (t *Table) UpdateRows(ctx context.Context, updatedRows durable.Index) (*Table, error) {
   470  	table, err := t.table.SetTableRows(ctx, updatedRows)
   471  	if err != nil {
   472  		return nil, err
   473  	}
   474  	return &Table{table: table}, nil
   475  }
   476  
   477  // GetNomsRowData retrieves the underlying map which is a map from a primary key to a list of field values.
   478  // Deprecated: use Table.GetRowData() instead.
   479  func (t *Table) GetNomsRowData(ctx context.Context) (types.Map, error) {
   480  	idx, err := t.table.GetTableRows(ctx)
   481  	if err != nil {
   482  		return types.Map{}, err
   483  	}
   484  
   485  	return durable.NomsMapFromIndex(idx), nil
   486  }
   487  
   488  // GetRowData retrieves the underlying map which is a map from a primary key to a list of field values.
   489  func (t *Table) GetRowData(ctx context.Context) (durable.Index, error) {
   490  	return t.table.GetTableRows(ctx)
   491  }
   492  
   493  // GetRowDataHash returns the hash.Hash of the row data index.
   494  func (t *Table) GetRowDataHash(ctx context.Context) (hash.Hash, error) {
   495  	idx, err := t.table.GetTableRows(ctx)
   496  	if err != nil {
   497  		return hash.Hash{}, err
   498  	}
   499  	return idx.HashOf()
   500  }
   501  
   502  // ResolveConflicts resolves conflicts for this table.
   503  func (t *Table) ResolveConflicts(ctx context.Context, pkTuples []types.Value) (invalid, notFound []types.Value, tbl *Table, err error) {
   504  	removed := 0
   505  	conflictSchema, confIdx, err := t.GetConflicts(ctx)
   506  	if err != nil {
   507  		return nil, nil, nil, err
   508  	}
   509  
   510  	if confIdx.Format() == types.Format_DOLT {
   511  		panic("resolve conflicts not implemented for new storage format")
   512  	}
   513  
   514  	confData := durable.NomsMapFromConflictIndex(confIdx)
   515  
   516  	confEdit := confData.Edit()
   517  	for _, pkTupleVal := range pkTuples {
   518  		if has, err := confData.Has(ctx, pkTupleVal); err != nil {
   519  			return nil, nil, nil, err
   520  		} else if has {
   521  			removed++
   522  			confEdit.Remove(pkTupleVal)
   523  		} else {
   524  			notFound = append(notFound, pkTupleVal)
   525  		}
   526  	}
   527  
   528  	if removed == 0 {
   529  		return invalid, notFound, tbl, ErrNoConflictsResolved
   530  	}
   531  
   532  	conflicts, err := confEdit.Map(ctx)
   533  	if err != nil {
   534  		return nil, nil, nil, err
   535  	}
   536  
   537  	if conflicts.Len() == 0 {
   538  		table, err := t.table.ClearConflicts(ctx)
   539  		if err != nil {
   540  			return nil, nil, nil, err
   541  		}
   542  		return invalid, notFound, &Table{table: table}, nil
   543  	}
   544  
   545  	table, err := t.table.SetConflicts(ctx, conflictSchema, durable.ConflictIndexFromNomsMap(conflicts, t.ValueReadWriter()))
   546  	if err != nil {
   547  		return nil, nil, nil, err
   548  	}
   549  
   550  	return invalid, notFound, &Table{table: table}, nil
   551  }
   552  
   553  // GetIndexSet returns the internal index map which goes from index name to a ref of the row data map.
   554  func (t *Table) GetIndexSet(ctx context.Context) (durable.IndexSet, error) {
   555  	return t.table.GetIndexes(ctx)
   556  }
   557  
   558  // SetIndexSet replaces the current internal index map, and returns an updated Table.
   559  func (t *Table) SetIndexSet(ctx context.Context, indexes durable.IndexSet) (*Table, error) {
   560  	table, err := t.table.SetIndexes(ctx, indexes)
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  	return &Table{table: table}, nil
   565  }
   566  
   567  // GetNomsIndexRowData retrieves the underlying map of an index, in which the primary key consists of all indexed columns.
   568  // Deprecated: use Table.GetIndexRowData() instead.
   569  func (t *Table) GetNomsIndexRowData(ctx context.Context, indexName string) (types.Map, error) {
   570  	sch, err := t.GetSchema(ctx)
   571  	if err != nil {
   572  		return types.EmptyMap, err
   573  	}
   574  
   575  	indexes, err := t.GetIndexSet(ctx)
   576  	if err != nil {
   577  		return types.EmptyMap, err
   578  	}
   579  
   580  	idx, err := indexes.GetIndex(ctx, sch, indexName)
   581  	if err != nil {
   582  		return types.EmptyMap, err
   583  	}
   584  
   585  	return durable.NomsMapFromIndex(idx), nil
   586  }
   587  
   588  // GetIndexRowData retrieves the underlying map of an index, in which the primary key consists of all indexed columns.
   589  func (t *Table) GetIndexRowData(ctx context.Context, indexName string) (durable.Index, error) {
   590  	sch, err := t.GetSchema(ctx)
   591  	if err != nil {
   592  		return nil, err
   593  	}
   594  
   595  	indexes, err := t.GetIndexSet(ctx)
   596  	if err != nil {
   597  		return nil, err
   598  	}
   599  
   600  	return indexes.GetIndex(ctx, sch, indexName)
   601  }
   602  
   603  // SetIndexRows replaces the current row data for the given index and returns an updated Table.
   604  func (t *Table) SetIndexRows(ctx context.Context, indexName string, idx durable.Index) (*Table, error) {
   605  	indexes, err := t.GetIndexSet(ctx)
   606  	if err != nil {
   607  		return nil, err
   608  	}
   609  
   610  	indexes, err = indexes.PutIndex(ctx, indexName, idx)
   611  	if err != nil {
   612  		return nil, err
   613  	}
   614  
   615  	return t.SetIndexSet(ctx, indexes)
   616  }
   617  
   618  // SetNomsIndexRows replaces the current row data for the given index and returns an updated Table.
   619  // Deprecated: use Table.SetIndexRows() instead.
   620  func (t *Table) SetNomsIndexRows(ctx context.Context, indexName string, idx types.Map) (*Table, error) {
   621  	indexes, err := t.GetIndexSet(ctx)
   622  	if err != nil {
   623  		return nil, err
   624  	}
   625  
   626  	indexes, err = indexes.PutNomsIndex(ctx, indexName, idx)
   627  	if err != nil {
   628  		return nil, err
   629  	}
   630  
   631  	return t.SetIndexSet(ctx, indexes)
   632  }
   633  
   634  // DeleteIndexRowData removes the underlying map of an index, along with its key entry. This should only be used
   635  // when removing an index altogether. If the intent is to clear an index's data, then use SetNomsIndexRows with
   636  // an empty map.
   637  func (t *Table) DeleteIndexRowData(ctx context.Context, indexName string) (*Table, error) {
   638  	indexes, err := t.GetIndexSet(ctx)
   639  	if err != nil {
   640  		return nil, err
   641  	}
   642  
   643  	indexes, err = indexes.DropIndex(ctx, indexName)
   644  	if err != nil {
   645  		return nil, err
   646  	}
   647  
   648  	return t.SetIndexSet(ctx, indexes)
   649  }
   650  
   651  // RenameIndexRowData changes the name for the index data. Does not verify that the new name is unoccupied. If the old
   652  // name does not exist, then this returns the called table without error.
   653  func (t *Table) RenameIndexRowData(ctx context.Context, oldIndexName, newIndexName string) (*Table, error) {
   654  	indexes, err := t.GetIndexSet(ctx)
   655  	if err != nil {
   656  		return nil, err
   657  	}
   658  
   659  	indexes, err = indexes.RenameIndex(ctx, oldIndexName, newIndexName)
   660  	if err != nil {
   661  		return nil, err
   662  	}
   663  
   664  	return t.SetIndexSet(ctx, indexes)
   665  }
   666  
   667  // GetAutoIncrementValue returns the current AUTO_INCREMENT value for this table.
   668  func (t *Table) GetAutoIncrementValue(ctx context.Context) (uint64, error) {
   669  	return t.table.GetAutoIncrement(ctx)
   670  }
   671  
   672  // SetAutoIncrementValue sets the current AUTO_INCREMENT value for this table. This method does not verify that the
   673  // value given is greater than current table values. Setting it lower than current table values will result in
   674  // incorrect key generation on future inserts, causing duplicate key errors.
   675  func (t *Table) SetAutoIncrementValue(ctx context.Context, val uint64) (*Table, error) {
   676  	table, err := t.table.SetAutoIncrement(ctx, val)
   677  	if err != nil {
   678  		return nil, err
   679  	}
   680  	return &Table{table: table}, nil
   681  }
   682  
   683  // AddColumnToRows adds the column named to row data as necessary and returns the resulting table.
   684  func (t *Table) AddColumnToRows(ctx context.Context, newCol string, newSchema schema.Schema) (*Table, error) {
   685  	idx, err := t.table.GetTableRows(ctx)
   686  	if err != nil {
   687  		return nil, err
   688  	}
   689  
   690  	newIdx, err := idx.AddColumnToRows(ctx, newCol, newSchema)
   691  	if err != nil {
   692  		return nil, err
   693  	}
   694  
   695  	newTable, err := t.table.SetTableRows(ctx, newIdx)
   696  	if err != nil {
   697  		return nil, err
   698  	}
   699  
   700  	return &Table{table: newTable}, nil
   701  }
   702  
   703  func (t *Table) DebugString(ctx context.Context, ns tree.NodeStore) string {
   704  	return t.table.DebugString(ctx, ns)
   705  }