From 78535320ddabcf4b8663a172cee7a917462a6997 Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Tue, 16 Mar 2021 21:26:34 +0400 Subject: [PATCH] Fix staticcheck warnings --- cmd/genji/dbutil/insert_test.go | 12 +- database/config.go | 4 +- document/array.go | 5 +- document/array_test.go | 1 + document/compare.go | 8 +- document/document.go | 3 + document/document_test.go | 2 + document/iterator.go | 25 ---- document/iterator_test.go | 97 ------------- document/value.go | 34 +---- document/value_test.go | 5 - engine/boltengine/engine.go | 1 - engine/boltengine/example_test.go | 4 +- expr/function.go | 4 +- planner/optimizer_test.go | 225 +++++++++++++++--------------- query/alter_test.go | 1 + query/drop_test.go | 1 + query/glob/like.go | 7 - query/insert_test.go | 39 +++--- query/select_test.go | 3 + query/transaction.go | 4 +- sql/driver/driver_test.go | 2 +- sql/parser/expr.go | 2 +- sql/scanner/init.go | 18 --- sql/scanner/init_tinygo.go | 17 --- sql/scanner/scanner.go | 20 ++- sql/scanner/token.go | 11 -- stream/iterator.go | 4 +- stream/operator.go | 2 +- stream/operator_test.go | 2 +- stream/project_test.go | 3 +- 31 files changed, 189 insertions(+), 377 deletions(-) delete mode 100644 sql/scanner/init.go delete mode 100644 sql/scanner/init_tinygo.go diff --git a/cmd/genji/dbutil/insert_test.go b/cmd/genji/dbutil/insert_test.go index 0f2fe0474..f3dcbecfe 100644 --- a/cmd/genji/dbutil/insert_test.go +++ b/cmd/genji/dbutil/insert_test.go @@ -17,11 +17,11 @@ func TestInsertJSON(t *testing.T) { want string fails bool }{ - {"Simple Json", `{"a": 1}`, `{"a": 1}`, false}, - {"JSON object", `{"a": {"b": [1, 2, 3]}}`, `{"a": {"b": [1, 2, 3]}}`, false}, - {"nested document", `{"a": {"b": [1, 2, 3]}}`, `{"a": {"b": [1, 2, 3]}}`, false}, - {"nested array multiple indexes", `{"a": {"b": [1, 2, [1, 2, {"c": "foo"}]]}}`, `{"a": {"b": [1, 2, [1, 2, {"c": "foo"}]]}}`, false}, - {"document in array", `{"a": [{"b":"foo"}, 2, 3]}`, `{"a": [{"b":"foo"}, 2, 3]}`, false}, + {"Simple Json", `{"a": 1}`, `[{"a": 1}]`, false}, + {"JSON object", `{"a": {"b": [1, 2, 3]}}`, `[{"a": {"b": [1, 2, 3]}}]`, false}, + {"nested document", `{"a": {"b": [1, 2, 3]}}`, `[{"a": {"b": [1, 2, 3]}}]`, false}, + {"nested array multiple indexes", `{"a": {"b": [1, 2, [1, 2, {"c": "foo"}]]}}`, `[{"a": {"b": [1, 2, [1, 2, {"c": "foo"}]]}}]`, false}, + {"document in array", `{"a": [{"b":"foo"}, 2, 3]}`, `[{"a": [{"b":"foo"}, 2, 3]}]`, false}, {"Non closed json array", `[{"foo":"bar"}`, ``, true}, {"Non closed json stream", `{"foo":"bar"`, ``, true}, } @@ -46,7 +46,7 @@ func TestInsertJSON(t *testing.T) { require.NoError(t, err) var buf bytes.Buffer - err = document.IteratorToJSON(&buf, res) + err = document.IteratorToJSONArray(&buf, res) require.NoError(t, err) require.JSONEq(t, tt.want, buf.String()) diff --git a/database/config.go b/database/config.go index 8364d5870..447949035 100644 --- a/database/config.go +++ b/database/config.go @@ -491,9 +491,7 @@ func (ti *TableInfo) ScanDocument(d document.Document) error { func (ti *TableInfo) Clone() *TableInfo { cp := *ti cp.FieldConstraints = nil - for _, fc := range ti.FieldConstraints { - cp.FieldConstraints = append(cp.FieldConstraints, fc) - } + cp.FieldConstraints = append(cp.FieldConstraints, ti.FieldConstraints...) return &cp } diff --git a/document/array.go b/document/array.go index deb1f2c13..ec4ae8d57 100644 --- a/document/array.go +++ b/document/array.go @@ -228,9 +228,8 @@ func (vb ValueBuffer) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements the json.Unmarshaler interface. func (vb *ValueBuffer) UnmarshalJSON(data []byte) error { var err error - _, perr := jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { - var v Value - v, err = parseJSONValue(dataType, value) + _, perr := jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, _ error) { + v, err := parseJSONValue(dataType, value) if err != nil { return } diff --git a/document/array_test.go b/document/array_test.go index 14e36a29b..efdbace40 100644 --- a/document/array_test.go +++ b/document/array_test.go @@ -88,5 +88,6 @@ func TestValueBufferApply(t *testing.T) { require.NoError(t, err) got, err := json.Marshal(buf) + require.NoError(t, err) require.JSONEq(t, `[6, [6, 6], {"4": 6}]`, string(got)) } diff --git a/document/compare.go b/document/compare.go index 5ef096615..3447059d3 100644 --- a/document/compare.go +++ b/document/compare.go @@ -121,13 +121,13 @@ func compareBooleans(op operator, a, b bool) bool { case operatorEq: return a == b case operatorGt: - return a == true && b == false + return a && !b case operatorGte: - return a == b || a == true + return a == b || a case operatorLt: - return a == false && b == true + return !a && b case operatorLte: - return a == b || a == false + return a == b || !a } return false diff --git a/document/document.go b/document/document.go index 4b5154636..491f8cde3 100644 --- a/document/document.go +++ b/document/document.go @@ -205,6 +205,9 @@ func setValueAtPath(v Value, p Path, newValue Value) (Value, error) { } va, err = setValueAtPath(va, p[1:], newValue) + if err != nil { + return v, err + } err = vb.Replace(p[0].ArrayIndex, va) return NewArrayValue(&vb), err } diff --git a/document/document_test.go b/document/document_test.go index 7556918c8..3a2f6a21c 100644 --- a/document/document_test.go +++ b/document/document_test.go @@ -215,6 +215,7 @@ func TestFieldBuffer(t *testing.T) { require.NoError(t, err) got, err := json.Marshal(buf) + require.NoError(t, err) require.JSONEq(t, `{"a": 1, "c": [1, 1], "f": {"g": 1}}`, string(got)) }) @@ -345,6 +346,7 @@ func TestNewFromStruct(t *testing.T) { Ig: 100, }, BB: time.Date(2020, 11, 15, 16, 37, 10, 20, time.UTC), + t: 99, } q := 5 diff --git a/document/iterator.go b/document/iterator.go index b2d948e1b..c59c2be8e 100644 --- a/document/iterator.go +++ b/document/iterator.go @@ -36,31 +36,6 @@ func (rr documentsIterator) Iterate(fn func(d Document) error) error { return nil } -// The IteratorFunc type is an adapter to allow the use of ordinary functions as Iterators. -// If f is a function with the appropriate signature, IteratorFunc(f) is an Iterator that calls f. -type IteratorFunc func(fn func(d Document) error) error - -// Iterate calls f(fn). -func (f IteratorFunc) Iterate(fn func(d Document) error) error { - return f(fn) -} - -// IteratorToJSON encodes all the documents of an iterator to JSON stream. -func IteratorToJSON(w io.Writer, s Iterator) error { - buf := bufio.NewWriter(w) - defer buf.Flush() - - return s.Iterate(func(d Document) error { - data, err := jsonDocument{d}.MarshalJSON() - if err != nil { - return err - } - - _, err = buf.Write(data) - return err - }) -} - // IteratorToJSONArray encodes all the documents of an iterator to a JSON array. func IteratorToJSONArray(w io.Writer, s Iterator) error { buf := bufio.NewWriter(w) diff --git a/document/iterator_test.go b/document/iterator_test.go index a392aed01..ef8fa4d9a 100644 --- a/document/iterator_test.go +++ b/document/iterator_test.go @@ -4,109 +4,12 @@ import ( "bytes" "encoding/json" "fmt" - "log" "testing" - "github.com/genjidb/genji" "github.com/genjidb/genji/document" "github.com/stretchr/testify/require" ) -func ExampleStream_Iterate() { - type User struct { - ID int64 - Name string - Age uint32 - Address struct { - City string - ZipCode string - } - } - - db, err := genji.Open(":memory:") - if err != nil { - log.Fatal(err) - } - defer db.Close() - - err = db.Exec("CREATE TABLE IF NOT EXISTS user") - if err != nil { - log.Fatal(err) - } - - for i := 1; i <= 10; i++ { - err = db.Exec("INSERT INTO user VALUES ?", &User{ - ID: int64(i), - Name: fmt.Sprintf("foo%d", i), - Age: uint32(i * 10), - Address: struct { - City string - ZipCode string - }{ - City: "Lyon", - ZipCode: fmt.Sprintf("69%03d", i), - }, - }) - if err != nil { - log.Fatal(err) - } - } - - result, err := db.Query(`SELECT id, name, age, address FROM user WHERE age >= 18`) - if err != nil { - panic(err) - } - defer result.Close() - - err = result.Iterate(func(d document.Document) error { - // Scan into a struct - var u User - err = document.StructScan(d, &u) - if err != nil { - return err - } - - fmt.Println(u) - - // Or scan individual variables - // Types of variables don't have to exactly match with the types stored - var id uint64 - var name []byte - var age uint8 - var address map[string]string - - err = document.Scan(d, &id, &name, &age, &address) - if err != nil { - return err - } - - fmt.Println(id, string(name), age, address) - return nil - }) - if err != nil { - panic(err) - } - - // Output: {2 foo2 20 {Lyon 69002}} - // 2 foo2 20 map[city:Lyon zipcode:69002] - // {3 foo3 30 {Lyon 69003}} - // 3 foo3 30 map[city:Lyon zipcode:69003] - // {4 foo4 40 {Lyon 69004}} - // 4 foo4 40 map[city:Lyon zipcode:69004] - // {5 foo5 50 {Lyon 69005}} - // 5 foo5 50 map[city:Lyon zipcode:69005] - // {6 foo6 60 {Lyon 69006}} - // 6 foo6 60 map[city:Lyon zipcode:69006] - // {7 foo7 70 {Lyon 69007}} - // 7 foo7 70 map[city:Lyon zipcode:69007] - // {8 foo8 80 {Lyon 69008}} - // 8 foo8 80 map[city:Lyon zipcode:69008] - // {9 foo9 90 {Lyon 69009}} - // 9 foo9 90 map[city:Lyon zipcode:69009] - // {10 foo10 100 {Lyon 69010}} - // 10 foo10 100 map[city:Lyon zipcode:69010] -} - func TestIteratorToJSONArray(t *testing.T) { var docs []document.Document for i := 0; i < 3; i++ { diff --git a/document/value.go b/document/value.go index 0c61a68c2..647bb3f16 100644 --- a/document/value.go +++ b/document/value.go @@ -13,13 +13,11 @@ import ( ) var ( - boolZeroValue = NewZeroValue(BoolValue) - integerZeroValue = NewZeroValue(IntegerValue) - doubleZeroValue = NewZeroValue(DoubleValue) - blobZeroValue = NewZeroValue(BlobValue) - textZeroValue = NewZeroValue(TextValue) - arrayZeroValue = NewZeroValue(ArrayValue) - documentZeroValue = NewZeroValue(DocumentValue) + boolZeroValue = NewZeroValue(BoolValue) + integerZeroValue = NewZeroValue(IntegerValue) + doubleZeroValue = NewZeroValue(DoubleValue) + blobZeroValue = NewZeroValue(BlobValue) + textZeroValue = NewZeroValue(TextValue) ) // ErrUnsupportedType is used to skip struct or array fields that are not supported. @@ -211,7 +209,7 @@ func (v Value) IsZeroValue() (bool, error) { case DoubleValue: return v.V == doubleZeroValue.V, nil case BlobValue: - return bytes.Compare(v.V.([]byte), blobZeroValue.V.([]byte)) == 0, nil + return bytes.Equal(v.V.([]byte), blobZeroValue.V.([]byte)), nil case TextValue: return v.V == textZeroValue.V, nil case ArrayValue: @@ -464,26 +462,6 @@ func calculateValues(a, b Value, operator byte) (res Value, err error) { return NewNullValue(), nil } -func convertNumberToInt64(v Value) (int64, error) { - var i int64 - - switch v.Type { - case IntegerValue: - return v.V.(int64), nil - case DoubleValue: - f := v.V.(float64) - if f > math.MaxInt64 { - return i, errors.New(`cannot convert "double" to "integer" without overflowing`) - } - if math.Trunc(f) != f { - return 0, errors.New(`cannot convert "double" value to "integer" without loss of precision`) - } - i = int64(f) - } - - return i, nil -} - func calculateIntegers(a, b Value, operator byte) (res Value, err error) { var xa, xb int64 diff --git a/document/value_test.go b/document/value_test.go index f6321295a..7f23c3258 100644 --- a/document/value_test.go +++ b/document/value_test.go @@ -35,13 +35,8 @@ func TestValueString(t *testing.T) { } func TestNewValue(t *testing.T) { - type st struct { - A int - B string - } type myBytes []byte type myString string - type myBool bool type myUint uint type myUint16 uint16 type myUint32 uint32 diff --git a/engine/boltengine/engine.go b/engine/boltengine/engine.go index 938cd0481..a396ed8af 100644 --- a/engine/boltengine/engine.go +++ b/engine/boltengine/engine.go @@ -11,7 +11,6 @@ import ( ) const ( - separator byte = 0x1F // name of the bucket used to mark keys for deletion binBucket = "__bin" ) diff --git a/engine/boltengine/example_test.go b/engine/boltengine/example_test.go index 2078148bf..d3e81d36c 100644 --- a/engine/boltengine/example_test.go +++ b/engine/boltengine/example_test.go @@ -19,10 +19,10 @@ func Example() { defer os.RemoveAll(dir) db, err := genji.Open(filepath.Join(dir, "my.db")) - defer db.Close() if err != nil { log.Fatal(err) } + defer db.Close() } func ExampleNewEngine() { @@ -38,8 +38,8 @@ func ExampleNewEngine() { } db, err := genji.New(context.Background(), ng) - defer db.Close() if err != nil { log.Fatal(err) } + defer db.Close() } diff --git a/expr/function.go b/expr/function.go index baa3f5eb7..3ef2d64e9 100644 --- a/expr/function.go +++ b/expr/function.go @@ -312,7 +312,7 @@ func (m *MinAggregator) Aggregate(env *Environment) error { return nil } - if m.Min.Type == v.Type || m.Min.Type.IsNumber() && m.Min.Type.IsNumber() { + if m.Min.Type == v.Type || m.Min.Type.IsNumber() && v.Type.IsNumber() { ok, err := m.Min.IsGreaterThan(v) if err != nil { return err @@ -408,7 +408,7 @@ func (m *MaxAggregator) Aggregate(env *Environment) error { return nil } - if m.Max.Type == v.Type || m.Max.Type.IsNumber() && m.Max.Type.IsNumber() { + if m.Max.Type == v.Type || m.Max.Type.IsNumber() && v.Type.IsNumber() { ok, err := m.Max.IsLesserThan(v) if err != nil { return err diff --git a/planner/optimizer_test.go b/planner/optimizer_test.go index abb06d4c7..eb854323c 100644 --- a/planner/optimizer_test.go +++ b/planner/optimizer_test.go @@ -8,17 +8,10 @@ import ( "github.com/genjidb/genji/expr" "github.com/genjidb/genji/planner" "github.com/genjidb/genji/sql/parser" - "github.com/genjidb/genji/stream" st "github.com/genjidb/genji/stream" "github.com/stretchr/testify/require" ) -func parsePath(t testing.TB, str string) document.Path { - vp, err := parser.ParsePath(str) - require.NoError(t, err) - return vp -} - func TestSplitANDConditionRule(t *testing.T) { tests := []struct { name string @@ -179,11 +172,11 @@ func TestPrecalculateExprRule(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - s := stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(test.e)) + s := st.New(st.SeqScan("foo")). + Pipe(st.Filter(test.e)) res, err := planner.PrecalculateExprRule(s, nil, test.params) require.NoError(t, err) - require.Equal(t, stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(test.expected)).String(), res.String()) + require.Equal(t, st.New(st.SeqScan("foo")).Pipe(st.Filter(test.expected)).String(), res.String()) }) } } @@ -191,30 +184,30 @@ func TestPrecalculateExprRule(t *testing.T) { func TestRemoveUnnecessarySelectionNodesRule(t *testing.T) { tests := []struct { name string - root, expected *stream.Stream + root, expected *st.Stream }{ { "non-constant expr", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("a"))), - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("a"))), }, { "truthy constant expr", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("10"))), - stream.New(stream.SeqScan("foo")), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("10"))), + st.New(st.SeqScan("foo")), }, { "truthy constant expr with IN", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(expr.In( + st.New(st.SeqScan("foo")).Pipe(st.Filter(expr.In( expr.Path(document.NewPath("a")), expr.ArrayValue(document.NewValueBuffer()), ))), - &stream.Stream{}, + &st.Stream{}, }, { "falsy constant expr", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("0"))), - &stream.Stream{}, + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("0"))), + &st.Stream{}, }, } @@ -234,48 +227,48 @@ func TestRemoveUnnecessarySelectionNodesRule(t *testing.T) { func TestRemoveUnnecessaryDedupNodeRule(t *testing.T) { tests := []struct { name string - root, expected *stream.Stream + root, expected *st.Stream }{ { "non-unique key", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("b"))). - Pipe(stream.Distinct()), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("b"))). - Pipe(stream.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("b"))). + Pipe(st.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("b"))). + Pipe(st.Distinct()), }, { "primary key", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("a"))). - Pipe(stream.Distinct()), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("a"))). + Pipe(st.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("a"))), }, { "primary key with alias", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("a AS A"))). - Pipe(stream.Distinct()), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("a AS A"))), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("a AS A"))). + Pipe(st.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("a AS A"))), }, { "unique index", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("c"))). - Pipe(stream.Distinct()), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("c"))), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("c"))). + Pipe(st.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("c"))), }, { "pk() function", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("pk()"))). - Pipe(stream.Distinct()), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Project(parser.MustParseExpr("pk()"))), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("pk()"))). + Pipe(st.Distinct()), + st.New(st.SeqScan("foo")). + Pipe(st.Project(parser.MustParseExpr("pk()"))), }, } @@ -309,129 +302,129 @@ func TestRemoveUnnecessaryDedupNodeRule(t *testing.T) { func TestUseIndexBasedOnSelectionNodeRule(t *testing.T) { tests := []struct { name string - root, expected *stream.Stream + root, expected *st.Stream }{ { "non-indexed path", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("d = 1"))), - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("d = 1"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("d = 1"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("d = 1"))), }, { "FROM foo WHERE a = 1", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("a = 1"))), - stream.New(stream.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("a = 1"))), + st.New(st.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})), }, { "FROM foo WHERE a = 1 AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), - stream.New(stream.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))), }, { "FROM foo WHERE c = 3 AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c = 3"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), - stream.New(stream.IndexScan("idx_foo_c", st.Range{Min: document.NewIntegerValue(3), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c = 3"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.IndexScan("idx_foo_c", st.Range{Min: document.NewIntegerValue(3), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), }, { "FROM foo WHERE c > 3 AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c > 3"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), - stream.New(stream.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("c > 3"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c > 3"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("c > 3"))), }, { "SELECT a FROM foo WHERE c = 3 AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c = 3"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), - stream.New(stream.IndexScan("idx_foo_c", st.Range{Min: document.NewIntegerValue(3), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c = 3"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))). + Pipe(st.Project(parser.MustParseExpr("a"))), + st.New(st.IndexScan("idx_foo_c", st.Range{Min: document.NewIntegerValue(3), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))). + Pipe(st.Project(parser.MustParseExpr("a"))), }, { "SELECT a FROM foo WHERE c = 'hello' AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c = 'hello'"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), - stream.New(stream.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("c = 'hello'"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c = 'hello'"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))). + Pipe(st.Project(parser.MustParseExpr("a"))), + st.New(st.IndexScan("idx_foo_b", st.Range{Min: document.NewIntegerValue(2), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("c = 'hello'"))). + Pipe(st.Project(parser.MustParseExpr("a"))), }, { "SELECT a FROM foo WHERE c = 'hello' AND d = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c = 'hello'"))). - Pipe(stream.Filter(parser.MustParseExpr("d = 2"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("c = 'hello'"))). - Pipe(stream.Filter(parser.MustParseExpr("d = 2"))). - Pipe(stream.Project(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c = 'hello'"))). + Pipe(st.Filter(parser.MustParseExpr("d = 2"))). + Pipe(st.Project(parser.MustParseExpr("a"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("c = 'hello'"))). + Pipe(st.Filter(parser.MustParseExpr("d = 2"))). + Pipe(st.Project(parser.MustParseExpr("a"))), }, { "FROM foo WHERE a IN [1, 2]", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter( + st.New(st.SeqScan("foo")).Pipe(st.Filter( expr.In( parser.MustParseExpr("a"), expr.ArrayValue(document.NewValueBuffer(document.NewIntegerValue(1), document.NewIntegerValue(2))), ), )), - stream.New(stream.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true}, st.Range{Min: document.NewIntegerValue(2), Exact: true})), + st.New(st.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true}, st.Range{Min: document.NewIntegerValue(2), Exact: true})), }, { "FROM foo WHERE 1 IN a", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("1 IN a"))), - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("1 IN a"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("1 IN a"))), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("1 IN a"))), }, { "FROM foo WHERE a >= 10", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("a >= 10"))), - stream.New(stream.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(10)})), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("a >= 10"))), + st.New(st.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(10)})), }, { "FROM foo WHERE k = 1", - stream.New(stream.SeqScan("foo")).Pipe(stream.Filter(parser.MustParseExpr("k = 1"))), - stream.New(stream.PkScan("foo", st.Range{Min: document.NewIntegerValue(1), Exact: true})), + st.New(st.SeqScan("foo")).Pipe(st.Filter(parser.MustParseExpr("k = 1"))), + st.New(st.PkScan("foo", st.Range{Min: document.NewIntegerValue(1), Exact: true})), }, { "FROM foo WHERE k = 1 AND b = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("k = 1"))). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), - stream.New(stream.PkScan("foo", st.Range{Min: document.NewIntegerValue(1), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("k = 1"))). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), + st.New(st.PkScan("foo", st.Range{Min: document.NewIntegerValue(1), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("b = 2"))), }, { "FROM foo WHERE a = 1 AND k = 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))). - Pipe(stream.Filter(parser.MustParseExpr("2 = k"))), - stream.New(stream.PkScan("foo", st.Range{Min: document.NewIntegerValue(2), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))). + Pipe(st.Filter(parser.MustParseExpr("2 = k"))), + st.New(st.PkScan("foo", st.Range{Min: document.NewIntegerValue(2), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))), }, { "FROM foo WHERE a = 1 AND k < 2", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))). - Pipe(stream.Filter(parser.MustParseExpr("k < 2"))), - stream.New(stream.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("k < 2"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))). + Pipe(st.Filter(parser.MustParseExpr("k < 2"))), + st.New(st.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("k < 2"))), }, { "FROM foo WHERE a = 1 AND k = 'hello'", - stream.New(stream.SeqScan("foo")). - Pipe(stream.Filter(parser.MustParseExpr("a = 1"))). - Pipe(stream.Filter(parser.MustParseExpr("k = 'hello'"))), - stream.New(stream.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})). - Pipe(stream.Filter(parser.MustParseExpr("k = 'hello'"))), + st.New(st.SeqScan("foo")). + Pipe(st.Filter(parser.MustParseExpr("a = 1"))). + Pipe(st.Filter(parser.MustParseExpr("k = 'hello'"))), + st.New(st.IndexScan("idx_foo_a", st.Range{Min: document.NewIntegerValue(1), Exact: true})). + Pipe(st.Filter(parser.MustParseExpr("k = 'hello'"))), }, } diff --git a/query/alter_test.go b/query/alter_test.go index ca5dcb5c0..6bfa355e3 100644 --- a/query/alter_test.go +++ b/query/alter_test.go @@ -36,6 +36,7 @@ func TestAlterTable(t *testing.T) { } d, err := db.QueryDocument("SELECT * FROM bar") + require.NoError(t, err) data, err := document.MarshalJSON(d) require.NoError(t, err) require.JSONEq(t, `{"name": "John Doe", "age": 99}`, string(data)) diff --git a/query/drop_test.go b/query/drop_test.go index 60a42d4cc..a5b3b7bb1 100644 --- a/query/drop_test.go +++ b/query/drop_test.go @@ -69,6 +69,7 @@ func TestDropIndex(t *testing.T) { indexes = tx.ListIndexes() return nil }) + require.NoError(t, err) require.Len(t, indexes, 1) require.Equal(t, "idx_test1_foo", indexes[0]) } diff --git a/query/glob/like.go b/query/glob/like.go index 9454f0c68..fc7b94d00 100644 --- a/query/glob/like.go +++ b/query/glob/like.go @@ -1,10 +1,3 @@ -// The author disclaims copyright to this source code. In place of -// a legal notice, here is a blessing: -// -// May you do good and not evil. -// May you find forgiveness for yourself and forgive others. -// May you share freely, never taking more than you give. -// // This is an optimized Go port of the SQLite’s icuLikeCompare routine using backtracking. // See https://sqlite.org/src/file?name=ext%2Ficu%2Ficu.c&ln=117-195&ci=54b54f02c66c5aea diff --git a/query/insert_test.go b/query/insert_test.go index 4ac3431b2..08c3036b7 100644 --- a/query/insert_test.go +++ b/query/insert_test.go @@ -21,22 +21,22 @@ func TestInsertStmt(t *testing.T) { params []interface{} }{ {"Values / No columns", `INSERT INTO test VALUES ("a", 'b', 'c')`, true, ``, nil}, - {"Values / With columns", `INSERT INTO test (a, b, c) VALUES ('a', 'b', 'c')`, false, `{"pk()":1,"a":"a","b":"b","c":"c"}`, nil}, + {"Values / With columns", `INSERT INTO test (a, b, c) VALUES ('a', 'b', 'c')`, false, `[{"pk()":1,"a":"a","b":"b","c":"c"}]`, nil}, {"Values / Ident", `INSERT INTO test (a) VALUES (a)`, true, ``, nil}, {"Values / Ident string", "INSERT INTO test (a) VALUES (`a`)", true, ``, nil}, - {"Values / With fields ident string", "INSERT INTO test (a, `foo bar`) VALUES ('c', 'd')", false, `{"pk()":1,"a":"c","foo bar":"d"}`, nil}, - {"Values / Positional Params", "INSERT INTO test (a, b, c) VALUES (?, 'e', ?)", false, `{"pk()":1,"a":"d","b":"e","c":"f"}`, []interface{}{"d", "f"}}, - {"Values / Named Params", "INSERT INTO test (a, b, c) VALUES ($d, 'e', $f)", false, `{"pk()":1,"a":"d","b":"e","c":"f"}`, []interface{}{sql.Named("f", "f"), sql.Named("d", "d")}}, + {"Values / With fields ident string", "INSERT INTO test (a, `foo bar`) VALUES ('c', 'd')", false, `[{"pk()":1,"a":"c","foo bar":"d"}]`, nil}, + {"Values / Positional Params", "INSERT INTO test (a, b, c) VALUES (?, 'e', ?)", false, `[{"pk()":1,"a":"d","b":"e","c":"f"}]`, []interface{}{"d", "f"}}, + {"Values / Named Params", "INSERT INTO test (a, b, c) VALUES ($d, 'e', $f)", false, `[{"pk()":1,"a":"d","b":"e","c":"f"}]`, []interface{}{sql.Named("f", "f"), sql.Named("d", "d")}}, {"Values / Invalid params", "INSERT INTO test (a, b, c) VALUES ('d', ?)", true, "", []interface{}{'e'}}, - {"Values / List", `INSERT INTO test (a, b, c) VALUES ("a", 'b', [1, 2, 3])`, false, `{"pk()":1,"a":"a","b":"b","c":[1,2,3]}`, nil}, - {"Values / Document", `INSERT INTO test (a, b, c) VALUES ("a", 'b', {c: 1, d: c + 1})`, false, `{"pk()":1,"a":"a","b":"b","c":{"c":1,"d":2}}`, nil}, - {"Documents", "INSERT INTO test VALUES {a: 'a', b: 2.3, c: 1 = 1}", false, `{"pk()":1,"a":"a","b":2.3,"c":true}`, nil}, - {"Documents / Positional Params", "INSERT INTO test VALUES {a: ?, b: 2.3, c: ?}", false, `{"pk()":1,"a":"a","b":2.3,"c":true}`, []interface{}{"a", true}}, - {"Documents / Named Params", "INSERT INTO test VALUES {a: $a, b: 2.3, c: $c}", false, `{"pk()":1,"a":1,"b":2.3,"c":true}`, []interface{}{sql.Named("c", true), sql.Named("a", 1)}}, - {"Documents / List ", "INSERT INTO test VALUES {a: [1, 2, 3]}", false, `{"pk()":1,"a":[1,2,3]}`, nil}, - {"Documents / strings", `INSERT INTO test VALUES {'a': 'a', b: 2.3}`, false, `{"pk()":1,"a":"a","b":2.3}`, nil}, - {"Documents / double quotes", `INSERT INTO test VALUES {"a": "b"}`, false, `{"pk()":1,"a":"b"}`, nil}, - {"Documents / with reference to other fields", `INSERT INTO test VALUES {a: 400, b: a * 4}`, false, `{"pk()":1,"a":400,"b":1600}`, nil}, + {"Values / List", `INSERT INTO test (a, b, c) VALUES ("a", 'b', [1, 2, 3])`, false, `[{"pk()":1,"a":"a","b":"b","c":[1,2,3]}]`, nil}, + {"Values / Document", `INSERT INTO test (a, b, c) VALUES ("a", 'b', {c: 1, d: c + 1})`, false, `[{"pk()":1,"a":"a","b":"b","c":{"c":1,"d":2}}]`, nil}, + {"Documents", "INSERT INTO test VALUES {a: 'a', b: 2.3, c: 1 = 1}", false, `[{"pk()":1,"a":"a","b":2.3,"c":true}]`, nil}, + {"Documents / Positional Params", "INSERT INTO test VALUES {a: ?, b: 2.3, c: ?}", false, `[{"pk()":1,"a":"a","b":2.3,"c":true}]`, []interface{}{"a", true}}, + {"Documents / Named Params", "INSERT INTO test VALUES {a: $a, b: 2.3, c: $c}", false, `[{"pk()":1,"a":1,"b":2.3,"c":true}]`, []interface{}{sql.Named("c", true), sql.Named("a", 1)}}, + {"Documents / List ", "INSERT INTO test VALUES {a: [1, 2, 3]}", false, `[{"pk()":1,"a":[1,2,3]}]`, nil}, + {"Documents / strings", `INSERT INTO test VALUES {'a': 'a', b: 2.3}`, false, `[{"pk()":1,"a":"a","b":2.3}]`, nil}, + {"Documents / double quotes", `INSERT INTO test VALUES {"a": "b"}`, false, `[{"pk()":1,"a":"b"}]`, nil}, + {"Documents / with reference to other fields", `INSERT INTO test VALUES {a: 400, b: a * 4}`, false, `[{"pk()":1,"a":400,"b":1600}]`, nil}, {"Read-only tables", `INSERT INTO __genji_tables VALUES {a: 400, b: a * 4}`, true, ``, nil}, } @@ -70,7 +70,7 @@ func TestInsertStmt(t *testing.T) { defer st.Close() var buf bytes.Buffer - err = document.IteratorToJSON(&buf, st) + err = document.IteratorToJSONArray(&buf, st) require.NoError(t, err) require.JSONEq(t, test.expected, buf.String()) } @@ -129,9 +129,9 @@ func TestInsertStmt(t *testing.T) { require.NoError(t, err) var buf bytes.Buffer - err = document.IteratorToJSON(&buf, res) + err = document.IteratorToJSONArray(&buf, res) require.NoError(t, err) - require.JSONEq(t, `{"a": "a", "b-b": "b"}`, buf.String()) + require.JSONEq(t, `[{"a": "a", "b-b": "b"}]`, buf.String()) }) t.Run("with types constraints", func(t *testing.T) { @@ -158,12 +158,13 @@ func TestInsertStmt(t *testing.T) { res, err := db.Query("SELECT * FROM test") defer res.Close() + require.NoError(t, err) var buf bytes.Buffer - err = document.IteratorToJSON(&buf, res) + err = document.IteratorToJSONArray(&buf, res) require.NoError(t, err) - require.JSONEq(t, `{ + require.JSONEq(t, `[{ "i": 10000000000, "db": 21.21, "b": true, @@ -172,7 +173,7 @@ func TestInsertStmt(t *testing.T) { "t": "text", "a": [1, "foo", true], "d": {"foo": "bar"} - }`, buf.String()) + }]`, buf.String()) }) // cf issue: https://github.com/genjidb/genji/issues/328 diff --git a/query/select_test.go b/query/select_test.go index ee09722ce..6fda89bb2 100644 --- a/query/select_test.go +++ b/query/select_test.go @@ -150,8 +150,11 @@ func TestSelectStmt(t *testing.T) { require.NoError(t, err) err = db.Exec(`INSERT INTO test (foo, bar) VALUES (1, 'a')`) + require.NoError(t, err) err = db.Exec(`INSERT INTO test (foo, bar) VALUES (2, 'b')`) + require.NoError(t, err) err = db.Exec(`INSERT INTO test (foo, bar) VALUES (3, 'c')`) + require.NoError(t, err) err = db.Exec(`INSERT INTO test (foo, bar) VALUES (4, 'd')`) require.NoError(t, err) diff --git a/query/transaction.go b/query/transaction.go index a43b61643..e51aa0f7a 100644 --- a/query/transaction.go +++ b/query/transaction.go @@ -39,7 +39,7 @@ func (stmt BeginStmt) Run(tx *database.Transaction, args []expr.Param) (Result, type RollbackStmt struct{} func (stmt RollbackStmt) alterQuery(ctx context.Context, db *database.Database, q *Query) error { - if q.tx == nil || q.autoCommit == true { + if q.tx == nil || q.autoCommit { return errors.New("cannot rollback with no active transaction") } @@ -63,7 +63,7 @@ func (stmt RollbackStmt) Run(tx *database.Transaction, args []expr.Param) (Resul type CommitStmt struct{} func (stmt CommitStmt) alterQuery(ctx context.Context, db *database.Database, q *Query) error { - if q.tx == nil || q.autoCommit == true { + if q.tx == nil || q.autoCommit { return errors.New("cannot commit with no active transaction") } diff --git a/sql/driver/driver_test.go b/sql/driver/driver_test.go index a55c7df01..eb087c134 100644 --- a/sql/driver/driver_test.go +++ b/sql/driver/driver_test.go @@ -29,7 +29,7 @@ func TestDriver(t *testing.T) { require.EqualValues(t, 0, n) for i := 0; i < 10; i++ { - res, err = db.Exec("INSERT INTO test (a, b, c) VALUES (?, ?, ?)", i, []int{i + 1, i + 2, i + 3}, &foo{Foo: "bar"}) + _, err = db.Exec("INSERT INTO test (a, b, c) VALUES (?, ?, ?)", i, []int{i + 1, i + 2, i + 3}, &foo{Foo: "bar"}) require.NoError(t, err) } diff --git a/sql/parser/expr.go b/sql/parser/expr.go index 4001b381c..cfe31d7c7 100644 --- a/sql/parser/expr.go +++ b/sql/parser/expr.go @@ -12,7 +12,7 @@ import ( ) type dummyOperator struct { - leftHand, rightHand expr.Expr + rightHand expr.Expr } func (d *dummyOperator) Token() scanner.Token { panic("not implemented") } diff --git a/sql/scanner/init.go b/sql/scanner/init.go deleted file mode 100644 index 20aa0ccf6..000000000 --- a/sql/scanner/init.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !wasm -// +build !tinygo - -package scanner - -import ( - "bufio" - "io" -) - -func init() { - initKeywords() -} - -// NewScanner returns a new instance of Scanner. -func NewScanner(r io.Reader) *Scanner { - return &Scanner{r: &reader{r: bufio.NewReaderSize(r, 128)}} -} diff --git a/sql/scanner/init_tinygo.go b/sql/scanner/init_tinygo.go deleted file mode 100644 index f79e32723..000000000 --- a/sql/scanner/init_tinygo.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build tinygo wasm - -package scanner - -import ( - "bufio" - "io" - "sync" -) - -var keywordsInitializer sync.Once - -// NewScanner returns a new instance of Scanner. -func NewScanner(r io.Reader) *Scanner { - keywordsInitializer.Do(initKeywords) - return &Scanner{r: &reader{r: bufio.NewReaderSize(r, 128)}} -} diff --git a/sql/scanner/scanner.go b/sql/scanner/scanner.go index 28a29fd64..039263443 100644 --- a/sql/scanner/scanner.go +++ b/sql/scanner/scanner.go @@ -1,9 +1,11 @@ package scanner import ( + "bufio" "bytes" "errors" "io" + "strings" "unicode/utf8" "github.com/genjidb/genji/stringutil" @@ -12,12 +14,27 @@ import ( // Code heavily inspired by the influxdata/influxql repository // https://github.com/influxdata/influxql/blob/57f403b00b124eb900835c0c944e9b60d848db5e/scanner.go#L12 +func init() { + keywords = make(map[string]Token) + for tok := keywordBeg + 1; tok < keywordEnd; tok++ { + keywords[strings.ToLower(tokens[tok])] = tok + } + for _, tok := range []Token{AND, OR, TRUE, FALSE, NULL, IN, IS, LIKE} { + keywords[strings.ToLower(tokens[tok])] = tok + } +} + // Scanner represents a lexical scanner for Genji. type Scanner struct { r *reader buf bytes.Buffer } +// NewScanner returns a new instance of Scanner. +func NewScanner(r io.Reader) *Scanner { + return &Scanner{r: &reader{r: bufio.NewReaderSize(r, 128)}} +} + func (s *Scanner) read() (ch rune, pos Pos) { ch, pos = s.r.read() if ch != eof { @@ -387,9 +404,6 @@ func isDigit(ch rune) bool { return (ch >= '0' && ch <= '9') } // isIdentChar returns true if the rune can be used in an unquoted identifier. func isIdentChar(ch rune) bool { return isLetter(ch) || isDigit(ch) || ch == '_' } -// isIdentFirstChar returns true if the rune can be used as the first char in an unquoted identifer. -func isIdentFirstChar(ch rune) bool { return isLetter(ch) || ch == '_' } - // BufScanner represents a wrapper for scanner to add a buffer. // It provides a fixed-length circular buffer that can be unread. type BufScanner struct { diff --git a/sql/scanner/token.go b/sql/scanner/token.go index dee2cac73..6bb7b9892 100644 --- a/sql/scanner/token.go +++ b/sql/scanner/token.go @@ -15,7 +15,6 @@ const ( WS COMMENT - literalBeg // IDENT and the following are Genji SQL literal tokens. IDENT // main NAMEDPARAM // $param @@ -266,16 +265,6 @@ var tokens = [...]string{ var keywords map[string]Token -func initKeywords() { - keywords = make(map[string]Token) - for tok := keywordBeg + 1; tok < keywordEnd; tok++ { - keywords[strings.ToLower(tokens[tok])] = tok - } - for _, tok := range []Token{AND, OR, TRUE, FALSE, NULL, IN, IS, LIKE} { - keywords[strings.ToLower(tokens[tok])] = tok - } -} - // String returns the string representation of the token. func (tok Token) String() string { if tok >= 0 && tok < Token(len(tokens)) { diff --git a/stream/iterator.go b/stream/iterator.go index 5bf766483..82e5a4132 100644 --- a/stream/iterator.go +++ b/stream/iterator.go @@ -483,11 +483,11 @@ func (r *Range) IsEqual(other *Range) bool { return false } - if r.rangeType != r.rangeType { + if r.rangeType != other.rangeType { return false } - if r.Exclusive != r.Exclusive { + if r.Exclusive != other.Exclusive { return false } diff --git a/stream/operator.go b/stream/operator.go index 7fd791ff6..0fea4d50e 100644 --- a/stream/operator.go +++ b/stream/operator.go @@ -408,7 +408,7 @@ func (op *TableInsertOperator) Iterate(in *expr.Environment, f func(out *expr.En } } - d, err := table.Insert(d) + _, err := table.Insert(d) if err != nil { return err } diff --git a/stream/operator_test.go b/stream/operator_test.go index a1d934e68..5726ac0be 100644 --- a/stream/operator_test.go +++ b/stream/operator_test.go @@ -688,7 +688,7 @@ func TestUnset(t *testing.T) { } for _, test := range tests { - t.Run(fmt.Sprintf("%s", test.path), func(t *testing.T) { + t.Run(test.path, func(t *testing.T) { s := stream.New(stream.Documents(test.in...)).Pipe(stream.Unset(test.path)) i := 0 err := s.Iterate(nil, func(out *expr.Environment) error { diff --git a/stream/project_test.go b/stream/project_test.go index 8fb3c2693..283b52344 100644 --- a/stream/project_test.go +++ b/stream/project_test.go @@ -1,7 +1,6 @@ package stream_test import ( - "fmt" "testing" "github.com/genjidb/genji/document" @@ -51,7 +50,7 @@ func TestProject(t *testing.T) { } for _, test := range tests { - t.Run(fmt.Sprintf("%s", test.name), func(t *testing.T) { + t.Run(test.name, func(t *testing.T) { var inEnv expr.Environment inEnv.SetDocument(test.in)