Better error formatting for duplicate key errors (don't include tags)

Signed-off-by: Zach Musgrave <zach@liquidata.co>
This commit is contained in:
Zach Musgrave
2020-09-11 17:41:04 -07:00
parent 2bd381288d
commit 69a6288fc2
2 changed files with 42 additions and 7 deletions

View File

@@ -31,7 +31,7 @@ import (
"github.com/liquidata-inc/dolt/go/store/types"
)
var ErrDuplicatePrimaryKeyFmt = "duplicate primary key given: (%v)"
var ErrDuplicatePrimaryKeyFmt = "duplicate primary key given: %v"
// TableEditor supports making multiple row edits (inserts, updates, deletes) to a table. It does error checking for key
// collision etc. in the Close() method, as well as during Insert / Update.
@@ -173,7 +173,10 @@ func (te *TableEditor) GetIndexedRows(ctx context.Context, key types.Tuple, inde
return nil, err
}
if fieldsVal == nil {
keyStr, _ := types.EncodedValue(ctx, key)
keyStr, err := formatKey(ctx, te.nbf, key)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("index key `%s` does not have a corresponding entry in table", keyStr)
}
@@ -244,11 +247,11 @@ func (te *TableEditor) InsertRow(ctx context.Context, dRow row.Row) error {
// If we've already inserted this key as part of this insert operation, that's an error. Inserting a row that
// already exists in the table will be handled in Close().
if _, ok := te.tea.addedKeys[keyHash]; ok {
value, err := types.EncodedValue(ctx, key)
keyStr, err := formatKey(ctx, te.nbf, key)
if err != nil {
return err
}
return fmt.Errorf(ErrDuplicatePrimaryKeyFmt, value)
return fmt.Errorf(ErrDuplicatePrimaryKeyFmt, keyStr)
}
te.tea.insertedKeys[keyHash] = key
te.tea.addedKeys[keyHash] = key
@@ -397,11 +400,11 @@ func (te *TableEditor) flushEditAccumulator(ctx context.Context, teaInterface in
return errhand.BuildDError("failed to read table").AddCause(err).Build()
}
if rowExists {
value, err := types.EncodedValue(ctx, addedKey)
keyStr, err := formatKey(ctx, te.nbf, addedKey)
if err != nil {
return err
}
return fmt.Errorf(ErrDuplicatePrimaryKeyFmt, value)
return fmt.Errorf(ErrDuplicatePrimaryKeyFmt, keyStr)
}
}
}
@@ -440,6 +443,37 @@ func (te *TableEditor) flushEditAccumulator(ctx context.Context, teaInterface in
return nil
}
// formatKey returns a comma-separated string represnetation of the key given.
func formatKey(ctx context.Context, nbf *types.NomsBinFormat, key types.Value) (string, error) {
tuple, ok := key.(types.Tuple)
if !ok {
return "", fmt.Errorf("Expected types.Tuple but got %T", key)
}
var vals []types.Value
iter, err := tuple.Iterator()
if err != nil {
return "", err
}
for iter.HasMore() {
i, val, err := iter.Next()
if err != nil {
return "", err
}
if i % 2 == 1 {
vals = append(vals, val)
}
}
valsOnlyTuple, err := types.NewTuple(nbf, vals...)
if err != nil {
return "", err
}
return types.EncodedValue(ctx, valsOnlyTuple)
}
func (te *TableEditor) getIndexIterator(ctx context.Context, key types.Tuple, indexName string) (table.TableReadCloser, error) {
var indexEd *IndexEditor
for _, ie := range te.indexEds {

View File

@@ -95,8 +95,9 @@ func (te *sqlTableEditor) Close(ctx *sql.Context) error {
func (te *sqlTableEditor) flush(ctx *sql.Context) error {
newRoot, err := te.tableEditor.Flush(ctx)
if err != nil {
return errhand.BuildDError("failed to write table back to database").AddCause(err).Build()
return err
}
newTable, ok, err := newRoot.GetTable(ctx, te.t.name)
if err != nil {
return errhand.BuildDError("failed to load updated table").AddCause(err).Build()