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 }