tdb/constraint_unique.go

46 lines
1.2 KiB
Go

package tdb
import (
"bytes"
"errors"
"fmt"
)
type uniqueConstraint struct {
table *table
field dbField
index indexish
}
func newUniqueConstraint(table *table, index indexish, field dbField) (constraintish, error) {
if table == nil {
return nil, errors.New("[constraint] [unique] unable to create without table")
}
if index == nil {
return nil, fmt.Errorf("[constraint] [unique] is only valid for indicies (to avoid full table scans)")
}
return &uniqueConstraint{
table: table,
field: field,
index: index,
}, nil
}
func (c *uniqueConstraint) validate(tx *Tx, pv dbPtrValue) error {
indexedVals := c.index.indexedValues(pv)
keyValue := c.index.keyValue(pv)
for _, indexedVal := range indexedVals {
if err := c.index.iteratePrefixed(tx, indexedVal, func(indexed []byte) (IterationSignal, error) {
if !bytes.Equal(keyValue, indexed) {
c.table.debugLogf("[constraint] [unique] violation: record with '%s'.'%s' = '%s' already exists (id: %s)", c.table.name, c.field.Name, indexedVal, indexed)
return StopIteration, fmt.Errorf("[constraint] [unique] violation for field '%s'.'%s'", c.table.name, c.field.Name)
}
return StopIteration, nil
}); err != nil {
return err
}
}
return nil
}