Use XIDs instead of UUIDs for record IDs

This commit is contained in:
Tobie Morgan Hitchcock 2017-11-26 16:54:49 +00:00
parent 1ac78aa950
commit 0762ee25b2
14 changed files with 150 additions and 43 deletions

View file

@ -21,8 +21,8 @@ import (
"github.com/abcum/surreal/sql" "github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/data" "github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/guid"
"github.com/abcum/surreal/util/keys" "github.com/abcum/surreal/util/keys"
"github.com/abcum/surreal/util/uuid"
) )
func (e *executor) executeCreate(ctx context.Context, stm *sql.CreateStatement) ([]interface{}, error) { func (e *executor) executeCreate(ctx context.Context, stm *sql.CreateStatement) ([]interface{}, error) {
@ -47,11 +47,11 @@ func (e *executor) executeCreate(ctx context.Context, stm *sql.CreateStatement)
return nil, fmt.Errorf("Can not execute CREATE query using value '%v'", what) return nil, fmt.Errorf("Can not execute CREATE query using value '%v'", what)
case *sql.Table: case *sql.Table:
key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: uuid.NewV4().String()} key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: guid.New().String()}
i.processThing(ctx, key) i.processThing(ctx, key)
case *sql.Ident: case *sql.Ident:
key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, ID: uuid.NewV4().String()} key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, ID: guid.New().String()}
i.processThing(ctx, key) i.processThing(ctx, key)
case *sql.Thing: case *sql.Thing:

View file

@ -82,7 +82,7 @@ func TestCreate(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 2) So(res, ShouldHaveLength, 2)
So(res[1].Result, ShouldHaveLength, 1) So(res[1].Result, ShouldHaveLength, 1)
So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(data.Consume(res[1].Result[0]).Get("meta.tb").Data(), ShouldEqual, "person") So(data.Consume(res[1].Result[0]).Get("meta.tb").Data(), ShouldEqual, "person")
}) })
@ -136,8 +136,8 @@ func TestCreate(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 2) So(res, ShouldHaveLength, 2)
So(res[1].Result, ShouldHaveLength, 100) So(res[1].Result, ShouldHaveLength, 100)
So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(data.Consume(res[1].Result[99]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[99]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })

View file

@ -170,10 +170,10 @@ func TestInsert(t *testing.T) {
So(res, ShouldHaveLength, 4) So(res, ShouldHaveLength, 4)
So(res[2].Result, ShouldHaveLength, 1) So(res[2].Result, ShouldHaveLength, 1)
So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(res[3].Result, ShouldHaveLength, 1) So(res[3].Result, ShouldHaveLength, 1)
So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })
@ -232,10 +232,10 @@ func TestInsert(t *testing.T) {
So(res, ShouldHaveLength, 4) So(res, ShouldHaveLength, 4)
So(res[2].Result, ShouldHaveLength, 1) So(res[2].Result, ShouldHaveLength, 1)
So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(res[3].Result, ShouldHaveLength, 1) So(res[3].Result, ShouldHaveLength, 1)
So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })

View file

@ -28,11 +28,11 @@ import (
"github.com/abcum/surreal/util/comp" "github.com/abcum/surreal/util/comp"
"github.com/abcum/surreal/util/data" "github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/fncs" "github.com/abcum/surreal/util/fncs"
"github.com/abcum/surreal/util/guid"
"github.com/abcum/surreal/util/ints" "github.com/abcum/surreal/util/ints"
"github.com/abcum/surreal/util/keys" "github.com/abcum/surreal/util/keys"
"github.com/abcum/surreal/util/nums" "github.com/abcum/surreal/util/nums"
"github.com/abcum/surreal/util/rand" "github.com/abcum/surreal/util/rand"
"github.com/abcum/surreal/util/uuid"
) )
type iterator struct { type iterator struct {
@ -650,7 +650,7 @@ func (i *iterator) processModel(ctx context.Context, key *keys.Thing, qry *sql.M
if i.checkState(ctx) { if i.checkState(ctx) {
key := key.Copy() key := key.Copy()
key.ID = uuid.NewV4().String() key.ID = guid.New().String()
i.submitTask(key, nil, nil) i.submitTask(key, nil, nil)
continue continue
} }
@ -805,7 +805,7 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte
if i.checkState(ctx) { if i.checkState(ctx) {
key := key.Copy() key := key.Copy()
key.ID = uuid.NewV4().String() key.ID = guid.New().String()
i.submitTask(key, nil, data.Consume(val)) i.submitTask(key, nil, data.Consume(val))
continue continue
} }

View file

@ -21,8 +21,8 @@ import (
"github.com/abcum/surreal/sql" "github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/data" "github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/guid"
"github.com/abcum/surreal/util/keys" "github.com/abcum/surreal/util/keys"
"github.com/abcum/surreal/util/uuid"
) )
func (e *executor) executeRelate(ctx context.Context, stm *sql.RelateStatement) ([]interface{}, error) { func (e *executor) executeRelate(ctx context.Context, stm *sql.RelateStatement) ([]interface{}, error) {
@ -53,11 +53,11 @@ func (e *executor) executeRelate(ctx context.Context, stm *sql.RelateStatement)
return nil, fmt.Errorf("Can not execute RELATE query using value '%v'", what) return nil, fmt.Errorf("Can not execute RELATE query using value '%v'", what)
case *sql.Table: case *sql.Table:
key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: uuid.NewV4().String()} key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: guid.New().String()}
i.processThing(ctx, key) i.processThing(ctx, key)
case *sql.Ident: case *sql.Ident:
key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, ID: uuid.NewV4().String()} key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, ID: guid.New().String()}
i.processThing(ctx, key) i.processThing(ctx, key)
} }

View file

@ -86,7 +86,7 @@ func TestSelect(t *testing.T) {
So(res, ShouldHaveLength, 3) So(res, ShouldHaveLength, 3)
So(res[1].Result, ShouldHaveLength, 1) So(res[1].Result, ShouldHaveLength, 1)
So(res[2].Result, ShouldHaveLength, 1) So(res[2].Result, ShouldHaveLength, 1)
So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(data.Consume(res[1].Result[0]).Get("meta.tb").Data(), ShouldEqual, "person") So(data.Consume(res[1].Result[0]).Get("meta.tb").Data(), ShouldEqual, "person")
}) })

View file

@ -134,8 +134,8 @@ func TestUpdate(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 2) So(res, ShouldHaveLength, 2)
So(res[1].Result, ShouldHaveLength, 100) So(res[1].Result, ShouldHaveLength, 100)
So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(data.Consume(res[1].Result[99]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[1].Result[99]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })

View file

@ -171,10 +171,10 @@ func TestUpsert(t *testing.T) {
So(res, ShouldHaveLength, 4) So(res, ShouldHaveLength, 4)
So(res[2].Result, ShouldHaveLength, 1) So(res[2].Result, ShouldHaveLength, 1)
So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(res[3].Result, ShouldHaveLength, 1) So(res[3].Result, ShouldHaveLength, 1)
So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })
@ -239,10 +239,10 @@ func TestUpsert(t *testing.T) {
So(res, ShouldHaveLength, 4) So(res, ShouldHaveLength, 4)
So(res[2].Result, ShouldHaveLength, 1) So(res[2].Result, ShouldHaveLength, 1)
So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[2].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[2].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
So(res[3].Result, ShouldHaveLength, 1) So(res[3].Result, ShouldHaveLength, 1)
So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom") So(data.Consume(res[3].Result[0]).Get("login").Data(), ShouldEqual, "tom")
So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 36) So(data.Consume(res[3].Result[0]).Get("meta.id").Data(), ShouldHaveLength, 20)
}) })

6
glide.lock generated
View file

@ -1,5 +1,5 @@
hash: 38028d7190e274aa6aa1346ce217556592f8c27eade989507685da3959323eaf hash: 2cdf97833582dc0d969ea9de15f67a99cf9fc5f4689f13a246b1e26a774faf7d
updated: 2017-11-23T13:36:00.529593Z updated: 2017-11-26T16:33:32.201745Z
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: 2d3a6656c17a60b0815b7e06ab0be04eacb6e613 version: 2d3a6656c17a60b0815b7e06ab0be04eacb6e613
@ -155,6 +155,8 @@ imports:
- internal/utilization - internal/utilization
- name: github.com/pkg/profile - name: github.com/pkg/profile
version: 5b67d428864e92711fcbd2f8629456121a56d91f version: 5b67d428864e92711fcbd2f8629456121a56d91f
- name: github.com/rs/xid
version: 02dd45c33376f85d1064355dc790dcc4850596b1
- name: github.com/satori/go.uuid - name: github.com/satori/go.uuid
version: 879c5887cd475cd7864858769793b2ceb0d44feb version: 879c5887cd475cd7864858769793b2ceb0d44feb
- name: github.com/sean-/seed - name: github.com/sean-/seed

View file

@ -61,6 +61,8 @@ import:
- package: google.golang.org/genproto - package: google.golang.org/genproto
subpackages: subpackages:
- googleapis/api/monitoredres - googleapis/api/monitoredres
- package: github.com/rs/xid
version: ^1.1.0
testImport: testImport:
- package: github.com/smartystreets/goconvey - package: github.com/smartystreets/goconvey
version: ^1.6.3 version: ^1.6.3

36
util/guid/guid.go Normal file
View file

@ -0,0 +1,36 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package guid
import (
"github.com/rs/xid"
)
type GUID struct {
xid.ID
}
// NewV1 returns a new GUID.
func New() *GUID {
return &GUID{xid.New()}
}
func Parse(input string) *GUID {
id, err := xid.FromString(input)
if err != nil {
return nil
}
return &GUID{id}
}

72
util/guid/guid_test.go Normal file
View file

@ -0,0 +1,72 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package guid
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestNew(t *testing.T) {
var str *GUID
str = New()
Convey(str.String(), t, func() {
Convey("Should be a GUID", func() {
So(str, ShouldHaveSameTypeAs, &GUID{})
})
Convey("Should not be nil", func() {
So(str, ShouldNotBeNil)
})
Convey("Should be of length 20", func() {
So(str.String(), ShouldHaveLength, 20)
})
})
}
func TestParsing(t *testing.T) {
var str *GUID
str = Parse("thiswillnotbeok5n4g")
Convey("Parse thiswillnotbeok5n4g", t, func() {
Convey("Should be nil", func() {
So(str, ShouldBeNil)
})
})
str = Parse("9m4e2mr0ui3e8a215n4g")
Convey("Parse 9m4e2mr0ui3e8a215n4g", t, func() {
Convey("Should be a GUID", func() {
So(str, ShouldHaveSameTypeAs, &GUID{})
})
Convey("Should not be nil", func() {
So(str, ShouldNotBeNil)
})
Convey("Should be of length 20", func() {
So(str.String(), ShouldHaveLength, 20)
})
Convey("Should be exactly `9m4e2mr0ui3e8a215n4g`", func() {
So(str.String(), ShouldEqual, "9m4e2mr0ui3e8a215n4g")
})
})
}

View file

@ -54,7 +54,11 @@ func NewV5(ns uuid.UUID, name string) *UUID {
return &UUID{uuid.NewV5(ns, name)} return &UUID{uuid.NewV5(ns, name)}
} }
// GetUUID parses and checks for a valid UUID string, and returns Nil if not valid. // Parse parses and checks for a valid UUID string, and returns nil if not valid.
func GetUUID(input string) *UUID { func Parse(input string) *UUID {
return &UUID{uuid.FromStringOrNil(input)} id, err := uuid.FromString(input)
if err != nil {
return nil
}
return &UUID{id}
} }

View file

@ -173,26 +173,17 @@ func TestParsing(t *testing.T) {
var str *UUID var str *UUID
str = GetUUID("thiswill-notbe-parsed-as-successful") str = Parse("thiswill-notbe-parsed-as-successful")
Convey(str.String(), t, func() { Convey("Parse thiswill-notbe-parsed-as-successful", t, func() {
Convey("Should be a UUID", func() { Convey("Should be nil", func() {
So(str, ShouldHaveSameTypeAs, &UUID{}) So(str, ShouldBeNil)
})
Convey("Should not be nil", func() {
So(str, ShouldNotBeNil)
})
Convey("Should be of length 36", func() {
So(str.String(), ShouldHaveLength, 36)
})
Convey("Should be exactly `00000000-0000-0000-0000-000000000000`", func() {
So(str.String(), ShouldEqual, "00000000-0000-0000-0000-000000000000")
}) })
}) })
str = GetUUID("1400A118-2749-4605-833C-E7437488BCBF") str = Parse("1400A118-2749-4605-833C-E7437488BCBF")
Convey(str.String(), t, func() { Convey("Parse 1400A118-2749-4605-833C-E7437488BCBF", t, func() {
Convey("Should be a UUID", func() { Convey("Should be a UUID", func() {
So(str, ShouldHaveSameTypeAs, &UUID{}) So(str, ShouldHaveSameTypeAs, &UUID{})
}) })