Add support for table versioning

This commit is contained in:
Tobie Morgan Hitchcock 2018-08-20 07:51:02 +01:00
parent de925ae16e
commit 8b0674c66d
5 changed files with 92 additions and 46 deletions

View file

@ -341,6 +341,21 @@ func (d *document) shouldDrop(ctx context.Context) (bool, error) {
} }
func (d *document) shouldVersn(ctx context.Context) (bool, error) {
// Check whether it is specified
// that the table should drop
// writes, and if so, then return.
tb, err := d.getTB(ctx)
if err != nil {
return false, err
}
return tb.Vers, err
}
func (d *document) storeThing(ctx context.Context) (err error) { func (d *document) storeThing(ctx context.Context) (err error) {
defer d.ulock(ctx) defer d.ulock(ctx)
@ -362,7 +377,13 @@ func (d *document) storeThing(ctx context.Context) (err error) {
// Write the value to the data // Write the value to the data
// layer and return any errors. // layer and return any errors.
if ok, err := d.shouldVersn(ctx); err != nil {
return err
} else if ok == true {
_, err = d.i.e.dbo.Put(ctx, d.i.e.time, d.key.Encode(), d.current.Encode()) _, err = d.i.e.dbo.Put(ctx, d.i.e.time, d.key.Encode(), d.current.Encode())
} else if ok == false {
_, err = d.i.e.dbo.Put(ctx, 0, d.key.Encode(), d.current.Encode())
}
return return
@ -382,7 +403,13 @@ func (d *document) purgeThing(ctx context.Context) (err error) {
// Reset the item by writing a // Reset the item by writing a
// nil value to the storage. // nil value to the storage.
if ok, err := d.shouldVersn(ctx); err != nil {
return err
} else if ok == true {
_, err = d.i.e.dbo.Put(ctx, d.i.e.time, d.key.Encode(), nil) _, err = d.i.e.dbo.Put(ctx, d.i.e.time, d.key.Encode(), nil)
} else if ok == false {
_, err = d.i.e.dbo.Clr(ctx, d.key.Encode())
}
return return

View file

@ -1923,6 +1923,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
CREATE |person:1..10|; CREATE |person:1..10|;
SELECT * FROM person VERSION "2017-01-01"; SELECT * FROM person VERSION "2017-01-01";
SELECT * FROM person; SELECT * FROM person;
@ -1930,10 +1931,10 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 4) So(res, ShouldHaveLength, 5)
So(res[1].Result, ShouldHaveLength, 10) So(res[2].Result, ShouldHaveLength, 10)
So(res[2].Result, ShouldHaveLength, 0) So(res[3].Result, ShouldHaveLength, 0)
So(res[3].Result, ShouldHaveLength, 10) So(res[4].Result, ShouldHaveLength, 10)
}) })
@ -1943,6 +1944,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
LET date = "2017-01-01"; LET date = "2017-01-01";
CREATE |person:1..10|; CREATE |person:1..10|;
SELECT * FROM person VERSION $date; SELECT * FROM person VERSION $date;
@ -1951,10 +1953,10 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 5) So(res, ShouldHaveLength, 6)
So(res[2].Result, ShouldHaveLength, 10) So(res[3].Result, ShouldHaveLength, 10)
So(res[3].Result, ShouldHaveLength, 0) So(res[4].Result, ShouldHaveLength, 0)
So(res[4].Result, ShouldHaveLength, 10) So(res[5].Result, ShouldHaveLength, 10)
}) })
@ -1964,6 +1966,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
LET time = "2017-01-01T15:04:05+07:00"; LET time = "2017-01-01T15:04:05+07:00";
CREATE |person:1..10|; CREATE |person:1..10|;
SELECT * FROM person VERSION $time; SELECT * FROM person VERSION $time;
@ -1972,10 +1975,10 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 5) So(res, ShouldHaveLength, 6)
So(res[2].Result, ShouldHaveLength, 10) So(res[3].Result, ShouldHaveLength, 10)
So(res[3].Result, ShouldHaveLength, 0) So(res[4].Result, ShouldHaveLength, 0)
So(res[4].Result, ShouldHaveLength, 10) So(res[5].Result, ShouldHaveLength, 10)
}) })
@ -1985,6 +1988,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
LET time = "test"; LET time = "test";
CREATE |person:1..10|; CREATE |person:1..10|;
SELECT * FROM person VERSION $time; SELECT * FROM person VERSION $time;
@ -1993,12 +1997,12 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 5) So(res, ShouldHaveLength, 6)
So(res[2].Result, ShouldHaveLength, 10) So(res[3].Result, ShouldHaveLength, 10)
So(res[3].Result, ShouldHaveLength, 0) So(res[4].Result, ShouldHaveLength, 0)
So(res[3].Status, ShouldEqual, "ERR") So(res[4].Status, ShouldEqual, "ERR")
So(res[3].Detail, ShouldEqual, "Found 'test' but VERSION expression must be a date or time") So(res[4].Detail, ShouldEqual, "Found 'test' but VERSION expression must be a date or time")
So(res[4].Result, ShouldHaveLength, 10) So(res[5].Result, ShouldHaveLength, 10)
}) })
@ -2008,6 +2012,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
LET old = time.now(); LET old = time.now();
CREATE person:test; CREATE person:test;
UPDATE person:test SET test = 1; UPDATE person:test SET test = 1;
@ -2025,19 +2030,19 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 14) So(res, ShouldHaveLength, 15)
So(res[3].Result, ShouldHaveLength, 1) So(res[4].Result, ShouldHaveLength, 1)
So(res[5].Result, ShouldHaveLength, 1) So(res[6].Result, ShouldHaveLength, 1)
So(res[7].Result, ShouldHaveLength, 1) So(res[8].Result, ShouldHaveLength, 1)
So(res[9].Result, ShouldHaveLength, 0) So(res[10].Result, ShouldHaveLength, 0)
So(res[10].Result, ShouldHaveLength, 1)
So(data.Consume(res[10].Result[0]).Get("test").Data(), ShouldEqual, 1)
So(res[11].Result, ShouldHaveLength, 1) So(res[11].Result, ShouldHaveLength, 1)
So(data.Consume(res[11].Result[0]).Get("test").Data(), ShouldEqual, 2) So(data.Consume(res[11].Result[0]).Get("test").Data(), ShouldEqual, 1)
So(res[12].Result, ShouldHaveLength, 1) So(res[12].Result, ShouldHaveLength, 1)
So(data.Consume(res[12].Result[0]).Get("test").Data(), ShouldEqual, 3) So(data.Consume(res[12].Result[0]).Get("test").Data(), ShouldEqual, 2)
So(res[13].Result, ShouldHaveLength, 1) So(res[13].Result, ShouldHaveLength, 1)
So(data.Consume(res[13].Result[0]).Get("test").Data(), ShouldEqual, 3) So(data.Consume(res[13].Result[0]).Get("test").Data(), ShouldEqual, 3)
So(res[14].Result, ShouldHaveLength, 1)
So(data.Consume(res[14].Result[0]).Get("test").Data(), ShouldEqual, 3)
}) })
@ -2047,6 +2052,7 @@ func TestSelect(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE TABLE person VERSIONED;
LET old = time.now(); LET old = time.now();
CREATE |person:1..3|; CREATE |person:1..3|;
UPDATE person:1, person:2, person:3 SET test = 1; UPDATE person:1, person:2, person:3 SET test = 1;
@ -2064,27 +2070,27 @@ func TestSelect(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 14) So(res, ShouldHaveLength, 15)
So(res[3].Result, ShouldHaveLength, 3) So(res[4].Result, ShouldHaveLength, 3)
So(res[5].Result, ShouldHaveLength, 3) So(res[6].Result, ShouldHaveLength, 3)
So(res[7].Result, ShouldHaveLength, 3) So(res[8].Result, ShouldHaveLength, 3)
So(res[9].Result, ShouldHaveLength, 0) So(res[10].Result, ShouldHaveLength, 0)
So(res[10].Result, ShouldHaveLength, 3)
So(data.Consume(res[10].Result).Get("0.test").Data(), ShouldEqual, 1)
So(data.Consume(res[10].Result).Get("1.test").Data(), ShouldEqual, 1)
So(data.Consume(res[10].Result).Get("2.test").Data(), ShouldEqual, 1)
So(res[11].Result, ShouldHaveLength, 3) So(res[11].Result, ShouldHaveLength, 3)
So(data.Consume(res[11].Result).Get("0.test").Data(), ShouldEqual, 2) So(data.Consume(res[11].Result).Get("0.test").Data(), ShouldEqual, 1)
So(data.Consume(res[11].Result).Get("1.test").Data(), ShouldEqual, 2) So(data.Consume(res[11].Result).Get("1.test").Data(), ShouldEqual, 1)
So(data.Consume(res[11].Result).Get("2.test").Data(), ShouldEqual, 2) So(data.Consume(res[11].Result).Get("2.test").Data(), ShouldEqual, 1)
So(res[12].Result, ShouldHaveLength, 3) So(res[12].Result, ShouldHaveLength, 3)
So(data.Consume(res[12].Result).Get("0.test").Data(), ShouldEqual, 3) So(data.Consume(res[12].Result).Get("0.test").Data(), ShouldEqual, 2)
So(data.Consume(res[12].Result).Get("1.test").Data(), ShouldEqual, 3) So(data.Consume(res[12].Result).Get("1.test").Data(), ShouldEqual, 2)
So(data.Consume(res[12].Result).Get("2.test").Data(), ShouldEqual, 3) So(data.Consume(res[12].Result).Get("2.test").Data(), ShouldEqual, 2)
So(res[13].Result, ShouldHaveLength, 3) So(res[13].Result, ShouldHaveLength, 3)
So(data.Consume(res[13].Result).Get("0.test").Data(), ShouldEqual, 3) So(data.Consume(res[13].Result).Get("0.test").Data(), ShouldEqual, 3)
So(data.Consume(res[13].Result).Get("1.test").Data(), ShouldEqual, 3) So(data.Consume(res[13].Result).Get("1.test").Data(), ShouldEqual, 3)
So(data.Consume(res[13].Result).Get("2.test").Data(), ShouldEqual, 3) So(data.Consume(res[13].Result).Get("2.test").Data(), ShouldEqual, 3)
So(res[14].Result, ShouldHaveLength, 3)
So(data.Consume(res[14].Result).Get("0.test").Data(), ShouldEqual, 3)
So(data.Consume(res[14].Result).Get("1.test").Data(), ShouldEqual, 3)
So(data.Consume(res[14].Result).Get("2.test").Data(), ShouldEqual, 3)
}) })

View file

@ -361,9 +361,10 @@ func (this RemoveScopeStatement) String() string {
func (this DefineTableStatement) String() (s string) { func (this DefineTableStatement) String() (s string) {
w := maybe(this.Cond != nil, print(" WHERE %v", this.Cond)) w := maybe(this.Cond != nil, print(" WHERE %v", this.Cond))
return print("DEFINE TABLE %v%v%v%v%v", return print("DEFINE TABLE %v%v%v%v%v%v",
maybe(this.Name != nil, print("%s", this.Name), print("%s", this.What)), maybe(this.Name != nil, print("%s", this.Name), print("%s", this.What)),
maybe(this.Full, " SCHEMAFULL"), maybe(this.Full, " SCHEMAFULL"),
maybe(this.Vers, " VERSIONED"),
maybe(this.Drop, " DROP"), maybe(this.Drop, " DROP"),
maybe(this.Lock, print(" AS SELECT %v FROM %v%v%v", this.Expr, this.From, w, this.Group)), maybe(this.Lock, print(" AS SELECT %v FROM %v%v%v", this.Expr, this.From, w, this.Group)),
maybe(this.Perms != nil, this.Perms), maybe(this.Perms != nil, this.Perms),

View file

@ -28,7 +28,7 @@ func (p *parser) parseDefineTableStatement() (stmt *DefineTableStatement, err er
for { for {
tok, _, exi := p.mightBe(DROP, SCHEMAFULL, SCHEMALESS, PERMISSIONS, AS) tok, _, exi := p.mightBe(DROP, SCHEMAFULL, SCHEMALESS, VERSIONED, UNVERSIONED, PERMISSIONS, AS)
if !exi { if !exi {
break break
} }
@ -45,6 +45,14 @@ func (p *parser) parseDefineTableStatement() (stmt *DefineTableStatement, err er
stmt.Full = false stmt.Full = false
} }
if is(tok, VERSIONED) {
stmt.Vers = true
}
if is(tok, UNVERSIONED) {
stmt.Vers = false
}
if is(tok, PERMISSIONS) { if is(tok, PERMISSIONS) {
if stmt.Perms, err = p.parsePerms(); err != nil { if stmt.Perms, err = p.parsePerms(); err != nil {
return nil, err return nil, err

View file

@ -191,11 +191,13 @@ const (
TRUE TRUE
TYPE TYPE
UNIQUE UNIQUE
UNVERSIONED
UPDATE UPDATE
UPSERT UPSERT
USE USE
VALUE VALUE
VERSION VERSION
VERSIONED
VOID VOID
WHEN WHEN
WHERE WHERE
@ -364,11 +366,13 @@ var tokens = [...]string{
TRUE: "TRUE", TRUE: "TRUE",
TYPE: "TYPE", TYPE: "TYPE",
UNIQUE: "UNIQUE", UNIQUE: "UNIQUE",
UNVERSIONED: "UNVERSIONED",
UPDATE: "UPDATE", UPDATE: "UPDATE",
UPSERT: "UPSERT", UPSERT: "UPSERT",
USE: "USE", USE: "USE",
VALUE: "VALUE", VALUE: "VALUE",
VERSION: "VERSION", VERSION: "VERSION",
VERSIONED: "VERSIONED",
VOID: "VOID", VOID: "VOID",
WHEN: "WHEN", WHEN: "WHEN",
WHERE: "WHERE", WHERE: "WHERE",