From 492cdbe26b2f2f415a37912f291e552af7484eaa Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Thu, 14 Jul 2022 13:20:33 +0800 Subject: [PATCH] Add easy to use error functions --- cmd/genji/shell/command.go | 6 ++-- db.go | 4 +-- db_test.go | 5 ++- errors.go | 36 +++++++++++++++++++ go.mod | 18 +++++----- go.sum | 29 ++++++--------- internal/database/catalog.go | 8 ++--- internal/database/catalog_test.go | 18 +++++----- internal/database/constraint.go | 10 ++---- internal/database/sequence.go | 2 +- internal/database/table.go | 8 ++--- internal/database/table_test.go | 8 ++--- {errors => internal/errors}/errors.go | 49 +++++++++++++++----------- internal/query/statement/alter.go | 2 +- internal/query/statement/alter_test.go | 5 ++- internal/query/statement/create.go | 2 +- internal/query/statement/drop.go | 2 +- internal/query/statement/drop_test.go | 4 +-- internal/query/statement/reindex.go | 2 +- internal/testutil/assert/errors.go | 2 +- 20 files changed, 125 insertions(+), 95 deletions(-) create mode 100644 errors.go rename {errors => internal/errors}/errors.go (51%) diff --git a/cmd/genji/shell/command.go b/cmd/genji/shell/command.go index bcc6a35ae..288d79145 100644 --- a/cmd/genji/shell/command.go +++ b/cmd/genji/shell/command.go @@ -15,7 +15,7 @@ import ( "github.com/genjidb/genji/cmd/genji/dbutil" "github.com/genjidb/genji/cmd/genji/doc" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/types" ) @@ -151,8 +151,8 @@ func runIndexesCmd(db *genji.DB, tableName string, w io.Writer) error { if tableName != "" { _, err := db.QueryDocument("SELECT 1 FROM __genji_catalog WHERE name = ? AND type = 'table' LIMIT 1", tableName) if err != nil { - if errors.Is(err, errs.ErrDocumentNotFound) { - return fmt.Errorf("%w: %q", errs.NotFoundError{Name: tableName}, tableName) + if errs.IsNotFoundError(err) { + return errors.Wrapf(err, "table %s does not exist", tableName) } return err } diff --git a/db.go b/db.go index 7bb64ec92..1a030ed12 100644 --- a/db.go +++ b/db.go @@ -12,11 +12,11 @@ import ( "github.com/cockroachdb/pebble" "github.com/cockroachdb/pebble/vfs" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" "github.com/genjidb/genji/internal/database/catalogstore" ipebble "github.com/genjidb/genji/internal/database/pebble" "github.com/genjidb/genji/internal/environment" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/query" "github.com/genjidb/genji/internal/query/statement" "github.com/genjidb/genji/internal/sql/parser" @@ -329,7 +329,7 @@ func scanDocument(iter document.Iterator) (types.Document, error) { } if d == nil { - return nil, errors.WithStack(errs.ErrDocumentNotFound) + return nil, errors.WithStack(errs.NewDocumentNotFoundError()) } fb := document.NewFieldBuffer() diff --git a/db_test.go b/db_test.go index 33532cdb4..0ad7951d8 100644 --- a/db_test.go +++ b/db_test.go @@ -11,7 +11,6 @@ import ( "github.com/genjidb/genji" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/testutil" "github.com/genjidb/genji/internal/testutil/assert" "github.com/genjidb/genji/types" @@ -184,14 +183,14 @@ func TestQueryDocument(t *testing.T) { t.Run("Should return an error if no document", func(t *testing.T) { r, err := db.QueryDocument("SELECT * FROM test WHERE a > 100") - assert.ErrorIs(t, err, errs.ErrDocumentNotFound) + require.True(t, genji.IsNotFoundError(err)) require.Nil(t, r) tx, err := db.Begin(false) assert.NoError(t, err) defer tx.Rollback() r, err = tx.QueryDocument("SELECT * FROM test WHERE a > 100") - assert.ErrorIs(t, err, errs.ErrDocumentNotFound) + require.True(t, genji.IsNotFoundError(err)) require.Nil(t, r) }) } diff --git a/errors.go b/errors.go new file mode 100644 index 000000000..83049042e --- /dev/null +++ b/errors.go @@ -0,0 +1,36 @@ +package genji + +import ( + "github.com/cockroachdb/errors" + "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" +) + +// IsNotFoundError determines if the given error is a NotFoundError. +// NotFoundError is returned when the requested table, index, document or sequence +// doesn't exist. +var IsNotFoundError = errs.IsNotFoundError + +// IsAlreadyExistsError determines if the error is returned as a result of +// a conflict when attempting to create a table, an index, a document or a sequence +// with a name that is already used by another resource. +func IsAlreadyExistsError(err error) bool { + if errs.IsAlreadyExistsError(err) { + return true + } + + for err != nil { + if cerr, ok := err.(*database.ConstraintViolationError); ok { + switch cerr.Constraint { + case "UNIQUE", "PRIMARY KEY": + return true + default: + return false + } + } + + err = errors.Unwrap(err) + } + + return false +} diff --git a/go.mod b/go.mod index 5f066c1c2..999667490 100644 --- a/go.mod +++ b/go.mod @@ -5,29 +5,29 @@ go 1.18 require ( github.com/buger/jsonparser v1.1.1 github.com/cockroachdb/errors v1.9.0 - github.com/cockroachdb/pebble v0.0.0-20220624201436-71d17c2a007b + github.com/cockroachdb/pebble v0.0.0-20220708173837-d3484a60444e github.com/google/go-cmp v0.5.8 - github.com/stretchr/testify v1.7.5 + github.com/stretchr/testify v1.8.0 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f ) require ( - github.com/DataDog/zstd v1.5.2 // indirect + github.com/DataDog/zstd v1.4.5 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect github.com/cockroachdb/redact v1.1.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/getsentry/sentry-go v0.13.0 // indirect + github.com/getsentry/sentry-go v0.12.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/klauspost/compress v1.15.6 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/klauspost/compress v1.11.7 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect - golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d // indirect - golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect + golang.org/x/exp v0.0.0-20200513190911-00229845015e // indirect + golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0659e68e8..7e98f48fb 100644 --- a/go.sum +++ b/go.sum @@ -7,9 +7,8 @@ github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EF github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= @@ -22,9 +21,8 @@ github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -39,8 +37,8 @@ github.com/cockroachdb/errors v1.9.0/go.mod h1:vaNcEYYqbIqB5JhKBhFV9CneUqeuEbB2O github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f h1:6jduT9Hfc0njg5jJ1DdKCFPdMBrp/mdZfCpa5h+WM74= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20220624201436-71d17c2a007b h1:4IzbYFgF+NdvAZDMUgV1nEVszyHH3i8kgplHFfAwruk= -github.com/cockroachdb/pebble v0.0.0-20220624201436-71d17c2a007b/go.mod h1:pr479tNxFRmcfDyklTqoRMDDVmRlEbL+d7a7rhKnrI4= +github.com/cockroachdb/pebble v0.0.0-20220708173837-d3484a60444e h1:MGFpdiedteFe4rm8UY/0FixU8RVAh4wZYUCLQys9GjI= +github.com/cockroachdb/pebble v0.0.0-20220708173837-d3484a60444e/go.mod h1:pr479tNxFRmcfDyklTqoRMDDVmRlEbL+d7a7rhKnrI4= github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= @@ -72,9 +70,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo= -github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0= github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= @@ -111,9 +108,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -166,9 +162,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= -github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -252,8 +247,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -290,9 +285,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20200513190911-00229845015e h1:rMqLP+9XLy+LdbCXHjJHAmTfXCr93W7oruWA6Hq1Alc= golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d h1:vtUKgx8dahOomfFzLREU8nSv25YHnTgLBn4rDnWZdU0= -golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -363,9 +357,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810 h1:rHZQSjJdAI4Xf5Qzeh2bBc5YJIkPFVM6oDtMFYmgws0= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/internal/database/catalog.go b/internal/database/catalog.go index 8e9110698..500e2d306 100644 --- a/internal/database/catalog.go +++ b/internal/database/catalog.go @@ -9,7 +9,7 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/lock" "github.com/genjidb/genji/internal/tree" "github.com/genjidb/genji/lib/atomic" @@ -422,8 +422,8 @@ func (c *Catalog) RenameTable(tx *Transaction, oldName, newName string) error { // Delete the old table info. err = c.CatalogTable.Delete(tx, oldName) - if errors.Is(err, errs.ErrDocumentNotFound) { - return errors.WithStack(errs.NotFoundError{Name: oldName}) + if errs.IsNotFoundError(err) { + return errors.Wrapf(err, "table %s does not exist", oldName) } if err != nil { return err @@ -789,7 +789,7 @@ func (c *catalogCache) Get(tp, name string) (Relation, error) { o, ok := m[name] if !ok { - return nil, errors.WithStack(errs.NotFoundError{Name: name}) + return nil, errors.WithStack(&errs.NotFoundError{Name: name}) } return o, nil diff --git a/internal/database/catalog_test.go b/internal/database/catalog_test.go index f318d0955..a700e2c26 100644 --- a/internal/database/catalog_test.go +++ b/internal/database/catalog_test.go @@ -8,8 +8,8 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/expr" "github.com/genjidb/genji/internal/testutil" "github.com/genjidb/genji/internal/testutil/assert" @@ -68,7 +68,7 @@ func TestCatalogTable(t *testing.T) { // Getting a table that doesn't exist should fail. _, err = catalog.GetTable(tx, "unknown") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "unknown"}) } @@ -91,13 +91,13 @@ func TestCatalogTable(t *testing.T) { // Getting a table that has been dropped should fail. _, err = catalog.GetTable(tx, "test") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "test"}) } // Dropping a table that doesn't exist should fail. err = catalog.DropTable(tx, "test") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "test"}) } @@ -153,7 +153,7 @@ func TestCatalogTable(t *testing.T) { // Getting the old table should return an error. _, err = catalog.GetTable(tx, "foo") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "foo"}) } @@ -179,7 +179,7 @@ func TestCatalogTable(t *testing.T) { // Renaming a non existing table should return an error err = catalog.RenameTable(tx, "foo", "") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "foo"}) } @@ -230,7 +230,7 @@ func TestCatalogTable(t *testing.T) { // Renaming a non existing table should return an error err = catalog.AddFieldConstraint(tx, "bar", &fieldToAdd, nil) - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "bar"}) } @@ -351,7 +351,7 @@ func TestCatalogCreateIndex(t *testing.T) { err := catalog.CreateIndex(tx, &database.IndexInfo{ IndexName: "idxFoo", Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo")}, }) - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "test"}) } @@ -449,7 +449,7 @@ func TestTxDropIndex(t *testing.T) { updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error { err := catalog.DropIndex(tx, "idxFoo") - assert.ErrorIs(t, err, errs.NotFoundError{Name: "idxFoo"}) + assert.ErrorIs(t, err, &errs.NotFoundError{Name: "idxFoo"}) return nil }) }) diff --git a/internal/database/constraint.go b/internal/database/constraint.go index 4a5e2b8bb..703712b10 100644 --- a/internal/database/constraint.go +++ b/internal/database/constraint.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/cockroachdb/errors" "github.com/genjidb/genji/document" "github.com/genjidb/genji/internal/stringutil" "github.com/genjidb/genji/internal/tree" @@ -342,15 +343,10 @@ type ConstraintViolationError struct { Key *tree.Key } -func (c *ConstraintViolationError) Error() string { +func (c ConstraintViolationError) Error() string { return fmt.Sprintf("%s constraint error: %s", c.Constraint, c.Paths) } func IsConstraintViolationError(err error) bool { - switch err.(type) { - case *ConstraintViolationError: - return true - default: - return false - } + return errors.Is(err, (*ConstraintViolationError)(nil)) } diff --git a/internal/database/sequence.go b/internal/database/sequence.go index 5fa00fd8a..2f298eb41 100644 --- a/internal/database/sequence.go +++ b/internal/database/sequence.go @@ -6,7 +6,7 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/tree" "github.com/genjidb/genji/types" ) diff --git a/internal/database/table.go b/internal/database/table.go index be6a39b0a..d668ba53f 100644 --- a/internal/database/table.go +++ b/internal/database/table.go @@ -5,7 +5,7 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/kv" "github.com/genjidb/genji/internal/tree" "github.com/genjidb/genji/types" @@ -86,7 +86,7 @@ func (t *Table) Delete(key *tree.Key) error { err := t.Tree.Delete(key) if errors.Is(err, kv.ErrKeyNotFound) { - return errors.WithStack(errs.ErrDocumentNotFound) + return errors.WithStack(errs.NewNotFoundError(key.String())) } return err @@ -105,7 +105,7 @@ func (t *Table) Replace(key *tree.Key, d types.Document) (types.Document, error) return nil, err } if !ok { - return nil, errors.Wrapf(errs.ErrDocumentNotFound, "can't replace key %q", key) + return nil, errors.Wrapf(errs.NewNotFoundError(key.String()), "can't replace key %q", key) } d, enc, err := t.encodeDocument(d) @@ -151,7 +151,7 @@ func (t *Table) GetDocument(key *tree.Key) (types.Document, error) { enc, err := t.Tree.Get(key) if err != nil { if errors.Is(err, kv.ErrKeyNotFound) { - return nil, errors.WithStack(errs.ErrDocumentNotFound) + return nil, errors.WithStack(errs.NewNotFoundError(key.String())) } return nil, fmt.Errorf("failed to fetch document %q: %w", key, err) } diff --git a/internal/database/table_test.go b/internal/database/table_test.go index 71daae182..9e9d3cd50 100644 --- a/internal/database/table_test.go +++ b/internal/database/table_test.go @@ -6,8 +6,8 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji/document" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/query/statement" "github.com/genjidb/genji/internal/testutil" "github.com/genjidb/genji/internal/testutil/assert" @@ -93,7 +93,7 @@ func TestTableGetDocument(t *testing.T) { defer cleanup() r, err := tb.GetDocument(tree.NewEncodedKey([]byte("id"))) - assert.ErrorIs(t, err, errs.ErrDocumentNotFound) + require.True(t, errs.IsNotFoundError(err)) require.Nil(t, r) }) @@ -203,7 +203,7 @@ func TestTableDelete(t *testing.T) { // try again, should fail _, err = tb.GetDocument(key1) - assert.ErrorIs(t, err, errs.ErrDocumentNotFound) + require.True(t, errs.IsNotFoundError(err)) // make sure it didn't also delete the other one res, err := tb.GetDocument(key2) @@ -220,7 +220,7 @@ func TestTableReplace(t *testing.T) { defer cleanup() _, err := tb.Replace(tree.NewEncodedKey([]byte("id")), newDocument()) - assert.ErrorIs(t, err, errs.ErrDocumentNotFound) + require.True(t, errs.IsNotFoundError(err)) }) t.Run("Should replace the right document", func(t *testing.T) { diff --git a/errors/errors.go b/internal/errors/errors.go similarity index 51% rename from errors/errors.go rename to internal/errors/errors.go index def4d3a86..fcc26de97 100644 --- a/errors/errors.go +++ b/internal/errors/errors.go @@ -6,15 +6,6 @@ import ( "github.com/cockroachdb/errors" ) -var ( - // ErrDocumentNotFound is returned when no document is associated with the provided key. - ErrDocumentNotFound = errors.New("document not found") - - // ErrDuplicateDocument is returned when another document is already associated with a given key, primary key, - // or if there is a unique index violation. - ErrDuplicateDocument = errors.New("duplicate document") -) - // AlreadyExistsError is returned when to create a table, an index or a sequence // with a name that is already used by another resource. type AlreadyExistsError struct { @@ -26,13 +17,15 @@ func (a AlreadyExistsError) Error() string { } func IsAlreadyExistsError(err error) bool { - err = errors.UnwrapAll(err) - switch err.(type) { - case AlreadyExistsError, *AlreadyExistsError: - return true - default: - return false + for err != nil { + switch err.(type) { + case *AlreadyExistsError, AlreadyExistsError: + return true + } + err = errors.Unwrap(err) } + + return false } // NotFoundError is returned when the requested table, index or sequence @@ -41,16 +34,30 @@ type NotFoundError struct { Name string } +func NewDocumentNotFoundError() error { + return NewNotFoundError("document") +} + +func NewNotFoundError(name string) error { + return &NotFoundError{Name: name} +} + func (a NotFoundError) Error() string { + if a.Name == "document" { + return "document not found" + } + return fmt.Sprintf("%q not found", a.Name) } func IsNotFoundError(err error) bool { - err = errors.UnwrapAll(err) - switch err.(type) { - case NotFoundError, *NotFoundError: - return true - default: - return false + for err != nil { + switch err.(type) { + case *NotFoundError, NotFoundError: + return true + } + err = errors.Unwrap(err) } + + return false } diff --git a/internal/query/statement/alter.go b/internal/query/statement/alter.go index f4c60223e..35b5b4027 100644 --- a/internal/query/statement/alter.go +++ b/internal/query/statement/alter.go @@ -2,8 +2,8 @@ package statement import ( "github.com/cockroachdb/errors" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" ) // AlterStmt is a DSL that allows creating a full ALTER TABLE query. diff --git a/internal/query/statement/alter_test.go b/internal/query/statement/alter_test.go index 91c1efce9..df604edf4 100644 --- a/internal/query/statement/alter_test.go +++ b/internal/query/statement/alter_test.go @@ -3,12 +3,11 @@ package statement_test import ( "testing" - "github.com/cockroachdb/errors" "github.com/genjidb/genji" "github.com/genjidb/genji/document" "github.com/genjidb/genji/internal/testutil/assert" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/stretchr/testify/require" ) @@ -33,7 +32,7 @@ func TestAlterTable(t *testing.T) { // Selecting from the old name should fail. err = db.Exec("SELECT * FROM foo") - if !errors.Is(err, errs.NotFoundError{}) { + if !errs.IsNotFoundError(err) { assert.ErrorIs(t, err, errs.NotFoundError{Name: "foo"}) } diff --git a/internal/query/statement/create.go b/internal/query/statement/create.go index bf7f06c0b..7321c575b 100644 --- a/internal/query/statement/create.go +++ b/internal/query/statement/create.go @@ -3,8 +3,8 @@ package statement import ( "math" - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/stream" "github.com/genjidb/genji/internal/stream/index" "github.com/genjidb/genji/internal/stream/table" diff --git a/internal/query/statement/drop.go b/internal/query/statement/drop.go index 6ff16dbe6..c21e3c96a 100644 --- a/internal/query/statement/drop.go +++ b/internal/query/statement/drop.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/cockroachdb/errors" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" ) // DropTableStmt is a DSL that allows creating a DROP TABLE query. diff --git a/internal/query/statement/drop_test.go b/internal/query/statement/drop_test.go index 99f0bb1cb..91331ddcc 100644 --- a/internal/query/statement/drop_test.go +++ b/internal/query/statement/drop_test.go @@ -5,7 +5,7 @@ import ( "github.com/cockroachdb/errors" "github.com/genjidb/genji" - errs "github.com/genjidb/genji/errors" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/testutil" "github.com/genjidb/genji/internal/testutil/assert" "github.com/genjidb/genji/types" @@ -105,7 +105,7 @@ func TestDropSequence(t *testing.T) { // Assert that the good index has been dropped. _, err := db.Catalog.GetSequence("seq1") - require.IsType(t, errs.NotFoundError{}, errors.Unwrap(err)) + require.IsType(t, &errs.NotFoundError{}, errors.Unwrap(err)) _, err = db.Catalog.GetSequence("seq2") assert.NoError(t, err) diff --git a/internal/query/statement/reindex.go b/internal/query/statement/reindex.go index 05a8eea79..b49bbd3af 100644 --- a/internal/query/statement/reindex.go +++ b/internal/query/statement/reindex.go @@ -1,8 +1,8 @@ package statement import ( - errs "github.com/genjidb/genji/errors" "github.com/genjidb/genji/internal/database" + errs "github.com/genjidb/genji/internal/errors" "github.com/genjidb/genji/internal/stream" "github.com/genjidb/genji/internal/stream/index" "github.com/genjidb/genji/internal/stream/table" diff --git a/internal/testutil/assert/errors.go b/internal/testutil/assert/errors.go index 56f010f43..9fb157b57 100644 --- a/internal/testutil/assert/errors.go +++ b/internal/testutil/assert/errors.go @@ -53,5 +53,5 @@ func NoErrorf(t testing.TB, err error, str string, args ...interface{}) { func NoError(t testing.TB, err error) { t.Helper() - NoErrorf(t, err, "Expected error to be nil but got %q instead", err) + NoErrorf(t, err, "Expected error to be nil but got %q instead: %+v", err, err) }