Ensure indexes are updated properly when deleting records

This commit is contained in:
Tobie Morgan Hitchcock 2020-12-09 23:49:21 +00:00
parent d2ad045d4d
commit aa623a3985
2 changed files with 128 additions and 6 deletions

View file

@ -1147,6 +1147,47 @@ func TestDefine(t *testing.T) {
}) })
Convey("Define a single-field unique index on a table, and ensure it prevents duplicate record values, after deleting records", t, func() {
setupDB(workerCount)
txt := `
USE NS test DB test;
DEFINE INDEX test ON person COLUMNS email UNIQUE;
UPDATE person:one SET account="one", email="info@demo.com";
UPDATE person:one SET account="demo", email="info@demo.com";
UPDATE person:one SET account="demo", email="test@demo.com";
UPDATE person:two SET account="demo", email="info@demo.com";
DELETE person:one;
UPDATE person:tre SET account="demo", email="info@demo.com";
UPDATE person:tre SET account="demo", email="test@demo.com";
SELECT * FROM person ORDER BY meta.id;
`
res, err := Execute(permsKV(), txt, nil)
So(err, ShouldBeNil)
So(res, ShouldHaveLength, 10)
So(res[1].Status, ShouldEqual, "OK")
So(res[2].Result, ShouldHaveLength, 1)
So(res[2].Status, ShouldEqual, "OK")
So(res[3].Result, ShouldHaveLength, 1)
So(res[3].Status, ShouldEqual, "OK")
So(res[4].Result, ShouldHaveLength, 1)
So(res[4].Status, ShouldEqual, "OK")
So(res[5].Result, ShouldHaveLength, 1)
So(res[5].Status, ShouldEqual, "OK")
So(res[6].Result, ShouldHaveLength, 0)
So(res[6].Status, ShouldEqual, "OK")
So(res[7].Result, ShouldHaveLength, 0)
So(res[7].Status, ShouldEqual, "ERR_IX")
So(res[8].Result, ShouldHaveLength, 1)
So(res[8].Status, ShouldEqual, "OK")
So(res[9].Result, ShouldHaveLength, 2)
So(data.Consume(res[9].Result[0]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "tre"})
So(data.Consume(res[9].Result[1]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "two"})
})
Convey("Define a multiple-field unique index on a table, and ensure it prevents duplicate record values", t, func() { Convey("Define a multiple-field unique index on a table, and ensure it prevents duplicate record values", t, func() {
setupDB(workerCount) setupDB(workerCount)
@ -1183,6 +1224,85 @@ func TestDefine(t *testing.T) {
}) })
Convey("Define a multiple-field unique index on a table, and ensure it prevents duplicate record values, after updating records", t, func() {
setupDB(workerCount)
txt := `
USE NS test DB test;
DEFINE INDEX test ON person COLUMNS account, email UNIQUE;
UPDATE person:one SET account="one", email="info@demo.com";
UPDATE person:one SET account="demo", email="info@demo.com";
UPDATE person:one SET account="demo", email="test@demo.com";
UPDATE person:two SET account="demo", email="info@demo.com";
UPDATE person:tre SET account="demo", email="info@demo.com";
UPDATE person:tre SET account="demo", email="test@demo.com";
SELECT * FROM person ORDER BY meta.id;
`
res, err := Execute(permsKV(), txt, nil)
So(err, ShouldBeNil)
So(res, ShouldHaveLength, 9)
So(res[1].Status, ShouldEqual, "OK")
So(res[2].Result, ShouldHaveLength, 1)
So(res[2].Status, ShouldEqual, "OK")
So(res[3].Result, ShouldHaveLength, 1)
So(res[3].Status, ShouldEqual, "OK")
So(res[4].Result, ShouldHaveLength, 1)
So(res[4].Status, ShouldEqual, "OK")
So(res[5].Result, ShouldHaveLength, 1)
So(res[5].Status, ShouldEqual, "OK")
So(res[6].Result, ShouldHaveLength, 0)
So(res[6].Status, ShouldEqual, "ERR_IX")
So(res[7].Result, ShouldHaveLength, 0)
So(res[7].Status, ShouldEqual, "ERR_IX")
So(res[8].Result, ShouldHaveLength, 2)
So(data.Consume(res[8].Result[0]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "one"})
So(data.Consume(res[8].Result[1]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "two"})
})
Convey("Define a multiple-field unique index on a table, and ensure it prevents duplicate record values, after deleting records", t, func() {
setupDB(workerCount)
txt := `
USE NS test DB test;
DEFINE INDEX test ON person COLUMNS account, email UNIQUE;
UPDATE person:one SET account="one", email="info@demo.com";
UPDATE person:one SET account="demo", email="info@demo.com";
UPDATE person:one SET account="demo", email="test@demo.com";
UPDATE person:two SET account="demo", email="info@demo.com";
DELETE person:one;
UPDATE person:tre SET account="demo", email="info@demo.com";
UPDATE person:tre SET account="demo", email="test@demo.com";
SELECT * FROM person ORDER BY meta.id;
`
res, err := Execute(permsKV(), txt, nil)
So(err, ShouldBeNil)
So(res, ShouldHaveLength, 10)
So(res[1].Status, ShouldEqual, "OK")
So(res[2].Result, ShouldHaveLength, 1)
So(res[2].Status, ShouldEqual, "OK")
So(res[3].Result, ShouldHaveLength, 1)
So(res[3].Status, ShouldEqual, "OK")
So(res[4].Result, ShouldHaveLength, 1)
So(res[4].Status, ShouldEqual, "OK")
So(res[5].Result, ShouldHaveLength, 1)
So(res[5].Status, ShouldEqual, "OK")
So(res[6].Result, ShouldHaveLength, 0)
So(res[6].Status, ShouldEqual, "OK")
So(res[7].Result, ShouldHaveLength, 0)
So(res[7].Status, ShouldEqual, "ERR_IX")
So(res[8].Result, ShouldHaveLength, 1)
So(res[8].Status, ShouldEqual, "OK")
So(res[9].Result, ShouldHaveLength, 2)
So(data.Consume(res[9].Result[0]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "tre"})
So(data.Consume(res[9].Result[1]).Get("id").Data(), ShouldResemble, &sql.Thing{"person", "two"})
})
Convey("Define a multiple-field foreign record unique index on a table, and ensure it prevents duplicate record values", t, func() { Convey("Define a multiple-field foreign record unique index on a table, and ensure it prevents duplicate record values", t, func() {
setupDB(workerCount) setupDB(workerCount)

View file

@ -422,16 +422,18 @@ func (d *document) purgeIndex(ctx context.Context) (err error) {
del := indx.Build(ix.Cols, d.initial) del := indx.Build(ix.Cols, d.initial)
if ix.Uniq == true { if ix.Uniq == true {
for _, v := range del { for _, f := range del {
key := &keys.Index{KV: d.key.KV, NS: d.key.NS, DB: d.key.DB, TB: d.key.TB, IX: ix.Name.VA, FD: v} enfd := data.Consume(f).Encode()
d.i.e.tx.DelC(ctx, 0, key.Encode(), d.id.Bytes()) didx := &keys.Index{KV: d.key.KV, NS: d.key.NS, DB: d.key.DB, TB: d.key.TB, IX: ix.Name.VA, FD: enfd}
d.i.e.tx.DelC(ctx, 0, didx.Encode(), d.id.Bytes())
} }
} }
if ix.Uniq == false { if ix.Uniq == false {
for _, v := range del { for _, f := range del {
key := &keys.Point{KV: d.key.KV, NS: d.key.NS, DB: d.key.DB, TB: d.key.TB, IX: ix.Name.VA, FD: v, ID: d.key.ID} enfd := data.Consume(f).Encode()
d.i.e.tx.DelC(ctx, 0, key.Encode(), d.id.Bytes()) aidx := &keys.Point{KV: d.key.KV, NS: d.key.NS, DB: d.key.DB, TB: d.key.TB, IX: ix.Name.VA, FD: enfd, ID: d.key.ID}
d.i.e.tx.DelC(ctx, 0, aidx.Encode(), d.id.Bytes())
} }
} }