mirror of
https://github.com/dolthub/dolt.git
synced 2026-03-15 19:31:03 -05:00
Bug fix for unresolved FK fields not being included in the FK's hash
This commit is contained in:
@@ -216,44 +216,62 @@ func (fk ForeignKey) DeepEquals(other ForeignKey) bool {
|
||||
}
|
||||
|
||||
// HashOf returns the Noms hash of a ForeignKey.
|
||||
func (fk ForeignKey) HashOf() hash.Hash {
|
||||
var bb bytes.Buffer
|
||||
bb.Write([]byte(fk.Name))
|
||||
bb.Write([]byte(fk.TableName))
|
||||
bb.Write([]byte(fk.TableIndex))
|
||||
func (fk ForeignKey) HashOf() (hash.Hash, error) {
|
||||
var fields []interface{}
|
||||
fields = append(fields, fk.Name, fk.TableName, fk.TableIndex)
|
||||
for _, t := range fk.TableColumns {
|
||||
_ = binary.Write(&bb, binary.LittleEndian, t)
|
||||
fields = append(fields, t)
|
||||
}
|
||||
bb.Write([]byte(fk.ReferencedTableName))
|
||||
bb.Write([]byte(fk.ReferencedTableIndex))
|
||||
fields = append(fields, fk.ReferencedTableName, fk.ReferencedTableIndex)
|
||||
for _, t := range fk.ReferencedTableColumns {
|
||||
_ = binary.Write(&bb, binary.LittleEndian, t)
|
||||
fields = append(fields, t)
|
||||
}
|
||||
bb.Write([]byte{byte(fk.OnUpdate), byte(fk.OnDelete)})
|
||||
fields = append(fields, []byte{byte(fk.OnUpdate), byte(fk.OnDelete)})
|
||||
for _, col := range fk.UnresolvedFKDetails.TableColumns {
|
||||
_ = binary.Write(&bb, binary.LittleEndian, col)
|
||||
fields = append(fields, col)
|
||||
}
|
||||
for _, col := range fk.UnresolvedFKDetails.ReferencedTableColumns {
|
||||
_ = binary.Write(&bb, binary.LittleEndian, col)
|
||||
fields = append(fields, col)
|
||||
}
|
||||
|
||||
return hash.Of(bb.Bytes())
|
||||
var bb bytes.Buffer
|
||||
for _, field := range fields {
|
||||
var err error
|
||||
switch t := field.(type) {
|
||||
case string:
|
||||
_, err = bb.Write([]byte(t))
|
||||
case []byte:
|
||||
_, err = bb.Write(t)
|
||||
case uint64:
|
||||
err = binary.Write(&bb, binary.LittleEndian, t)
|
||||
default:
|
||||
return hash.Hash{}, fmt.Errorf("unsupported type %T", t)
|
||||
}
|
||||
if err != nil {
|
||||
return hash.Hash{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return hash.Of(bb.Bytes()), nil
|
||||
}
|
||||
|
||||
// CombinedHash returns a combined hash value for all foreign keys in the slice provided.
|
||||
// An empty slice has a zero hash.
|
||||
func CombinedHash(fks []ForeignKey) hash.Hash {
|
||||
func CombinedHash(fks []ForeignKey) (hash.Hash, error) {
|
||||
if len(fks) == 0 {
|
||||
return hash.Hash{}
|
||||
return hash.Hash{}, nil
|
||||
}
|
||||
|
||||
var bb bytes.Buffer
|
||||
for _, fk := range fks {
|
||||
h := fk.HashOf()
|
||||
h, err := fk.HashOf()
|
||||
if err != nil {
|
||||
return hash.Hash{}, err
|
||||
}
|
||||
bb.Write(h[:])
|
||||
}
|
||||
|
||||
return hash.Of(bb.Bytes())
|
||||
return hash.Of(bb.Bytes()), nil
|
||||
}
|
||||
|
||||
// IsSelfReferential returns whether the table declaring the foreign key is also referenced by the foreign key.
|
||||
@@ -330,7 +348,11 @@ func (fkc *ForeignKeyCollection) AddKeys(fks ...ForeignKey) error {
|
||||
// 8 char = 5 base32 bytes, should be collision resistant
|
||||
// TODO: constraint names should be unique, and this isn't guaranteed to be.
|
||||
// This logic needs to live at the table / DB level.
|
||||
key.Name = key.HashOf().String()[:8]
|
||||
fkHash, err := key.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key.Name = fkHash.String()[:8]
|
||||
}
|
||||
|
||||
if _, ok := fkc.GetByNameCaseInsensitive(key.Name); ok {
|
||||
@@ -347,7 +369,11 @@ func (fkc *ForeignKeyCollection) AddKeys(fks ...ForeignKey) error {
|
||||
}
|
||||
}
|
||||
|
||||
fkc.foreignKeys[key.HashOf().String()] = key
|
||||
fkHash, err := key.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fkc.foreignKeys[fkHash.String()] = key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -631,7 +657,11 @@ func (fkc *ForeignKeyCollection) RemoveTables(ctx context.Context, tables ...str
|
||||
return fmt.Errorf("unable to remove `%s` since it is referenced from table `%s`", fk.ReferencedTableName, fk.TableName)
|
||||
}
|
||||
if dropChild {
|
||||
delete(fkc.foreignKeys, fk.HashOf().String())
|
||||
fkHash, err := fk.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(fkc.foreignKeys, fkHash.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -649,7 +679,12 @@ func (fkc *ForeignKeyCollection) RemoveAndUnresolveTables(ctx context.Context, r
|
||||
if !fk.IsResolved() {
|
||||
continue
|
||||
}
|
||||
delete(fkc.foreignKeys, fk.HashOf().String())
|
||||
|
||||
fkHash, err := fk.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(fkc.foreignKeys, fkHash.String())
|
||||
|
||||
fk.UnresolvedFKDetails.TableColumns = make([]string, len(fk.TableColumns))
|
||||
fk.UnresolvedFKDetails.ReferencedTableColumns = make([]string, len(fk.ReferencedTableColumns))
|
||||
@@ -700,10 +735,19 @@ func (fkc *ForeignKeyCollection) RemoveAndUnresolveTables(ctx context.Context, r
|
||||
fk.ReferencedTableColumns = nil
|
||||
fk.TableIndex = ""
|
||||
fk.ReferencedTableIndex = ""
|
||||
fkc.foreignKeys[fk.HashOf().String()] = fk
|
||||
|
||||
fkHash, err = fk.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fkc.foreignKeys[fkHash.String()] = fk
|
||||
}
|
||||
if dropChild {
|
||||
delete(fkc.foreignKeys, fk.HashOf().String())
|
||||
fkHash, err := fk.HashOf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(fkc.foreignKeys, fkHash.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -25,11 +25,72 @@ import (
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/commands"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
func TestForeignKeyHashOf(t *testing.T) {
|
||||
// Assert that we can get an expected hash for a simple Foreign Key
|
||||
t.Run("HashOf for resolved foreign key", func(t *testing.T) {
|
||||
fk := doltdb.ForeignKey{
|
||||
Name: "fk1",
|
||||
TableName: "table1",
|
||||
TableIndex: "i1",
|
||||
TableColumns: []uint64{123},
|
||||
ReferencedTableName: "parentTable",
|
||||
ReferencedTableIndex: "i2",
|
||||
ReferencedTableColumns: []uint64{321},
|
||||
OnUpdate: 0,
|
||||
OnDelete: 0,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{},
|
||||
}
|
||||
hashOf, err := fk.HashOf()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "65brfkb3fh6n7kgpv8d38mjb6krrc54r", hashOf.String())
|
||||
})
|
||||
|
||||
// Assert that two unresolved Foreign Keys get unique hashes, when only their unresolved FK details are different
|
||||
t.Run("HashOf for unresolved FK uses unresolved fields", func(t *testing.T) {
|
||||
fk1 := doltdb.ForeignKey{
|
||||
Name: "",
|
||||
TableName: "table1",
|
||||
TableIndex: "i1",
|
||||
TableColumns: nil,
|
||||
ReferencedTableName: "parentTable",
|
||||
ReferencedTableIndex: "i2",
|
||||
ReferencedTableColumns: nil,
|
||||
OnUpdate: 0,
|
||||
OnDelete: 0,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"col1"},
|
||||
ReferencedTableColumns: []string{"col2"},
|
||||
},
|
||||
}
|
||||
hash1, err := fk1.HashOf()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "qiv9l4juuk20buqml2unlbohfvo95mcd", hash1.String())
|
||||
|
||||
fk2 := doltdb.ForeignKey{
|
||||
Name: "",
|
||||
TableName: "table1",
|
||||
TableIndex: "i1",
|
||||
TableColumns: nil,
|
||||
ReferencedTableName: "parentTable",
|
||||
ReferencedTableIndex: "i2",
|
||||
ReferencedTableColumns: nil,
|
||||
OnUpdate: 0,
|
||||
OnDelete: 0,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"col2"},
|
||||
ReferencedTableColumns: []string{"col2"},
|
||||
},
|
||||
}
|
||||
hash2, err := fk2.HashOf()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "cdglg27qlu0dva6k87vriasnn11o2bnn", hash2.String())
|
||||
assert.NotEqual(t, hash1, hash2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestForeignKeys(t *testing.T) {
|
||||
t.Skip("foreign key representation has changed, need to update tests")
|
||||
for _, test := range foreignKeyTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testForeignKeys(t, test)
|
||||
@@ -38,7 +99,6 @@ func TestForeignKeys(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestForeignKeyErrors(t *testing.T) {
|
||||
skipNewFormat(t)
|
||||
cmds := []testCommand{
|
||||
{commands.SqlCmd{}, []string{"-q", `CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX (v1));`}},
|
||||
{commands.SqlCmd{}, []string{"-q", `CREATE TABLE test2(pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX (v1),` +
|
||||
@@ -62,12 +122,6 @@ func TestForeignKeyErrors(t *testing.T) {
|
||||
require.Equal(t, 1, exitCode)
|
||||
}
|
||||
|
||||
func skipNewFormat(t *testing.T) {
|
||||
if types.IsFormat_DOLT(types.Format_Default) {
|
||||
t.Skip()
|
||||
}
|
||||
}
|
||||
|
||||
type foreignKeyTest struct {
|
||||
name string
|
||||
setup []testCommand
|
||||
@@ -157,6 +211,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -177,6 +235,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1v2_idx",
|
||||
ReferencedTableColumns: []uint64{6269, 7947},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1", "v2"},
|
||||
ReferencedTableColumns: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -199,6 +261,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk2",
|
||||
@@ -208,6 +274,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v2_idx",
|
||||
ReferencedTableColumns: []uint64{7947},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v2"},
|
||||
ReferencedTableColumns: []string{"v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -230,6 +300,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -253,6 +327,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_Cascade,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk2",
|
||||
@@ -263,6 +341,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableIndex: "v2_idx",
|
||||
ReferencedTableColumns: []uint64{7947},
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_SetNull,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v2"},
|
||||
ReferencedTableColumns: []string{"v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -284,6 +366,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_Cascade,
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_Cascade,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -319,6 +405,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk2",
|
||||
@@ -330,6 +420,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableColumns: []uint64{7947},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_Restrict,
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_Restrict,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v2"},
|
||||
ReferencedTableColumns: []string{"v2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk3",
|
||||
@@ -341,6 +435,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableColumns: []uint64{5237},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_Cascade,
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_Cascade,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v3"},
|
||||
ReferencedTableColumns: []string{"v3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk4",
|
||||
@@ -352,6 +450,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableColumns: []uint64{14774},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_SetNull,
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_SetNull,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v4"},
|
||||
ReferencedTableColumns: []string{"v4"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fk5",
|
||||
@@ -363,6 +465,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableColumns: []uint64{8125},
|
||||
OnUpdate: doltdb.ForeignKeyReferentialAction_NoAction,
|
||||
OnDelete: doltdb.ForeignKeyReferentialAction_NoAction,
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v5"},
|
||||
ReferencedTableColumns: []string{"v5"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -381,6 +487,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -392,13 +502,17 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
},
|
||||
fks: []doltdb.ForeignKey{
|
||||
{
|
||||
Name: "19eof0mu",
|
||||
Name: "1ncba7pr",
|
||||
TableName: "child",
|
||||
TableIndex: "v1_idx",
|
||||
TableColumns: []uint64{1215},
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -413,7 +527,7 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
},
|
||||
fks: []doltdb.ForeignKey{
|
||||
{
|
||||
Name: "mv9a59oo",
|
||||
Name: "7nt5f9b0",
|
||||
TableName: "new_table",
|
||||
// unnamed indexes take the column name
|
||||
TableIndex: "v1",
|
||||
@@ -421,6 +535,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -435,13 +553,17 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
},
|
||||
fks: []doltdb.ForeignKey{
|
||||
{
|
||||
Name: "n4qun7ju",
|
||||
Name: "k48mbatd",
|
||||
TableName: "child",
|
||||
TableIndex: "v1v2_idx",
|
||||
TableColumns: []uint64{1215, 8734},
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1v2_idx",
|
||||
ReferencedTableColumns: []uint64{6269, 7947},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1", "v2"},
|
||||
ReferencedTableColumns: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -457,22 +579,30 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
},
|
||||
fks: []doltdb.ForeignKey{
|
||||
{
|
||||
Name: "19eof0mu",
|
||||
Name: "1ncba7pr",
|
||||
TableName: "child",
|
||||
TableIndex: "v1_idx",
|
||||
TableColumns: []uint64{1215},
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "p79c8qtq",
|
||||
Name: "8geddp18",
|
||||
TableName: "child",
|
||||
TableIndex: "v2_idx",
|
||||
TableColumns: []uint64{8734},
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v2_idx",
|
||||
ReferencedTableColumns: []uint64{7947},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v2"},
|
||||
ReferencedTableColumns: []string{"v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -499,6 +629,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1_idx",
|
||||
ReferencedTableColumns: []uint64{6269},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1"},
|
||||
ReferencedTableColumns: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -528,6 +662,10 @@ var foreignKeyTests = []foreignKeyTest{
|
||||
ReferencedTableName: "parent",
|
||||
ReferencedTableIndex: "v1v2",
|
||||
ReferencedTableColumns: []uint64{6269, 7947},
|
||||
UnresolvedFKDetails: doltdb.UnresolvedFKDetails{
|
||||
TableColumns: []string{"v1", "v2"},
|
||||
ReferencedTableColumns: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
25
go/libraries/doltcore/env/actions/checkout.go
vendored
25
go/libraries/doltcore/env/actions/checkout.go
vendored
@@ -383,9 +383,18 @@ func mergeForeignKeyChanges(
|
||||
newFksForTable, _ := newFks.KeysForTable(tblName)
|
||||
changedFksForTable, _ := changedFks.KeysForTable(tblName)
|
||||
|
||||
oldHash := doltdb.CombinedHash(oldFksForTable)
|
||||
newHash := doltdb.CombinedHash(newFksForTable)
|
||||
changedHash := doltdb.CombinedHash(changedFksForTable)
|
||||
oldHash, err := doltdb.CombinedHash(oldFksForTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newHash, err := doltdb.CombinedHash(newFksForTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changedHash, err := doltdb.CombinedHash(changedFksForTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if oldHash == changedHash {
|
||||
fksByTable[tblName] = append(fksByTable[tblName], newFksForTable...)
|
||||
@@ -406,10 +415,16 @@ func mergeForeignKeyChanges(
|
||||
for _, tblName := range tblNames {
|
||||
if _, exists := fksByTable[tblName]; !exists {
|
||||
oldKeys, _ := oldFks.KeysForTable(tblName)
|
||||
oldHash := doltdb.CombinedHash(oldKeys)
|
||||
oldHash, err := doltdb.CombinedHash(oldKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
changedKeys, _ := changedFks.KeysForTable(tblName)
|
||||
changedHash := doltdb.CombinedHash(changedKeys)
|
||||
changedHash, err := doltdb.CombinedHash(changedKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if oldHash == emptyHash {
|
||||
fksByTable[tblName] = append(fksByTable[tblName], changedKeys...)
|
||||
|
||||
@@ -176,7 +176,7 @@ var MergeScripts = []queries.ScriptTest{
|
||||
{
|
||||
Query: "SELECT from_root_ish, violation_type, hex(dolt_row_hash), aColumn, bColumn, CAST(violation_info as CHAR) FROM dolt_constraint_violations_aTable;",
|
||||
Expected: []sql.Row{
|
||||
{doltCommit, "foreign key", "13F8480978D0556FA9AE6DF5745A7ACA", 2, -1, `{"Columns":["bColumn"],"ForeignKey":"ki7k6iea","Index":"bColumn","OnDelete":"RESTRICT","OnUpdate":"RESTRICT","ReferencedColumns":["pk"],"ReferencedIndex":"","ReferencedTable":"parent","Table":"aTable"}`},
|
||||
{doltCommit, "foreign key", "13F8480978D0556FA9AE6DF5745A7ACA", 2, -1, `{"Columns":["bColumn"],"ForeignKey":"ml92huct","Index":"bColumn","OnDelete":"RESTRICT","OnUpdate":"RESTRICT","ReferencedColumns":["pk"],"ReferencedIndex":"","ReferencedTable":"parent","Table":"aTable"}`},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -3474,7 +3474,7 @@ var MergeArtifactsScripts = []queries.ScriptTest{
|
||||
Assertions: []queries.ScriptTestAssertion{
|
||||
{
|
||||
Query: "CALL DOLT_MERGE('right');",
|
||||
ExpectedErrStr: "error storing constraint violation for primary key (( 1 )): another violation already exists\nnew violation: {\"Columns\":[\"col1\"],\"ForeignKey\":\"aoso3tte\",\"Index\":\"col1\",\"OnDelete\":\"RESTRICT\",\"OnUpdate\":\"RESTRICT\",\"ReferencedColumns\":[\"col1\"],\"ReferencedIndex\":\"par_col1_idx\",\"ReferencedTable\":\"parent\",\"Table\":\"child\"} old violation: ({\"Columns\":[\"col2\"],\"ForeignKey\":\"nof6fc49\",\"Index\":\"col2\",\"OnDelete\":\"RESTRICT\",\"OnUpdate\":\"RESTRICT\",\"ReferencedColumns\":[\"col2\"],\"ReferencedIndex\":\"par_col2_idx\",\"ReferencedTable\":\"parent\",\"Table\":\"child\"})",
|
||||
ExpectedErrStr: "error storing constraint violation for primary key (( 1 )): another violation already exists\nnew violation: {\"Columns\":[\"col2\"],\"ForeignKey\":\"r8l98srn\",\"Index\":\"col2\",\"OnDelete\":\"RESTRICT\",\"OnUpdate\":\"RESTRICT\",\"ReferencedColumns\":[\"col2\"],\"ReferencedIndex\":\"par_col2_idx\",\"ReferencedTable\":\"parent\",\"Table\":\"child\"} old violation: ({\"Columns\":[\"col1\"],\"ForeignKey\":\"ut564qa1\",\"Index\":\"col1\",\"OnDelete\":\"RESTRICT\",\"OnUpdate\":\"RESTRICT\",\"ReferencedColumns\":[\"col1\"],\"ReferencedIndex\":\"par_col1_idx\",\"ReferencedTable\":\"parent\",\"Table\":\"child\"})",
|
||||
},
|
||||
{
|
||||
Query: "SELECT * from parent;",
|
||||
|
||||
@@ -1998,7 +1998,7 @@ var DoltConstraintViolationTransactionTests = []queries.TransactionTest{
|
||||
"To allow transactions to be committed with constraint violations from a merge or transaction sequencing set @@dolt_force_transaction_commit=1.\n" +
|
||||
"Constraint violations: \n" +
|
||||
"Type: Foreign Key Constraint Violation\n" +
|
||||
"\tForeignKey: 0050p5ek,\n" +
|
||||
"\tForeignKey: r4cf97vs,\n" +
|
||||
"\tTable: child,\n" +
|
||||
"\tReferencedTable: ,\n" +
|
||||
"\tIndex: parent_fk,\n" +
|
||||
@@ -2006,7 +2006,7 @@ var DoltConstraintViolationTransactionTests = []queries.TransactionTest{
|
||||
},
|
||||
{
|
||||
Query: "/* client b */ INSERT INTO child VALUES (1, 1);",
|
||||
ExpectedErrStr: "cannot add or update a child row - Foreign key violation on fk: `0050p5ek`, table: `child`, referenced table: `parent`, key: `[1]`",
|
||||
ExpectedErrStr: "cannot add or update a child row - Foreign key violation on fk: `r4cf97vs`, table: `child`, referenced table: `parent`, key: `[1]`",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -134,17 +134,17 @@ SQL
|
||||
run dolt sql -q "select constraint_name, table_name, column_name, ordinal_position, position_in_unique_constraint, referenced_table_name, referenced_column_name from information_schema.KEY_COLUMN_USAGE;" -r csv
|
||||
[[ "$output" =~ "PRIMARY,colors,id,1,,," ]] || false
|
||||
[[ "$output" =~ "PRIMARY,materials,id,1,,," ]] || false
|
||||
[[ "$output" =~ "jb6i5huc,materials,color,1,1,colors,color" ]] || false
|
||||
[[ "$output" =~ "npjt0g99,materials,color,1,1,colors,color" ]] || false
|
||||
[[ "$output" =~ "PRIMARY,objects,id,1,,," ]] || false
|
||||
[[ "$output" =~ "i5lsjmoo,objects,color,1,1,materials,color" ]] || false
|
||||
[[ "$output" =~ "i5lsjmoo,objects,material,2,2,materials,material" ]] || false
|
||||
[[ "$output" =~ "ootftvit,objects,color,1,1,materials,color" ]] || false
|
||||
[[ "$output" =~ "ootftvit,objects,material,2,2,materials,material" ]] || false
|
||||
[[ "$output" =~ "PRIMARY,child,id,1,,," ]] || false
|
||||
[[ "$output" =~ "PRIMARY,parent,id,1,,," ]] || false
|
||||
|
||||
# check information_schema.TABLE_CONSTRAINTS table
|
||||
run dolt sql -q "select * from information_schema.TABLE_CONSTRAINTS where table_name = 'materials';" -r csv
|
||||
[[ "$output" =~ "def,dolt-repo-$$,PRIMARY,dolt-repo-$$,materials,PRIMARY KEY,YES" ]] || false
|
||||
[[ "$output" =~ "def,dolt-repo-$$,jb6i5huc,dolt-repo-$$,materials,FOREIGN KEY,YES" ]] || false
|
||||
[[ "$output" =~ "def,dolt-repo-$$,npjt0g99,dolt-repo-$$,materials,FOREIGN KEY,YES" ]] || false
|
||||
|
||||
# check information_schema.TABLE_CONSTRAINTS_EXTENSIONS table
|
||||
run dolt sql -q "select constraint_name from information_schema.TABLE_CONSTRAINTS_EXTENSIONS where table_name = 'materials';" -r csv
|
||||
|
||||
Reference in New Issue
Block a user