github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/doltdb/durable/table.go (about) 1 // Copyright 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 durable 16 17 import ( 18 "bytes" 19 "context" 20 "errors" 21 "fmt" 22 23 flatbuffers "github.com/dolthub/flatbuffers/v23/go" 24 25 "github.com/dolthub/dolt/go/gen/fb/serial" 26 "github.com/dolthub/dolt/go/libraries/doltcore/conflict" 27 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 28 "github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding" 29 "github.com/dolthub/dolt/go/store/hash" 30 "github.com/dolthub/dolt/go/store/pool" 31 "github.com/dolthub/dolt/go/store/prolly" 32 "github.com/dolthub/dolt/go/store/prolly/shim" 33 "github.com/dolthub/dolt/go/store/prolly/tree" 34 "github.com/dolthub/dolt/go/store/types" 35 ) 36 37 const ( 38 tableStructName = "table" 39 40 schemaRefKey = "schema_ref" 41 tableRowsKey = "rows" 42 artifactsKey = "artifacts" 43 conflictsKey = "conflicts" 44 conflictSchemasKey = "conflict_schemas" 45 constraintViolationsKey = "constraint_violations" 46 indexesKey = "indexes" 47 autoIncrementKey = "auto_increment" 48 ) 49 50 var ( 51 ErrUnknownAutoIncrementValue = fmt.Errorf("auto increment set for non-numeric column type") 52 ) 53 54 var ( 55 errNbfUnknown = fmt.Errorf("unknown NomsBinFormat") 56 errNbfUnsupported = fmt.Errorf("operation unsupported for NomsBinFormat") 57 ) 58 59 // Table is a Dolt table that can be persisted. 60 type Table interface { 61 // HashOf returns the hash.Hash of this table. 62 HashOf() (hash.Hash, error) 63 64 // Format returns the types.NomsBinFormat for this table. 65 Format() *types.NomsBinFormat 66 67 // GetSchemaHash returns the hash.Hash of this table's schema. 68 GetSchemaHash(ctx context.Context) (hash.Hash, error) 69 // GetSchema returns this table's schema. 70 GetSchema(ctx context.Context) (schema.Schema, error) 71 // SetSchema sets this table's schema. 72 SetSchema(ctx context.Context, sch schema.Schema) (Table, error) 73 74 // GetTableRows returns this tables rows. 75 GetTableRows(ctx context.Context) (Index, error) 76 // SetTableRows sets this table's rows. 77 SetTableRows(ctx context.Context, rows Index) (Table, error) 78 79 // GetIndexes returns the secondary indexes for this table. 80 GetIndexes(ctx context.Context) (IndexSet, error) 81 // SetIndexes sets the secondary indexes for this table. 82 SetIndexes(ctx context.Context, indexes IndexSet) (Table, error) 83 84 // GetArtifacts returns the merge artifacts for this table. 85 GetArtifacts(ctx context.Context) (ArtifactIndex, error) 86 // SetArtifacts sets the merge artifacts for this table. 87 SetArtifacts(ctx context.Context, artifacts ArtifactIndex) (Table, error) 88 89 // GetConflicts returns the merge conflicts for this table. 90 GetConflicts(ctx context.Context) (conflict.ConflictSchema, ConflictIndex, error) 91 // HasConflicts returns true if this table has conflicts. 92 HasConflicts(ctx context.Context) (bool, error) 93 // SetConflicts sets the merge conflicts for this table. 94 SetConflicts(ctx context.Context, sch conflict.ConflictSchema, conflicts ConflictIndex) (Table, error) 95 // ClearConflicts removes all merge conflicts for this table. 96 ClearConflicts(ctx context.Context) (Table, error) 97 98 // GetConstraintViolations returns the constraint violations for this table. 99 GetConstraintViolations(ctx context.Context) (types.Map, error) 100 // SetConstraintViolations sets the constraint violations for this table. 101 SetConstraintViolations(ctx context.Context, violations types.Map) (Table, error) 102 103 // GetAutoIncrement returns the AUTO_INCREMENT sequence value for this table. 104 GetAutoIncrement(ctx context.Context) (uint64, error) 105 // SetAutoIncrement sets the AUTO_INCREMENT sequence value for this table. 106 SetAutoIncrement(ctx context.Context, val uint64) (Table, error) 107 108 // DebugString returns the table contents for debugging purposes 109 DebugString(ctx context.Context, ns tree.NodeStore) string 110 } 111 112 type nomsTable struct { 113 vrw types.ValueReadWriter 114 ns tree.NodeStore 115 tableStruct types.Struct 116 } 117 118 var _ Table = nomsTable{} 119 120 var sharePool = pool.NewBuffPool() 121 122 // NewNomsTable makes a new Table. 123 func NewNomsTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema, rows types.Map, indexes IndexSet, autoIncVal types.Value) (Table, error) { 124 return NewTable(ctx, vrw, ns, sch, nomsIndex{index: rows, vrw: vrw}, indexes, autoIncVal) 125 } 126 127 // NewTable returns a new Table. 128 func NewTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema, rows Index, indexes IndexSet, autoIncVal types.Value) (Table, error) { 129 if vrw.Format().UsesFlatbuffers() { 130 return newDoltDevTable(ctx, vrw, ns, sch, rows, indexes, autoIncVal) 131 } 132 133 schVal, err := encoding.MarshalSchema(ctx, vrw, sch) 134 if err != nil { 135 return nil, err 136 } 137 138 schemaRef, err := refFromNomsValue(ctx, vrw, schVal) 139 if err != nil { 140 return nil, err 141 } 142 143 rowsRef, err := RefFromIndex(ctx, vrw, rows) 144 if err != nil { 145 return nil, err 146 } 147 148 if indexes == nil { 149 indexes, err = NewIndexSet(ctx, vrw, ns) 150 if err != nil { 151 return nil, err 152 } 153 } 154 155 indexesRef, err := refFromNomsValue(ctx, vrw, mapFromIndexSet(indexes)) 156 if err != nil { 157 return nil, err 158 } 159 160 sd := types.StructData{ 161 schemaRefKey: schemaRef, 162 tableRowsKey: rowsRef, 163 indexesKey: indexesRef, 164 } 165 166 if schema.HasAutoIncrement(sch) && autoIncVal != nil { 167 sd[autoIncrementKey] = autoIncVal 168 } 169 170 tableStruct, err := types.NewStruct(vrw.Format(), tableStructName, sd) 171 if err != nil { 172 return nil, err 173 } 174 175 return nomsTable{vrw, ns, tableStruct}, nil 176 } 177 178 // TableFromAddr deserializes the table in the chunk at |addr|. 179 func TableFromAddr(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, addr hash.Hash) (Table, error) { 180 val, err := vrw.ReadValue(ctx, addr) 181 if err != nil { 182 return nil, err 183 } 184 185 if !vrw.Format().UsesFlatbuffers() { 186 st, ok := val.(types.Struct) 187 if !ok { 188 err = errors.New("table ref is unexpected noms value") 189 return nil, err 190 } 191 192 return nomsTable{vrw: vrw, tableStruct: st, ns: ns}, nil 193 } else { 194 sm, ok := val.(types.SerialMessage) 195 if !ok { 196 err = errors.New("table ref is unexpected noms value; not SerialMessage") 197 return nil, err 198 } 199 id := serial.GetFileID(sm) 200 if id != serial.TableFileID { 201 err = errors.New("table ref is unexpected noms value; GetFileID == " + id) 202 return nil, err 203 } 204 st, err := serial.TryGetRootAsTable([]byte(sm), serial.MessagePrefixSz) 205 if err != nil { 206 return nil, err 207 } 208 return doltDevTable{vrw, ns, st}, nil 209 } 210 } 211 212 // RefFromNomsTable serialized |table|, and returns its types.Ref. 213 func RefFromNomsTable(ctx context.Context, table Table) (types.Ref, error) { 214 nt, ok := table.(nomsTable) 215 if ok { 216 return refFromNomsValue(ctx, nt.vrw, nt.tableStruct) 217 } 218 ddt := table.(doltDevTable) 219 220 return refFromNomsValue(ctx, ddt.vrw, ddt.nomsValue()) 221 } 222 223 // VrwFromTable returns the types.ValueReadWriter used by |t|. 224 // todo(andy): this is a temporary method that will be removed when there is a 225 // general-purpose abstraction to replace types.ValueReadWriter. 226 func VrwFromTable(t Table) types.ValueReadWriter { 227 if nt, ok := t.(nomsTable); ok { 228 return nt.vrw 229 } else { 230 ddt := t.(doltDevTable) 231 return ddt.vrw 232 } 233 } 234 235 func NodeStoreFromTable(t Table) tree.NodeStore { 236 if nt, ok := t.(nomsTable); ok { 237 return nt.ns 238 } else { 239 ddt := t.(doltDevTable) 240 return ddt.ns 241 } 242 } 243 244 // valueReadWriter returns the valueReadWriter for this table. 245 func (t nomsTable) valueReadWriter() types.ValueReadWriter { 246 return t.vrw 247 } 248 249 // HashOf implements Table. 250 func (t nomsTable) HashOf() (hash.Hash, error) { 251 return t.tableStruct.Hash(t.vrw.Format()) 252 } 253 254 // Format returns the types.NomsBinFormat for this index. 255 func (t nomsTable) Format() *types.NomsBinFormat { 256 return t.vrw.Format() 257 } 258 259 // GetSchema implements Table. 260 func (t nomsTable) GetSchema(ctx context.Context) (schema.Schema, error) { 261 schemaRefVal, _, err := t.tableStruct.MaybeGet(schemaRefKey) 262 263 if err != nil { 264 return nil, err 265 } 266 267 schemaRef := schemaRefVal.(types.Ref) 268 return schemaFromRef(ctx, t.vrw, schemaRef) 269 } 270 271 // GetSchemaHash implements Table. 272 func (t nomsTable) GetSchemaHash(ctx context.Context) (hash.Hash, error) { 273 r, _, err := t.tableStruct.MaybeGet(schemaRefKey) 274 if err != nil { 275 return hash.Hash{}, err 276 } 277 return r.(types.Ref).TargetHash(), nil 278 } 279 280 // SetSchema implements Table. 281 func (t nomsTable) SetSchema(ctx context.Context, sch schema.Schema) (Table, error) { 282 newSchemaVal, err := encoding.MarshalSchema(ctx, t.vrw, sch) 283 if err != nil { 284 return nil, err 285 } 286 287 schRef, err := refFromNomsValue(ctx, t.vrw, newSchemaVal) 288 if err != nil { 289 return nil, err 290 } 291 292 newTableStruct, err := t.tableStruct.Set(schemaRefKey, schRef) 293 if err != nil { 294 return nil, err 295 } 296 297 return nomsTable{t.vrw, t.ns, newTableStruct}, nil 298 } 299 300 // SetTableRows implements Table. 301 func (t nomsTable) SetTableRows(ctx context.Context, updatedRows Index) (Table, error) { 302 rowsRef, err := RefFromIndex(ctx, t.vrw, updatedRows) 303 if err != nil { 304 return nil, err 305 } 306 307 updatedSt, err := t.tableStruct.Set(tableRowsKey, rowsRef) 308 if err != nil { 309 return nil, err 310 } 311 312 return nomsTable{t.vrw, t.ns, updatedSt}, nil 313 } 314 315 // GetTableRows implements Table. 316 func (t nomsTable) GetTableRows(ctx context.Context) (Index, error) { 317 val, _, err := t.tableStruct.MaybeGet(tableRowsKey) 318 if err != nil { 319 return nil, err 320 } 321 322 sch, err := t.GetSchema(ctx) 323 if err != nil { 324 return nil, err 325 } 326 327 return indexFromRef(ctx, t.vrw, t.ns, sch, val.(types.Ref)) 328 } 329 330 // GetIndexes implements Table. 331 func (t nomsTable) GetIndexes(ctx context.Context) (IndexSet, error) { 332 iv, ok, err := t.tableStruct.MaybeGet(indexesKey) 333 if err != nil { 334 return nil, err 335 } 336 if !ok { 337 return NewIndexSet(ctx, t.vrw, t.ns) 338 } 339 340 im, err := iv.(types.Ref).TargetValue(ctx, t.vrw) 341 if err != nil { 342 return nil, err 343 } 344 345 return nomsIndexSet{ 346 indexes: im.(types.Map), 347 vrw: t.vrw, 348 ns: t.ns, 349 }, nil 350 } 351 352 // SetIndexes implements Table. 353 func (t nomsTable) SetIndexes(ctx context.Context, indexes IndexSet) (Table, error) { 354 if indexes == nil { 355 var err error 356 indexes, err = NewIndexSet(ctx, t.vrw, t.ns) 357 if err != nil { 358 return nil, err 359 } 360 } 361 362 indexesRef, err := refFromNomsValue(ctx, t.vrw, mapFromIndexSet(indexes)) 363 if err != nil { 364 return nil, err 365 } 366 367 newTableStruct, err := t.tableStruct.Set(indexesKey, indexesRef) 368 if err != nil { 369 return nil, err 370 } 371 372 return nomsTable{t.vrw, t.ns, newTableStruct}, nil 373 } 374 375 // GetArtifacts implements Table. 376 func (t nomsTable) GetArtifacts(ctx context.Context) (ArtifactIndex, error) { 377 if t.Format() != types.Format_DOLT { 378 panic("artifacts not implemented for old storage format") 379 } 380 381 sch, err := t.GetSchema(ctx) 382 if err != nil { 383 return nil, err 384 } 385 386 val, ok, err := t.tableStruct.MaybeGet(artifactsKey) 387 if err != nil { 388 return nil, err 389 } 390 if !ok { 391 return NewEmptyArtifactIndex(ctx, t.vrw, t.ns, sch) 392 } 393 394 return artifactIndexFromRef(ctx, t.vrw, t.ns, sch, val.(types.Ref)) 395 } 396 397 // SetArtifacts implements Table. 398 func (t nomsTable) SetArtifacts(ctx context.Context, artifacts ArtifactIndex) (Table, error) { 399 if t.Format() != types.Format_DOLT { 400 panic("artifacts not implemented for old storage format") 401 } 402 403 ref, err := RefFromArtifactIndex(ctx, t.vrw, artifacts) 404 if err != nil { 405 return nil, err 406 } 407 408 updated, err := t.tableStruct.Set(artifactsKey, ref) 409 if err != nil { 410 return nil, err 411 } 412 413 return nomsTable{t.vrw, t.ns, updated}, nil 414 } 415 416 // HasConflicts implements Table. 417 func (t nomsTable) HasConflicts(ctx context.Context) (bool, error) { 418 _, ok, err := t.tableStruct.MaybeGet(conflictSchemasKey) 419 return ok, err 420 } 421 422 // GetConflicts implements Table. 423 func (t nomsTable) GetConflicts(ctx context.Context) (conflict.ConflictSchema, ConflictIndex, error) { 424 schemasVal, ok, err := t.tableStruct.MaybeGet(conflictSchemasKey) 425 if err != nil { 426 return conflict.ConflictSchema{}, nil, err 427 } 428 if !ok { 429 sch, err := t.GetSchema(ctx) 430 if err != nil { 431 return conflict.ConflictSchema{}, nil, err 432 } 433 empty, err := NewEmptyConflictIndex(ctx, t.vrw, t.ns, sch, sch, sch) 434 if err != nil { 435 return conflict.ConflictSchema{}, nil, err 436 } 437 return conflict.ConflictSchema{}, empty, nil 438 } 439 440 schemas, err := conflict.ConflictSchemaFromValue(ctx, t.vrw, schemasVal) 441 if err != nil { 442 return conflict.ConflictSchema{}, nil, err 443 } 444 445 conflictsVal, _, err := t.tableStruct.MaybeGet(conflictsKey) 446 if err != nil { 447 return conflict.ConflictSchema{}, nil, err 448 } 449 450 if conflictsVal == nil { 451 confIndex, err := NewEmptyConflictIndex(ctx, t.vrw, t.ns, schemas.Schema, schemas.MergeSchema, schemas.Base) 452 if err != nil { 453 return conflict.ConflictSchema{}, nil, err 454 } 455 return conflict.ConflictSchema{}, confIndex, nil 456 } 457 458 i, err := conflictIndexFromRef(ctx, t.vrw, t.ns, schemas.Schema, schemas.MergeSchema, schemas.Base, conflictsVal.(types.Ref)) 459 if err != nil { 460 return conflict.ConflictSchema{}, nil, err 461 } 462 463 return schemas, i, nil 464 } 465 466 // SetConflicts implements Table. 467 func (t nomsTable) SetConflicts(ctx context.Context, schemas conflict.ConflictSchema, conflictData ConflictIndex) (Table, error) { 468 if t.Format() == types.Format_DOLT { 469 panic("should use artifacts") 470 } 471 472 conflictsRef, err := RefFromConflictIndex(ctx, t.vrw, conflictData) 473 if err != nil { 474 return nil, err 475 } 476 477 tpl, err := conflict.ValueFromConflictSchema(ctx, t.vrw, schemas) 478 if err != nil { 479 return nil, err 480 } 481 482 updatedSt, err := t.tableStruct.Set(conflictSchemasKey, tpl) 483 if err != nil { 484 return nil, err 485 } 486 487 updatedSt, err = updatedSt.Set(conflictsKey, conflictsRef) 488 if err != nil { 489 return nil, err 490 } 491 492 return nomsTable{t.vrw, t.ns, updatedSt}, nil 493 } 494 495 // GetConflictSchemas implements Table. 496 func (t nomsTable) GetConflictSchemas(ctx context.Context) (base, sch, mergeSch schema.Schema, err error) { 497 schemasVal, ok, err := t.tableStruct.MaybeGet(conflictSchemasKey) 498 499 if err != nil { 500 return nil, nil, nil, err 501 } 502 503 if ok { 504 schemas, err := conflict.ConflictFromTuple(schemasVal.(types.Tuple)) 505 506 if err != nil { 507 return nil, nil, nil, err 508 } 509 510 baseRef := schemas.Base.(types.Ref) 511 valRef := schemas.Value.(types.Ref) 512 mergeRef := schemas.MergeValue.(types.Ref) 513 514 var baseSch, sch, mergeSch schema.Schema 515 if baseSch, err = schemaFromRef(ctx, t.vrw, baseRef); err == nil { 516 if sch, err = schemaFromRef(ctx, t.vrw, valRef); err == nil { 517 mergeSch, err = schemaFromRef(ctx, t.vrw, mergeRef) 518 } 519 } 520 521 return baseSch, sch, mergeSch, err 522 } 523 return nil, nil, nil, nil 524 } 525 526 // ClearConflicts implements Table. 527 func (t nomsTable) ClearConflicts(ctx context.Context) (Table, error) { 528 if t.Format() == types.Format_DOLT { 529 panic("should use artifacts") 530 } 531 532 tSt, err := t.tableStruct.Delete(conflictSchemasKey) 533 534 if err != nil { 535 return nil, err 536 } 537 538 tSt, err = tSt.Delete(conflictsKey) 539 540 if err != nil { 541 return nil, err 542 } 543 544 return nomsTable{t.vrw, t.ns, tSt}, nil 545 } 546 547 // GetConstraintViolations implements Table. 548 func (t nomsTable) GetConstraintViolations(ctx context.Context) (types.Map, error) { 549 constraintViolationsRefVal, ok, err := t.tableStruct.MaybeGet(constraintViolationsKey) 550 if err != nil { 551 return types.EmptyMap, err 552 } 553 if !ok { 554 emptyMap, err := types.NewMap(ctx, t.vrw) 555 return emptyMap, err 556 } 557 constraintViolationsVal, err := constraintViolationsRefVal.(types.Ref).TargetValue(ctx, t.vrw) 558 if err != nil { 559 return types.EmptyMap, err 560 } 561 return constraintViolationsVal.(types.Map), nil 562 } 563 564 // SetConstraintViolations implements Table. 565 func (t nomsTable) SetConstraintViolations(ctx context.Context, violationsMap types.Map) (Table, error) { 566 // We can't just call violationsMap.Empty() as we can't guarantee that the caller passed in an instantiated map 567 if violationsMap == types.EmptyMap || violationsMap.Len() == 0 { 568 updatedStruct, err := t.tableStruct.Delete(constraintViolationsKey) 569 if err != nil { 570 return nil, err 571 } 572 return nomsTable{t.vrw, t.ns, updatedStruct}, nil 573 } 574 constraintViolationsRef, err := refFromNomsValue(ctx, t.vrw, violationsMap) 575 if err != nil { 576 return nil, err 577 } 578 updatedStruct, err := t.tableStruct.Set(constraintViolationsKey, constraintViolationsRef) 579 if err != nil { 580 return nil, err 581 } 582 return nomsTable{t.vrw, t.ns, updatedStruct}, nil 583 } 584 585 // GetAutoIncrement implements Table. 586 func (t nomsTable) GetAutoIncrement(ctx context.Context) (uint64, error) { 587 val, ok, err := t.tableStruct.MaybeGet(autoIncrementKey) 588 if err != nil { 589 return 0, err 590 } 591 if !ok { 592 return 1, nil 593 } 594 595 // older versions might have serialized auto-increment 596 // value as types.Int or types.Float. 597 switch t := val.(type) { 598 case types.Int: 599 return uint64(t), nil 600 case types.Uint: 601 return uint64(t), nil 602 case types.Float: 603 return uint64(t), nil 604 default: 605 return 0, ErrUnknownAutoIncrementValue 606 } 607 } 608 609 // SetAutoIncrement implements Table. 610 func (t nomsTable) SetAutoIncrement(ctx context.Context, val uint64) (Table, error) { 611 st, err := t.tableStruct.Set(autoIncrementKey, types.Uint(val)) 612 if err != nil { 613 return nil, err 614 } 615 return nomsTable{t.vrw, t.ns, st}, nil 616 } 617 618 func (t nomsTable) DebugString(ctx context.Context, ns tree.NodeStore) string { 619 var buf bytes.Buffer 620 err := types.WriteEncodedValue(ctx, &buf, t.tableStruct) 621 if err != nil { 622 panic(err) 623 } 624 625 schemaRefVal, _, _ := t.tableStruct.MaybeGet(schemaRefKey) 626 schemaRef := schemaRefVal.(types.Ref) 627 schemaVal, err := schemaRef.TargetValue(ctx, t.vrw) 628 if err != nil { 629 panic(err) 630 } 631 632 buf.WriteString("\nschema: ") 633 err = types.WriteEncodedValue(ctx, &buf, schemaVal) 634 if err != nil { 635 panic(err) 636 } 637 638 iv, ok, err := t.tableStruct.MaybeGet(indexesKey) 639 if err != nil { 640 panic(err) 641 } 642 643 if ok { 644 buf.WriteString("\nindexes: ") 645 im, err := iv.(types.Ref).TargetValue(ctx, t.vrw) 646 if err != nil { 647 panic(err) 648 } 649 650 err = types.WriteEncodedValue(ctx, &buf, im) 651 if err != nil { 652 panic(err) 653 } 654 } 655 656 buf.WriteString("\ndata:\n") 657 data, err := t.GetTableRows(ctx) 658 if err != nil { 659 panic(err) 660 } 661 662 err = types.WriteEncodedValue(ctx, &buf, NomsMapFromIndex(data)) 663 if err != nil { 664 panic(err) 665 } 666 667 return buf.String() 668 } 669 670 func refFromNomsValue(ctx context.Context, vrw types.ValueReadWriter, val types.Value) (types.Ref, error) { 671 return vrw.WriteValue(ctx, val) 672 } 673 674 func schemaFromRef(ctx context.Context, vrw types.ValueReadWriter, ref types.Ref) (schema.Schema, error) { 675 return schemaFromAddr(ctx, vrw, ref.TargetHash()) 676 } 677 678 func schemaFromAddr(ctx context.Context, vrw types.ValueReadWriter, addr hash.Hash) (schema.Schema, error) { 679 return encoding.UnmarshalSchemaAtAddr(ctx, vrw, addr) 680 } 681 682 type doltDevTable struct { 683 vrw types.ValueReadWriter 684 ns tree.NodeStore 685 msg *serial.Table 686 } 687 688 func (t doltDevTable) DebugString(ctx context.Context, ns tree.NodeStore) string { 689 rows, err := t.GetTableRows(ctx) 690 if err != nil { 691 panic(err) 692 } 693 694 schema, err := t.GetSchema(ctx) 695 if err != nil { 696 panic(err) 697 } 698 699 return rows.DebugString(ctx, ns, schema) 700 } 701 702 var _ Table = doltDevTable{} 703 704 type serialTableFields struct { 705 schema []byte 706 rows []byte 707 indexes prolly.AddressMap 708 conflictsdata []byte 709 conflictsours []byte 710 conflictstheirs []byte 711 conflictsancestor []byte 712 violations []byte 713 artifacts []byte 714 autoincval uint64 715 } 716 717 func (fields serialTableFields) write() (*serial.Table, error) { 718 // TODO: Chance for a pool. 719 builder := flatbuffers.NewBuilder(1024) 720 721 indexesam := fields.indexes 722 indexesbytes := []byte(tree.ValueFromNode(indexesam.Node()).(types.SerialMessage)) 723 724 schemaoff := builder.CreateByteVector(fields.schema) 725 rowsoff := builder.CreateByteVector(fields.rows) 726 indexesoff := builder.CreateByteVector(indexesbytes) 727 conflictsdataoff := builder.CreateByteVector(fields.conflictsdata) 728 conflictsoursoff := builder.CreateByteVector(fields.conflictsours) 729 conflictstheirsoff := builder.CreateByteVector(fields.conflictstheirs) 730 conflictsbaseoff := builder.CreateByteVector(fields.conflictsancestor) 731 serial.ConflictsStart(builder) 732 serial.ConflictsAddData(builder, conflictsdataoff) 733 serial.ConflictsAddOurSchema(builder, conflictsoursoff) 734 serial.ConflictsAddTheirSchema(builder, conflictstheirsoff) 735 serial.ConflictsAddAncestorSchema(builder, conflictsbaseoff) 736 conflictsoff := serial.ConflictsEnd(builder) 737 738 violationsoff := builder.CreateByteVector(fields.violations) 739 artifactsoff := builder.CreateByteVector(fields.artifacts) 740 741 serial.TableStart(builder) 742 serial.TableAddSchema(builder, schemaoff) 743 serial.TableAddPrimaryIndex(builder, rowsoff) 744 serial.TableAddSecondaryIndexes(builder, indexesoff) 745 serial.TableAddAutoIncrementValue(builder, fields.autoincval) 746 serial.TableAddConflicts(builder, conflictsoff) 747 serial.TableAddViolations(builder, violationsoff) 748 serial.TableAddArtifacts(builder, artifactsoff) 749 bs := serial.FinishMessage(builder, serial.TableEnd(builder), []byte(serial.TableFileID)) 750 return serial.TryGetRootAsTable(bs, serial.MessagePrefixSz) 751 } 752 753 func newDoltDevTable(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeStore, sch schema.Schema, rows Index, indexes IndexSet, autoIncVal types.Value) (Table, error) { 754 schVal, err := encoding.MarshalSchema(ctx, vrw, sch) 755 if err != nil { 756 return nil, err 757 } 758 759 schemaRef, err := refFromNomsValue(ctx, vrw, schVal) 760 if err != nil { 761 return nil, err 762 } 763 schemaAddr := schemaRef.TargetHash() 764 765 rowsbytes, err := rows.bytes() 766 if err != nil { 767 return nil, err 768 } 769 770 if indexes == nil { 771 indexes, err = NewIndexSet(ctx, vrw, ns) 772 if err != nil { 773 return nil, err 774 } 775 } 776 777 var autoInc uint64 778 if autoIncVal != nil { 779 autoInc = uint64(autoIncVal.(types.Uint)) 780 } 781 782 var emptyhash hash.Hash 783 msg, err := serialTableFields{ 784 schema: schemaAddr[:], 785 rows: rowsbytes, 786 indexes: indexes.(doltDevIndexSet).am, 787 conflictsdata: emptyhash[:], 788 conflictsours: emptyhash[:], 789 conflictstheirs: emptyhash[:], 790 conflictsancestor: emptyhash[:], 791 violations: emptyhash[:], 792 artifacts: emptyhash[:], 793 autoincval: autoInc, 794 }.write() 795 if err != nil { 796 return nil, err 797 } 798 799 return doltDevTable{vrw, ns, msg}, nil 800 } 801 802 func (t doltDevTable) nomsValue() types.Value { 803 return types.SerialMessage(t.msg.Table().Bytes) 804 } 805 806 func (t doltDevTable) HashOf() (hash.Hash, error) { 807 return t.nomsValue().Hash(t.Format()) 808 } 809 810 func (t doltDevTable) Format() *types.NomsBinFormat { 811 return t.vrw.Format() 812 } 813 814 func (t doltDevTable) GetSchemaHash(ctx context.Context) (hash.Hash, error) { 815 return hash.New(t.msg.SchemaBytes()), nil 816 } 817 818 func (t doltDevTable) GetSchema(ctx context.Context) (schema.Schema, error) { 819 addr := hash.New(t.msg.SchemaBytes()) 820 return schemaFromAddr(ctx, t.vrw, addr) 821 } 822 823 func (t doltDevTable) SetSchema(ctx context.Context, sch schema.Schema) (Table, error) { 824 newSchemaVal, err := encoding.MarshalSchema(ctx, t.vrw, sch) 825 if err != nil { 826 return nil, err 827 } 828 829 schRef, err := refFromNomsValue(ctx, t.vrw, newSchemaVal) 830 if err != nil { 831 return nil, err 832 } 833 834 addr := schRef.TargetHash() 835 msg := t.clone() 836 copy(msg.SchemaBytes(), addr[:]) 837 return doltDevTable{t.vrw, t.ns, msg}, nil 838 } 839 840 func (t doltDevTable) GetTableRows(ctx context.Context) (Index, error) { 841 rowbytes := t.msg.PrimaryIndexBytes() 842 sch, err := t.GetSchema(ctx) 843 if err != nil { 844 return nil, err 845 } 846 m, err := shim.MapFromValue(types.SerialMessage(rowbytes), sch, t.ns) 847 if err != nil { 848 return nil, err 849 } 850 return IndexFromProllyMap(m), nil 851 } 852 853 func (t doltDevTable) SetTableRows(ctx context.Context, rows Index) (Table, error) { 854 rowsbytes, err := rows.bytes() 855 if err != nil { 856 return nil, err 857 } 858 859 fields, err := t.fields() 860 if err != nil { 861 return nil, err 862 } 863 fields.rows = rowsbytes 864 msg, err := fields.write() 865 if err != nil { 866 return nil, err 867 } 868 869 return doltDevTable{t.vrw, t.ns, msg}, nil 870 } 871 872 func (t doltDevTable) GetIndexes(ctx context.Context) (IndexSet, error) { 873 ambytes := t.msg.SecondaryIndexesBytes() 874 node, err := tree.NodeFromBytes(ambytes) 875 if err != nil { 876 return nil, err 877 } 878 ns := t.ns 879 am, err := prolly.NewAddressMap(node, ns) 880 if err != nil { 881 return nil, err 882 } 883 return doltDevIndexSet{t.vrw, t.ns, am}, nil 884 } 885 886 func (t doltDevTable) SetIndexes(ctx context.Context, indexes IndexSet) (Table, error) { 887 fields, err := t.fields() 888 if err != nil { 889 return nil, err 890 } 891 fields.indexes = indexes.(doltDevIndexSet).am 892 msg, err := fields.write() 893 if err != nil { 894 return nil, err 895 } 896 return doltDevTable{t.vrw, t.ns, msg}, nil 897 } 898 899 func (t doltDevTable) GetConflicts(ctx context.Context) (conflict.ConflictSchema, ConflictIndex, error) { 900 conflicts, err := t.msg.TryConflicts(nil) 901 if err != nil { 902 return conflict.ConflictSchema{}, nil, err 903 } 904 905 ouraddr := hash.New(conflicts.OurSchemaBytes()) 906 theiraddr := hash.New(conflicts.TheirSchemaBytes()) 907 baseaddr := hash.New(conflicts.AncestorSchemaBytes()) 908 909 if ouraddr.IsEmpty() { 910 sch, err := t.GetSchema(ctx) 911 if err != nil { 912 return conflict.ConflictSchema{}, nil, err 913 } 914 empty, err := NewEmptyConflictIndex(ctx, t.vrw, t.ns, sch, sch, sch) 915 if err != nil { 916 return conflict.ConflictSchema{}, nil, err 917 } 918 return conflict.ConflictSchema{}, empty, nil 919 } 920 921 ourschema, err := getSchemaAtAddr(ctx, t.vrw, ouraddr) 922 if err != nil { 923 return conflict.ConflictSchema{}, nil, err 924 } 925 theirschema, err := getSchemaAtAddr(ctx, t.vrw, theiraddr) 926 if err != nil { 927 return conflict.ConflictSchema{}, nil, err 928 } 929 baseschema, err := getSchemaAtAddr(ctx, t.vrw, baseaddr) 930 if err != nil { 931 return conflict.ConflictSchema{}, nil, err 932 } 933 934 conflictschema := conflict.ConflictSchema{ 935 Base: baseschema, 936 Schema: ourschema, 937 MergeSchema: theirschema, 938 } 939 940 mapaddr := hash.New(conflicts.DataBytes()) 941 var conflictIdx ConflictIndex 942 if mapaddr.IsEmpty() { 943 conflictIdx, err = NewEmptyConflictIndex(ctx, t.vrw, t.ns, ourschema, theirschema, baseschema) 944 if err != nil { 945 return conflict.ConflictSchema{}, nil, err 946 } 947 } else { 948 conflictIdx, err = conflictIndexFromAddr(ctx, t.vrw, t.ns, ourschema, theirschema, baseschema, mapaddr) 949 if err != nil { 950 return conflict.ConflictSchema{}, nil, err 951 } 952 } 953 954 return conflictschema, conflictIdx, nil 955 } 956 957 // GetArtifacts implements Table. 958 func (t doltDevTable) GetArtifacts(ctx context.Context) (ArtifactIndex, error) { 959 if t.Format() != types.Format_DOLT { 960 panic("artifacts only implemented for DOLT") 961 } 962 963 sch, err := t.GetSchema(ctx) 964 if err != nil { 965 return nil, err 966 } 967 968 addr := hash.New(t.msg.ArtifactsBytes()) 969 if addr.IsEmpty() { 970 return NewEmptyArtifactIndex(ctx, t.vrw, t.ns, sch) 971 } 972 973 return artifactIndexFromAddr(ctx, t.vrw, t.ns, sch, addr) 974 } 975 976 // SetArtifacts implements Table. 977 func (t doltDevTable) SetArtifacts(ctx context.Context, artifacts ArtifactIndex) (Table, error) { 978 if t.Format() != types.Format_DOLT { 979 panic("artifacts only implemented for DOLT") 980 } 981 982 var addr hash.Hash 983 if artifacts != nil { 984 c, err := artifacts.Count() 985 if err != nil { 986 return nil, err 987 } 988 if c != 0 { 989 ref, err := RefFromArtifactIndex(ctx, t.vrw, artifacts) 990 if err != nil { 991 return nil, err 992 } 993 addr = ref.TargetHash() 994 } 995 } 996 msg := t.clone() 997 copy(msg.ArtifactsBytes(), addr[:]) 998 return doltDevTable{t.vrw, t.ns, msg}, nil 999 } 1000 1001 func (t doltDevTable) HasConflicts(ctx context.Context) (bool, error) { 1002 1003 conflicts, err := t.msg.TryConflicts(nil) 1004 if err != nil { 1005 return false, err 1006 } 1007 addr := hash.New(conflicts.OurSchemaBytes()) 1008 return !addr.IsEmpty(), nil 1009 } 1010 1011 func (t doltDevTable) SetConflicts(ctx context.Context, sch conflict.ConflictSchema, conflicts ConflictIndex) (Table, error) { 1012 conflictsRef, err := RefFromConflictIndex(ctx, t.vrw, conflicts) 1013 if err != nil { 1014 return nil, err 1015 } 1016 conflictsAddr := conflictsRef.TargetHash() 1017 1018 baseaddr, err := getAddrForSchema(ctx, t.vrw, sch.Base) 1019 if err != nil { 1020 return nil, err 1021 } 1022 ouraddr, err := getAddrForSchema(ctx, t.vrw, sch.Schema) 1023 if err != nil { 1024 return nil, err 1025 } 1026 theiraddr, err := getAddrForSchema(ctx, t.vrw, sch.MergeSchema) 1027 if err != nil { 1028 return nil, err 1029 } 1030 1031 msg := t.clone() 1032 cmsg, err := msg.TryConflicts(nil) 1033 if err != nil { 1034 return nil, err 1035 } 1036 copy(cmsg.DataBytes(), conflictsAddr[:]) 1037 copy(cmsg.OurSchemaBytes(), ouraddr[:]) 1038 copy(cmsg.TheirSchemaBytes(), theiraddr[:]) 1039 copy(cmsg.AncestorSchemaBytes(), baseaddr[:]) 1040 1041 return doltDevTable{t.vrw, t.ns, msg}, nil 1042 } 1043 1044 func (t doltDevTable) ClearConflicts(ctx context.Context) (Table, error) { 1045 msg := t.clone() 1046 conflicts, err := msg.TryConflicts(nil) 1047 if err != nil { 1048 return nil, err 1049 } 1050 var emptyhash hash.Hash 1051 copy(conflicts.DataBytes(), emptyhash[:]) 1052 copy(conflicts.OurSchemaBytes(), emptyhash[:]) 1053 copy(conflicts.TheirSchemaBytes(), emptyhash[:]) 1054 copy(conflicts.AncestorSchemaBytes(), emptyhash[:]) 1055 return doltDevTable{t.vrw, t.ns, msg}, nil 1056 } 1057 1058 func (t doltDevTable) GetConstraintViolations(ctx context.Context) (types.Map, error) { 1059 addr := hash.New(t.msg.ViolationsBytes()) 1060 if addr.IsEmpty() { 1061 return types.NewMap(ctx, t.vrw) 1062 } 1063 v, err := t.vrw.ReadValue(ctx, addr) 1064 if err != nil { 1065 return types.Map{}, err 1066 } 1067 return v.(types.Map), nil 1068 } 1069 1070 func (t doltDevTable) SetConstraintViolations(ctx context.Context, violations types.Map) (Table, error) { 1071 var addr hash.Hash 1072 if violations != types.EmptyMap && violations.Len() != 0 { 1073 ref, err := refFromNomsValue(ctx, t.vrw, violations) 1074 if err != nil { 1075 return nil, err 1076 } 1077 addr = ref.TargetHash() 1078 } 1079 msg := t.clone() 1080 copy(msg.ViolationsBytes(), addr[:]) 1081 return doltDevTable{t.vrw, t.ns, msg}, nil 1082 } 1083 1084 func (t doltDevTable) GetAutoIncrement(ctx context.Context) (uint64, error) { 1085 res := t.msg.AutoIncrementValue() 1086 if res == 0 { 1087 return 1, nil 1088 } 1089 return res, nil 1090 } 1091 1092 func (t doltDevTable) SetAutoIncrement(ctx context.Context, val uint64) (Table, error) { 1093 // TODO: This clones before checking if the mutate will work. 1094 msg := t.clone() 1095 if !msg.MutateAutoIncrementValue(val) { 1096 fields, err := t.fields() 1097 if err != nil { 1098 return nil, err 1099 } 1100 fields.autoincval = val 1101 msg, err = fields.write() 1102 if err != nil { 1103 return nil, err 1104 } 1105 } 1106 return doltDevTable{t.vrw, t.ns, msg}, nil 1107 } 1108 1109 func (t doltDevTable) clone() *serial.Table { 1110 bs := make([]byte, len(t.msg.Table().Bytes)) 1111 copy(bs, t.msg.Table().Bytes) 1112 var ret serial.Table 1113 ret.Init(bs, t.msg.Table().Pos) 1114 return &ret 1115 } 1116 1117 func (t doltDevTable) fields() (serialTableFields, error) { 1118 ambytes := t.msg.SecondaryIndexesBytes() 1119 node, err := tree.NodeFromBytes(ambytes) 1120 if err != nil { 1121 return serialTableFields{}, err 1122 } 1123 ns := t.ns 1124 1125 conflicts, err := t.msg.TryConflicts(nil) 1126 if err != nil { 1127 return serialTableFields{}, err 1128 } 1129 am, err := prolly.NewAddressMap(node, ns) 1130 if err != nil { 1131 return serialTableFields{}, err 1132 } 1133 return serialTableFields{ 1134 schema: t.msg.SchemaBytes(), 1135 rows: t.msg.PrimaryIndexBytes(), 1136 indexes: am, 1137 conflictsdata: conflicts.DataBytes(), 1138 conflictsours: conflicts.OurSchemaBytes(), 1139 conflictstheirs: conflicts.TheirSchemaBytes(), 1140 conflictsancestor: conflicts.AncestorSchemaBytes(), 1141 violations: t.msg.ViolationsBytes(), 1142 artifacts: t.msg.ArtifactsBytes(), 1143 autoincval: t.msg.AutoIncrementValue(), 1144 }, nil 1145 } 1146 1147 func getSchemaAtAddr(ctx context.Context, vrw types.ValueReadWriter, addr hash.Hash) (schema.Schema, error) { 1148 return encoding.UnmarshalSchemaAtAddr(ctx, vrw, addr) 1149 } 1150 1151 func getAddrForSchema(ctx context.Context, vrw types.ValueReadWriter, sch schema.Schema) (hash.Hash, error) { 1152 st, err := encoding.MarshalSchema(ctx, vrw, sch) 1153 if err != nil { 1154 return hash.Hash{}, err 1155 } 1156 ref, err := vrw.WriteValue(ctx, st) 1157 if err != nil { 1158 return hash.Hash{}, err 1159 } 1160 return ref.TargetHash(), nil 1161 }