From 4ec08b4b51e8b6c4932c6f3351fc73e13703685c Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Fri, 14 Jun 2024 13:07:21 -0400 Subject: [PATCH] Update golangci-lint and turn it on in CI --- .github/workflows/main.yml | 10 ++---- .golangci.yml | 62 ++++++++++++++++++++++++++------- Makefile | 8 ++++- batchx.go | 1 + batchx_test.go | 1 + benchmark_test.go | 18 +++++----- cmd/schemagen/map_types.go | 8 ++--- cmd/schemagen/schemagen.go | 10 +++--- cmd/schemagen/schemagen_test.go | 3 +- dbutil/rewrite_test.go | 6 ++-- doc_test.go | 1 + example_test.go | 57 +++++++++++++++++++++--------- go.sum | 5 --- gocqlxtest/gocqlxtest.go | 8 +++-- iterx.go | 17 ++++----- iterx_test.go | 32 +++++++++-------- migrate/example/cql/embed.go | 2 ++ migrate/example/example_test.go | 3 +- migrate/migrate.go | 9 +++-- migrate/migrate_test.go | 19 +++++----- qb/batch.go | 16 ++++----- qb/batch_test.go | 5 +-- qb/cmp.go | 4 +-- qb/cmp_test.go | 2 -- qb/delete.go | 2 +- qb/delete_test.go | 2 +- qb/insert.go | 4 +-- qb/insert_test.go | 7 ++-- qb/select.go | 12 +++---- qb/update.go | 2 +- qb/update_test.go | 2 +- qb/using.go | 6 ++-- qb/using_test.go | 12 +++---- queryx.go | 11 +++--- session.go | 3 +- table/table_test.go | 1 + udt.go | 2 +- 37 files changed, 222 insertions(+), 151 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ae31d0a..cf9e6df 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,13 +38,9 @@ jobs: - name: Download Dependencies run: make get-deps -# - name: Lint -# uses: golangci/golangci-lint-action@v3 -# with: -# version: v1.45.2 - - - run: go vet ./... - + - name: Lint + run: make check + - name: Run Scylla Container run: make run-scylla diff --git a/.golangci.yml b/.golangci.yml index d2a90a8..ec8009b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,23 @@ run: deadline: 5m - tests: false + tests: true + allow-parallel-runners: true + modules-download-mode: readonly + build-tags: [ all, integration ] linters-settings: + revive: + rules: + - name: package-comments + disabled: true + goimports: + local-prefixes: github.com/scylladb/gocqlx + gofumpt: + extra-rules: true + govet: + enable-all: true + disable: + - shadow errcheck: check-blank: true gocognit: @@ -23,22 +38,43 @@ linters-settings: line-length: 180 linters: - enable-all: true - disable: - - funlen - - gas - - gochecknoglobals - - gochecknoinits - - gomnd - - interfacer - - maligned - - nakedret - - prealloc - - wsl + disable-all: true + enable: + - errcheck + - gocritic + - gofumpt + - goheader + - goimports + - gosimple + - govet + - ineffassign + - lll + - misspell + - predeclared + - revive + - staticcheck + - thelper + - tparallel + - typecheck + - unused + - forbidigo issues: + new: true + new-from-rev: origin/master exclude-use-default: false exclude: - composite literal uses unkeyed fields - Error return value of `.+\.Close` is not checked - method Json should be JSON + exclude-rules: + - path: (.*_test.go|migrate/example|gocqlxtest/) + linters: + - fieldalignment + - govet + - errcheck + - path: doc_test.go + linters: + - unused + - revive + diff --git a/Makefile b/Makefile index ad6f721..a0785e3 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,11 @@ fmt: check: @$(GOBIN)/golangci-lint run ./... +.PHONY: fix +fix: + @$(GOBIN)/golangci-lint run --fix ./... + @$(GOBIN)/fieldalignment -fix -test false ./... + GOTEST := go test -cpu $(GOTEST_CPU) -count=1 -cover -race -tags all .PHONY: test @@ -69,4 +74,5 @@ endef .PHONY: get-tools get-tools: @echo "==> Installing tools at $(GOBIN)..." - @$(call dl_tgz,golangci-lint,https://github.com/golangci/golangci-lint/releases/download/v1.45.2/golangci-lint-v1.45.2-linux-amd64.tar.gz) + @$(call dl_tgz,golangci-lint,https://github.com/golangci/golangci-lint/releases/download/v1.59.1/golangci-lint-1.59.1-linux-amd64.tar.gz) + go install golang.org/x/tools@v0.9.3/go/analysis/passes/fieldalignment/cmd/fieldalignment \ No newline at end of file diff --git a/batchx.go b/batchx.go index 39825b6..6b504e7 100644 --- a/batchx.go +++ b/batchx.go @@ -4,6 +4,7 @@ import ( "github.com/gocql/gocql" ) +// Batch a batch operations. type Batch struct { *gocql.Batch } diff --git a/batchx_test.go b/batchx_test.go index 6c4705a..9e5f3dd 100644 --- a/batchx_test.go +++ b/batchx_test.go @@ -12,6 +12,7 @@ import ( "github.com/gocql/gocql" "github.com/google/go-cmp/cmp" + "github.com/scylladb/gocqlx/v2" "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/qb" diff --git a/benchmark_test.go b/benchmark_test.go index 21222e4..53d3ab7 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -13,7 +13,7 @@ import ( "testing" "github.com/scylladb/gocqlx/v2" - . "github.com/scylladb/gocqlx/v2/gocqlxtest" + "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/qb" ) @@ -46,7 +46,7 @@ var benchPersonCols = []string{"id", "first_name", "last_name", "email", "gender // BenchmarkBaseGocqlInsert performs standard insert. func BenchmarkBaseGocqlInsert(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() if err := session.ExecStmt(benchPersonSchema); err != nil { @@ -69,7 +69,7 @@ func BenchmarkBaseGocqlInsert(b *testing.B) { // BenchmarkGocqlInsert performs insert with struct binding. func BenchmarkGocqlxInsert(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() if err := session.ExecStmt(benchPersonSchema); err != nil { @@ -96,7 +96,7 @@ func BenchmarkGocqlxInsert(b *testing.B) { // BenchmarkBaseGocqlGet performs standard scan. func BenchmarkBaseGocqlGet(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() initTable(b, session, people) @@ -119,7 +119,7 @@ func BenchmarkBaseGocqlGet(b *testing.B) { // BenchmarkGocqlxGet performs get. func BenchmarkGocqlxGet(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() initTable(b, session, people) @@ -147,7 +147,7 @@ func BenchmarkGocqlxGet(b *testing.B) { // pointers. func BenchmarkBaseGocqlSelect(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() initTable(b, session, people) @@ -162,7 +162,7 @@ func BenchmarkBaseGocqlSelect(b *testing.B) { v := make([]*benchPerson, 100) p := new(benchPerson) for iter.Scan(&p.ID, &p.FirstName, &p.LastName, &p.Email, &p.Gender, &p.IPAddress) { - v = append(v, p) + v = append(v, p) // nolint:staticcheck p = new(benchPerson) } if err := iter.Close(); err != nil { @@ -174,7 +174,7 @@ func BenchmarkBaseGocqlSelect(b *testing.B) { // BenchmarkGocqlSelect performs select to a slice pointers. func BenchmarkGocqlxSelect(b *testing.B) { people := loadFixtures() - session := CreateSession(b) + session := gocqlxtest.CreateSession(b) defer session.Close() initTable(b, session, people) @@ -212,6 +212,8 @@ func loadFixtures() []*benchPerson { } func initTable(b *testing.B, session gocqlx.Session, people []*benchPerson) { + b.Helper() + if err := session.ExecStmt(benchPersonSchema); err != nil { b.Fatal(err) } diff --git a/cmd/schemagen/map_types.go b/cmd/schemagen/map_types.go index 4f59554..8c7c5f7 100644 --- a/cmd/schemagen/map_types.go +++ b/cmd/schemagen/map_types.go @@ -74,9 +74,9 @@ func mapScyllaToGoType(s string) string { typeStr := "struct {\n" for i, t := range types { - typeStr = typeStr + "\t\tField" + strconv.Itoa(i+1) + " " + mapScyllaToGoType(t) + "\n" + typeStr += "\t\tField" + strconv.Itoa(i+1) + " " + mapScyllaToGoType(t) + "\n" } - typeStr = typeStr + "\t}" + typeStr += "\t}" return typeStr } @@ -96,8 +96,8 @@ func typeToString(t interface{}) string { return t.(gocql.NativeType).String() case "gocql.CollectionType": collectionType := t.(gocql.CollectionType).String() - collectionType = strings.Replace(collectionType, "(", "<", -1) - collectionType = strings.Replace(collectionType, ")", ">", -1) + collectionType = strings.ReplaceAll(collectionType, "(", "<") + collectionType = strings.ReplaceAll(collectionType, ")", ">") return collectionType default: panic(fmt.Sprintf("Did not expect %v type in user defined type", tType)) diff --git a/cmd/schemagen/schemagen.go b/cmd/schemagen/schemagen.go index 85875c7..d64a017 100644 --- a/cmd/schemagen/schemagen.go +++ b/cmd/schemagen/schemagen.go @@ -15,6 +15,7 @@ import ( "strings" "github.com/gocql/gocql" + "github.com/scylladb/gocqlx/v2" _ "github.com/scylladb/gocqlx/v2/table" ) @@ -31,10 +32,8 @@ var ( flagIgnoreIndexes = cmd.Bool("ignore-indexes", false, "don't generate types for indexes") ) -var ( - //go:embed keyspace.tmpl - keyspaceTmpl string -) +//go:embed keyspace.tmpl +var keyspaceTmpl string func main() { err := cmd.Parse(os.Args[1:]) @@ -80,7 +79,6 @@ func renderTemplate(md *gocql.KeyspaceMetadata) ([]byte, error) { Funcs(template.FuncMap{"mapScyllaToGoType": mapScyllaToGoType}). Funcs(template.FuncMap{"typeToString": typeToString}). Parse(keyspaceTmpl) - if err != nil { log.Fatalln("unable to parse models template:", err) } @@ -169,7 +167,7 @@ func existsInSlice(s []string, v string) bool { // The second element contains the name of the type. // // [["", "my_other_type"]] -var userTypes = regexp.MustCompile(`(?:<|\s)(\w+)(?:>|,)`) // match all types contained in set, list, tuple etc. +var userTypes = regexp.MustCompile(`(?:<|\s)(\w+)[>,]`) // match all types contained in set, list, tuple etc. // usedInTables reports whether the typeName is used in any of columns of the provided tables. func usedInTables(typeName string, tables map[string]*gocql.TableMetadata) bool { diff --git a/cmd/schemagen/schemagen_test.go b/cmd/schemagen/schemagen_test.go index 44c5925..19baccd 100644 --- a/cmd/schemagen/schemagen_test.go +++ b/cmd/schemagen/schemagen_test.go @@ -10,6 +10,7 @@ import ( "github.com/gocql/gocql" "github.com/google/go-cmp/cmp" + "github.com/scylladb/gocqlx/v2/gocqlxtest" ) @@ -105,7 +106,7 @@ func Test_usedInTables(t *testing.T) { }) } - t.Run("doesn't panic with empty type name", func(t *testing.T) { + t.Run("doesn't panic with empty type name", func(_ *testing.T) { tables := map[string]*gocql.TableMetadata{ "table": {Columns: map[string]*gocql.ColumnMetadata{ "column": {Validator: "map"}, diff --git a/dbutil/rewrite_test.go b/dbutil/rewrite_test.go index 1132b5f..a72ff29 100644 --- a/dbutil/rewrite_test.go +++ b/dbutil/rewrite_test.go @@ -12,13 +12,13 @@ import ( "time" "github.com/scylladb/gocqlx/v2/dbutil" - . "github.com/scylladb/gocqlx/v2/gocqlxtest" + "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/qb" "github.com/scylladb/gocqlx/v2/table" ) func TestRewriteTableTTL(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.rewrite_table (testtext text PRIMARY KEY)`); err != nil { @@ -61,7 +61,7 @@ func TestRewriteTableTTL(t *testing.T) { } func TestRewriteTableClone(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.rewrite_table_clone_src (testtext text PRIMARY KEY, testint int)`); err != nil { diff --git a/doc_test.go b/doc_test.go index 64d3850..7318aba 100644 --- a/doc_test.go +++ b/doc_test.go @@ -6,6 +6,7 @@ package gocqlx_test import ( "github.com/gocql/gocql" + "github.com/scylladb/gocqlx/v2" "github.com/scylladb/gocqlx/v2/qb" ) diff --git a/example_test.go b/example_test.go index fe22c5f..33f3108 100644 --- a/example_test.go +++ b/example_test.go @@ -14,12 +14,13 @@ import ( "time" "github.com/gocql/gocql" + "golang.org/x/sync/errgroup" + "gopkg.in/inf.v0" + "github.com/scylladb/gocqlx/v2" "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/qb" "github.com/scylladb/gocqlx/v2/table" - "golang.org/x/sync/errgroup" - "gopkg.in/inf.v0" ) // Running examples locally: @@ -43,7 +44,7 @@ func TestExample(t *testing.T) { datatypesBlob(t, session) datatypesUserDefinedType(t, session) datatypesUserDefinedTypeWrapper(t, session) - datatypesJson(t, session) + datatypesJSON(t, session) pagingForwardPaging(t, session) pagingEfficientFullTableScan(t, session) @@ -73,6 +74,8 @@ type PlaylistItem struct { // queries. It uses "BindStruct" function for parameter binding and "Select" // function for loading data to a slice. func basicCreateAndPopulateKeyspace(t *testing.T, session gocqlx.Session, keyspace string) { + t.Helper() + err := session.ExecStmt(fmt.Sprintf( `CREATE KEYSPACE IF NOT EXISTS %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`, keyspace, @@ -162,6 +165,8 @@ func basicCreateAndPopulateKeyspace(t *testing.T, session gocqlx.Session, keyspa // queries with all types. It uses "BindStruct" function for parameter binding and "Select" // function for loading data to a slice. func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -178,7 +183,7 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { DoublE float64 DuratioN gocql.Duration FloaT float32 - Id [16]byte + ID [16]byte InT int32 IneT string ListInt []int32 @@ -256,14 +261,16 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { // Insert song using query builder. insertCheckTypes := qb.Insert("examples.check_types"). - Columns("asci_i", "big_int", "blo_b", "boolea_n", "dat_e", "decima_l", "doubl_e", "duratio_n", "floa_t", "ine_t", "in_t", "small_int", "tex_t", "tim_e", "timestam_p", "timeuui_d", "tiny_int", "id", "var_char", "var_int", "map_int_text", "list_int", "set_int").Query(session) + Columns("asci_i", "big_int", "blo_b", "boolea_n", "dat_e", "decima_l", "doubl_e", "duratio_n", "floa_t", + "ine_t", "in_t", "small_int", "tex_t", "tim_e", "timestam_p", "timeuui_d", "tiny_int", "id", "var_char", + "var_int", "map_int_text", "list_int", "set_int").Query(session) - var byteId [16]byte + var byteID [16]byte id := []byte("756716f7-2e54-4715-9f00-91dcbea6cf50") - copy(byteId[:], id) + copy(byteID[:], id) date := time.Date(2021, time.December, 11, 10, 23, 0, 0, time.UTC) - var double float64 = 1.2 + var double float64 = 1.2 // nolint:revive var float float32 = 1.3 var integer int32 = 123 listInt := []int32{1, 2, 3} @@ -286,7 +293,7 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { DoublE: double, DuratioN: gocql.Duration{Months: 1, Days: 1, Nanoseconds: 86400}, FloaT: float, - Id: byteId, + ID: byteID, InT: integer, IneT: "127.0.0.1", ListInt: listInt, @@ -309,7 +316,7 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { queryCheckTypes := checkTypesTable.SelectQuery(session) queryCheckTypes.BindStruct(&CheckTypesStruct{ - Id: byteId, + ID: byteID, }) var items []*CheckTypesStruct @@ -325,6 +332,8 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) { // This example shows how to load a single value using "Get" function. // Get can also work with UDTs and types that implement gocql marshalling functions. func basicReadScyllaVersion(t *testing.T, session gocqlx.Session) { + t.Helper() + var releaseVersion string err := session.Query("SELECT release_version FROM system.local", nil).Get(&releaseVersion) @@ -340,6 +349,8 @@ func basicReadScyllaVersion(t *testing.T, session gocqlx.Session) { // to handle situations where driver returns more coluns that we are ready to // consume. func datatypesBlob(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -392,6 +403,8 @@ type Coordinates struct { // This example shows how to add User Defined Type marshalling capabilities by // adding a single line - embedding gocqlx.UDT. func datatypesUserDefinedType(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -446,6 +459,8 @@ type coordinates struct { // types that we cannot modify, like library or transfer objects, without // rewriting them in runtime. func datatypesUserDefinedTypeWrapper(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -501,7 +516,9 @@ func datatypesUserDefinedTypeWrapper(t *testing.T, session gocqlx.Session) { } // This example shows how to use query builder to work with -func datatypesJson(t *testing.T, session gocqlx.Session) { +func datatypesJSON(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -524,17 +541,17 @@ func datatypesJson(t *testing.T, session gocqlx.Session) { } // fromJson lets you provide individual columns as JSON: - insertFromJson := qb.Insert("examples.querybuilder_json"). + insertFromJSON := qb.Insert("examples.querybuilder_json"). Columns("id", "name"). FuncColumn("specs", qb.Fn("fromJson", "json")). Query(session) - insertFromJson.BindMap(qb.M{ + insertFromJSON.BindMap(qb.M{ "id": 3, "name": "Screen", "json": `{ "size": "24-inch" }`, }) - if err := insertFromJson.Exec(); err != nil { + if err := insertFromJSON.Exec(); err != nil { t.Fatal("Exec() failed:", err) } @@ -559,12 +576,12 @@ func datatypesJson(t *testing.T, session gocqlx.Session) { row := &struct { ID int - JsonSpecs string + JSONSpecs string }{} if err := q.Get(row); err != nil { t.Fatal("Get() failed:", err) } - t.Logf("Entry #%d's specs as JSON: %s", row.ID, row.JsonSpecs) + t.Logf("Entry #%d's specs as JSON: %s", row.ID, row.JSONSpecs) } type Video struct { @@ -600,6 +617,8 @@ func pagingFillTable(t *testing.T, insert *gocqlx.Queryx) { // This example shows how to use stateful paging and how "Select" function // can be used to fetch single page only. func pagingForwardPaging(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -669,6 +688,8 @@ func pagingForwardPaging(t *testing.T, session gocqlx.Session) { // // [1] https://www.scylladb.com/2017/02/13/efficient-full-table-scans-with-scylla-1-6/. func pagingEfficientFullTableScan(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -779,6 +800,8 @@ func pagingEfficientFullTableScan(t *testing.T, session gocqlx.Session) { // Compare-And-Set (CAS) functions. // See: https://docs.scylladb.com/using-scylla/lwt/ for more details. func lwtLock(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) @@ -878,6 +901,8 @@ func lwtLock(t *testing.T, session gocqlx.Session) { // This example shows how to reuse the same insert statement with // partially filled parameters without generating tombstones for empty columns. func unsetEmptyValues(t *testing.T, session gocqlx.Session) { + t.Helper() + err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`) if err != nil { t.Fatal("create keyspace:", err) diff --git a/go.sum b/go.sum index 00894b5..13ad649 100644 --- a/go.sum +++ b/go.sum @@ -3,13 +3,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCS github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gocql/gocql v0.0.0-20200131111108-92af2e088537 h1:NaMut1fdw76YYX/TPinSAbai4DShF5tPort3bHpET6g= -github.com/gocql/gocql v0.0.0-20200131111108-92af2e088537/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1 h1:px9qUCy/RNJNsfCam4m2IxWGxNuimkrioEF0vrrbPsg= github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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= diff --git a/gocqlxtest/gocqlxtest.go b/gocqlxtest/gocqlxtest.go index 6272d59..11f3512 100644 --- a/gocqlxtest/gocqlxtest.go +++ b/gocqlxtest/gocqlxtest.go @@ -13,6 +13,7 @@ import ( "time" "github.com/gocql/gocql" + "github.com/scylladb/gocqlx/v2" ) @@ -31,8 +32,10 @@ var initOnce sync.Once // CreateSession creates a new gocqlx session from flags. func CreateSession(tb testing.TB) gocqlx.Session { + tb.Helper() + cluster := CreateCluster() - return createSessionFromCluster(cluster, tb) + return createSessionFromCluster(tb, cluster) } // CreateCluster creates gocql ClusterConfig from flags. @@ -92,7 +95,8 @@ func CreateKeyspace(cluster *gocql.ClusterConfig, keyspace string) error { return nil } -func createSessionFromCluster(cluster *gocql.ClusterConfig, tb testing.TB) gocqlx.Session { +func createSessionFromCluster(tb testing.TB, cluster *gocql.ClusterConfig) gocqlx.Session { + tb.Helper() if !flag.Parsed() { flag.Parse() } diff --git a/iterx.go b/iterx.go index 54f37dd..eaa30b7 100644 --- a/iterx.go +++ b/iterx.go @@ -19,17 +19,14 @@ var DefaultUnsafe bool // Iterx is a wrapper around gocql.Iter which adds struct scanning capabilities. type Iterx struct { + err error *gocql.Iter - Mapper *reflectx.Mapper - + Mapper *reflectx.Mapper + fields [][]int + values []interface{} unsafe bool structOnly bool applied bool - err error - - // Cache memory for a rows during iteration in structScan. - fields [][]int - values []interface{} } // Unsafe forces the iterator to ignore missing fields. By default when scanning @@ -206,9 +203,9 @@ func (iter *Iterx) scanAll(dest interface{}) bool { // isScannable takes the reflect.Type and the actual dest value and returns // whether or not it's Scannable. t is scannable if: -// * ptr to t implements gocql.Unmarshaler, gocql.UDTUnmarshaler or UDT -// * it is not a struct -// * it has no exported fields +// - ptr to t implements gocql.Unmarshaler, gocql.UDTUnmarshaler or UDT +// - it is not a struct +// - it has no exported fields func (iter *Iterx) isScannable(t reflect.Type) bool { ptr := reflect.PtrTo(t) switch { diff --git a/iterx_test.go b/iterx_test.go index 2a1304f..ca68ce8 100644 --- a/iterx_test.go +++ b/iterx_test.go @@ -16,10 +16,11 @@ import ( "github.com/gocql/gocql" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "gopkg.in/inf.v0" + "github.com/scylladb/gocqlx/v2" - . "github.com/scylladb/gocqlx/v2/gocqlxtest" + "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/qb" - "gopkg.in/inf.v0" ) type FullName struct { @@ -27,11 +28,11 @@ type FullName struct { LastName string } -func (n FullName) MarshalCQL(info gocql.TypeInfo) ([]byte, error) { +func (n FullName) MarshalCQL(_ gocql.TypeInfo) ([]byte, error) { return []byte(n.FirstName + " " + n.LastName), nil } -func (n *FullName) UnmarshalCQL(info gocql.TypeInfo, data []byte) error { +func (n *FullName) UnmarshalCQL(_ gocql.TypeInfo, data []byte) error { t := strings.SplitN(string(data), " ", 2) n.FirstName, n.LastName = t[0], t[1] return nil @@ -48,7 +49,7 @@ type FullNamePtrUDT struct { } func TestIterxStruct(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TYPE gocqlx_test.FullName (first_Name text, last_name text)`); err != nil { @@ -125,7 +126,10 @@ func TestIterxStruct(t *testing.T) { Testptrudt: FullNamePtrUDT{FullName: &FullName{FirstName: "John", LastName: "Doe"}}, } - const insertStmt = `INSERT INTO struct_table (testuuid, testtimestamp, testvarchar, testbigint, testblob, testbool, testfloat,testdouble, testint, testdecimal, testlist, testset, testmap, testvarint, testinet, testcustom, testudt, testptrudt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` + const insertStmt = `INSERT INTO struct_table ( + testuuid, testtimestamp, testvarchar, testbigint, testblob, testbool, testfloat, testdouble, + testint, testdecimal, testlist, testset, testmap, testvarint, testinet, testcustom, testudt, testptrudt + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` if err := session.Query(insertStmt, nil).Bind( m.Testuuid, @@ -212,7 +216,7 @@ func TestIterxStruct(t *testing.T) { } func TestIterxScannable(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.scannable_table (testfullname text PRIMARY KEY)`); err != nil { @@ -265,7 +269,7 @@ func TestIterxScannable(t *testing.T) { } func TestIterxStructOnly(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.struct_only_table (first_name text, last_name text, PRIMARY KEY (first_name, last_name))`); err != nil { @@ -336,7 +340,7 @@ func TestIterxStructOnly(t *testing.T) { } func TestIterxStructOnlyUDT(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.struct_only_udt_table (first_name text, last_name text, PRIMARY KEY (first_name, last_name))`); err != nil { @@ -412,7 +416,7 @@ func TestIterxStructOnlyUDT(t *testing.T) { } func TestIterxUnsafe(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.unsafe_table (testtext text PRIMARY KEY, testtextunbound text)`); err != nil { @@ -499,7 +503,7 @@ func TestIterxUnsafe(t *testing.T) { } func TestIterxNotFound(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.not_found_table (testtext text PRIMARY KEY)`); err != nil { @@ -547,7 +551,7 @@ func TestIterxNotFound(t *testing.T) { } func TestIterxErrorOnNil(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.nil_table (testtext text PRIMARY KEY)`); err != nil { @@ -582,7 +586,7 @@ func TestIterxErrorOnNil(t *testing.T) { } func TestIterxPaging(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() if err := session.ExecStmt(`CREATE TABLE gocqlx_test.paging_table (id int PRIMARY KEY, val int)`); err != nil { @@ -625,7 +629,7 @@ func TestIterxPaging(t *testing.T) { } func TestIterxCAS(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() const ( diff --git a/migrate/example/cql/embed.go b/migrate/example/cql/embed.go index 32eb68a..b4858cb 100644 --- a/migrate/example/cql/embed.go +++ b/migrate/example/cql/embed.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a ALv2-style // license that can be found in the LICENSE file. +//go:build all || integration // +build all integration package cql @@ -9,5 +10,6 @@ package cql import "embed" // Files contains *.cql schema migration files. +// //go:embed *.cql var Files embed.FS diff --git a/migrate/example/example_test.go b/migrate/example/example_test.go index 26930bc..f6c23f2 100644 --- a/migrate/example/example_test.go +++ b/migrate/example/example_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a ALv2-style // license that can be found in the LICENSE file. +//go:build all || integration // +build all integration package example @@ -37,7 +38,7 @@ func TestExample(t *testing.T) { defer session.Close() // Add callback prints - log := func(ctx context.Context, session gocqlx.Session, ev migrate.CallbackEvent, name string) error { + log := func(_ context.Context, _ gocqlx.Session, ev migrate.CallbackEvent, name string) error { t.Log(ev, name) return nil } diff --git a/migrate/migrate.go b/migrate/migrate.go index 077ffff..bd2da27 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -7,7 +7,6 @@ package migrate import ( "bytes" "context" - "errors" "fmt" "io" "io/fs" @@ -20,6 +19,7 @@ import ( "time" "github.com/gocql/gocql" + "github.com/scylladb/gocqlx/v2" "github.com/scylladb/gocqlx/v2/qb" ) @@ -58,11 +58,11 @@ const ( // Info contains information on migration applied on a database. type Info struct { + StartTime time.Time + EndTime time.Time Name string Checksum string Done int - StartTime time.Time - EndTime time.Time } // List provides a listing of applied migrations. @@ -128,8 +128,7 @@ func FromFS(ctx context.Context, session gocqlx.Session, f fs.FS) error { for i := 0; i < len(dbm); i++ { if dbm[i].Name != fm[i] { - fmt.Println(dbm[i].Name, fm[i], i) - return errors.New("inconsistent migrations") + return fmt.Errorf("inconsistent migrations found, expected %q got %q at %d", fm[i], dbm[i].Name, i) } c, err := fileChecksum(f, fm[i]) if err != nil { diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index f44ad05..1fa02ae 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -15,8 +15,9 @@ import ( "testing" "github.com/psanford/memfs" + "github.com/scylladb/gocqlx/v2" - . "github.com/scylladb/gocqlx/v2/gocqlxtest" + "github.com/scylladb/gocqlx/v2/gocqlxtest" "github.com/scylladb/gocqlx/v2/migrate" ) @@ -45,7 +46,7 @@ func recreateTables(tb testing.TB, session gocqlx.Session) { } func TestMigration(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() recreateTables(t, session) @@ -91,7 +92,7 @@ func TestMigration(t *testing.T) { } func TestMigrationNoSemicolon(t *testing.T) { - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() recreateTables(t, session) @@ -168,14 +169,14 @@ func TestMigrationCallback(t *testing.T) { afterCalled int inCalled int ) - migrate.Callback = func(ctx context.Context, session gocqlx.Session, ev migrate.CallbackEvent, name string) error { + migrate.Callback = func(_ context.Context, _ gocqlx.Session, ev migrate.CallbackEvent, _ string) error { switch ev { case migrate.BeforeMigration: - beforeCalled += 1 + beforeCalled++ case migrate.AfterMigration: - afterCalled += 1 + afterCalled++ case migrate.CallComment: - inCalled += 1 + inCalled++ } return nil } @@ -191,6 +192,8 @@ func TestMigrationCallback(t *testing.T) { } assertCallbacks := func(t *testing.T, before, afer, in int) { + t.Helper() + if beforeCalled != before { t.Fatalf("expected %d before calls got %d", before, beforeCalled) } @@ -202,7 +205,7 @@ func TestMigrationCallback(t *testing.T) { } } - session := CreateSession(t) + session := gocqlxtest.CreateSession(t) defer session.Close() recreateTables(t, session) diff --git a/qb/batch.go b/qb/batch.go index 597c4e1..3556634 100644 --- a/qb/batch.go +++ b/qb/batch.go @@ -18,21 +18,21 @@ import ( // BatchBuilder builds CQL BATCH statements. type BatchBuilder struct { - unlogged bool - counter bool - using using stmts []string names []string + using using + unlogged bool + counter bool } // Batch returns a new BatchBuilder. // BatchBuilder encapsulates batch cqls as one ordinary gocql.Query for convenience. // Below are the limitations of encapsulating batch cqls based on gocql.Query instead of gocql.Batch: -// * gocql.Batch has some more batch specific check, such as BatchSize(65535). -// * gocql.Batch use BatchObserver instead of QueryObserver. -// * gocql.Batch has cancelBatch call back. -// * gocql.Batch prepares the included statements separately, which is more efficient. -// In contrast, gocqlx.qb.BatchBuilder, which is based on gocql.Query, prepares the whole batch statements as one ordinary query. +// - gocql.Batch has some more batch specific check, such as BatchSize(65535). +// - gocql.Batch use BatchObserver instead of QueryObserver. +// - gocql.Batch has cancelBatch call back. +// - gocql.Batch prepares the included statements separately, which is more efficient. +// In contrast, gocqlx.qb.BatchBuilder, which is based on gocql.Query, prepares the whole batch statements as one ordinary query. // // Deprecated: Please use gocql.Session.NewBatch() instead. func Batch() *BatchBuilder { diff --git a/qb/batch_test.go b/qb/batch_test.go index 027bfc7..9e16fb4 100644 --- a/qb/batch_test.go +++ b/qb/batch_test.go @@ -39,7 +39,8 @@ func TestBatchBuilder(t *testing.T) { B: Batch(). AddWithPrefix("a", m). AddWithPrefix("b", m), - S: "BEGIN BATCH INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) ; INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) ; APPLY BATCH ", + S: `BEGIN BATCH INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) ; + INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) ; APPLY BATCH `, N: []string{"a.id", "a.user_uuid", "a.firstname", "b.id", "b.user_uuid", "b.firstname"}, }, // Add UNLOGGED @@ -64,7 +65,7 @@ func TestBatchBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Batch().Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Batch().Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "BEGIN BATCH USING TIMESTAMP 1115251200000000 APPLY BATCH ", }, { diff --git a/qb/cmp.go b/qb/cmp.go index a611167..821fab0 100644 --- a/qb/cmp.go +++ b/qb/cmp.go @@ -26,9 +26,9 @@ const ( // Cmp if a filtering comparator that is used in WHERE and IF clauses. type Cmp struct { - op op - column string value value + column string + op op } func (c Cmp) writeCql(cql *bytes.Buffer) (names []string) { diff --git a/qb/cmp_test.go b/qb/cmp_test.go index d39bc29..8375368 100644 --- a/qb/cmp_test.go +++ b/qb/cmp_test.go @@ -165,8 +165,6 @@ func TestCmp(t *testing.T) { S: "like LIKE (?,?)", N: []string{"name[0]", "name[1]"}, }, - - // Custom bind names on tuples { C: EqTupleNamed("eq", 2, "name"), diff --git a/qb/delete.go b/qb/delete.go index 1c52432..a1ff3b9 100644 --- a/qb/delete.go +++ b/qb/delete.go @@ -19,9 +19,9 @@ import ( type DeleteBuilder struct { table string columns columns - using using where where _if _if + using using exists bool } diff --git a/qb/delete_test.go b/qb/delete_test.go index fd99b8a..b524b71 100644 --- a/qb/delete_test.go +++ b/qb/delete_test.go @@ -69,7 +69,7 @@ func TestDeleteBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Delete("cycling.cyclist_name").Where(w).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Delete("cycling.cyclist_name").Where(w).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "DELETE FROM cycling.cyclist_name USING TIMESTAMP 1115251200000000 WHERE id=? ", N: []string{"expr"}, }, diff --git a/qb/insert.go b/qb/insert.go index 86b4a66..25923f1 100644 --- a/qb/insert.go +++ b/qb/insert.go @@ -17,16 +17,16 @@ import ( // initializer specifies an value for a column in an insert operation. type initializer struct { - column string value value + column string } // InsertBuilder builds CQL INSERT statements. type InsertBuilder struct { table string columns []initializer - unique bool using using + unique bool json bool } diff --git a/qb/insert_test.go b/qb/insert_test.go index 5ea3b4e..9193c96 100644 --- a/qb/insert_test.go +++ b/qb/insert_test.go @@ -17,7 +17,6 @@ func TestInsertBuilder(t *testing.T) { N []string S string }{ - // Basic test for insert { B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname"), @@ -67,7 +66,7 @@ func TestInsertBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP 1115251200000000 ", N: []string{"id", "user_uuid", "firstname"}, }, @@ -78,7 +77,7 @@ func TestInsertBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP 1115251200000000 ", N: []string{"id", "user_uuid", "firstname"}, }, @@ -89,7 +88,7 @@ func TestInsertBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP 1115251200000000 ", N: []string{"id", "user_uuid", "firstname"}, }, diff --git a/qb/select.go b/qb/select.go index afadc04..7964164 100644 --- a/qb/select.go +++ b/qb/select.go @@ -34,15 +34,15 @@ func (o Order) String() string { // SelectBuilder builds CQL SELECT statements. type SelectBuilder struct { + limit limit + limitPerPartition limit table string - columns columns - distinct columns - using using where where groupBy columns orderBy columns - limit limit - limitPerPartition limit + columns columns + distinct columns + using using allowFiltering bool bypassCache bool json bool @@ -132,7 +132,7 @@ func (b *SelectBuilder) From(table string) *SelectBuilder { } // Json sets the clause of the query. -func (b *SelectBuilder) Json() *SelectBuilder { +func (b *SelectBuilder) Json() *SelectBuilder { // nolint: revive b.json = true return b } diff --git a/qb/update.go b/qb/update.go index 1537a90..1826199 100644 --- a/qb/update.go +++ b/qb/update.go @@ -32,10 +32,10 @@ func (a assignment) writeCql(cql *bytes.Buffer) (names []string) { // UpdateBuilder builds CQL UPDATE statements. type UpdateBuilder struct { table string - using using assignments []assignment where where _if _if + using using exists bool } diff --git a/qb/update_test.go b/qb/update_test.go index 0a9160b..13bb742 100644 --- a/qb/update_test.go +++ b/qb/update_test.go @@ -117,7 +117,7 @@ func TestUpdateBuilder(t *testing.T) { }, // Add TIMESTAMP { - B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "UPDATE cycling.cyclist_name USING TIMESTAMP 1115251200000000 SET id=?,user_uuid=?,firstname=? WHERE id=? ", N: []string{"id", "user_uuid", "firstname", "expr"}, }, diff --git a/qb/using.go b/qb/using.go index 477af32..7e4cbe0 100644 --- a/qb/using.go +++ b/qb/using.go @@ -21,12 +21,12 @@ func Timestamp(t time.Time) int64 { } type using struct { - ttl int64 ttlName string - timestamp int64 timestampName string - timeout time.Duration timeoutName string + ttl int64 + timestamp int64 + timeout time.Duration } func (u *using) TTL(d time.Duration) *using { diff --git a/qb/using_test.go b/qb/using_test.go index 60cbdc2..fe856b1 100644 --- a/qb/using_test.go +++ b/qb/using_test.go @@ -43,7 +43,7 @@ func TestUsing(t *testing.T) { }, // Timestamp { - B: new(using).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: new(using).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "USING TIMESTAMP 1115251200000000 ", }, // TimestampNamed @@ -65,7 +65,7 @@ func TestUsing(t *testing.T) { }, // TTL Timestamp { - B: new(using).TTL(time.Second).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: new(using).TTL(time.Second).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "USING TTL 1 AND TIMESTAMP 1115251200000000 ", }, // TTL TimestampNamed @@ -82,7 +82,7 @@ func TestUsing(t *testing.T) { }, // TTLNamed Timestamp { - B: new(using).TTLNamed("ttl").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: new(using).TTLNamed("ttl").Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "USING TTL ? AND TIMESTAMP 1115251200000000 ", N: []string{"ttl"}, }, @@ -99,7 +99,7 @@ func TestUsing(t *testing.T) { }, // TTL Timestamp Timeout { - B: new(using).TTL(time.Second).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)).Timeout(time.Second), + B: new(using).TTL(time.Second).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)).Timeout(time.Second), S: "USING TTL 1 AND TIMESTAMP 1115251200000000 AND TIMEOUT 1s ", }, // TTL with no duration @@ -129,13 +129,13 @@ func TestUsing(t *testing.T) { }, // Timestamp TimestampNamed { - B: new(using).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)).TimestampNamed("ts"), + B: new(using).Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)).TimestampNamed("ts"), S: "USING TIMESTAMP ? ", N: []string{"ts"}, }, // TimestampNamed Timestamp { - B: new(using).TimestampNamed("ts").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)), + B: new(using).TimestampNamed("ts").Timestamp(time.Date(2005, 5, 5, 0, 0, 0, 0, time.UTC)), S: "USING TIMESTAMP 1115251200000000 ", }, } diff --git a/queryx.go b/queryx.go index 36e8acc..c4faa90 100644 --- a/queryx.go +++ b/queryx.go @@ -90,12 +90,11 @@ func allowedBindRune(b byte) bool { // Queryx is a wrapper around gocql.Query which adds struct binding capabilities. type Queryx struct { - *gocql.Query - Names []string + err error + tr Transformer Mapper *reflectx.Mapper - - tr Transformer - err error + *gocql.Query + Names []string } // Query creates a new Queryx from gocql.Query using a default mapper. @@ -150,7 +149,7 @@ func (q *Queryx) bindStructArgs(arg0 interface{}, arg1 map[string]interface{}) ( arglist := make([]interface{}, 0, len(q.Names)) // grab the indirected value of arg - v := reflect.ValueOf(arg0) + var v reflect.Value for v = reflect.ValueOf(arg0); v.Kind() == reflect.Ptr; { v = v.Elem() } diff --git a/session.go b/session.go index 608a3ae..aef880a 100644 --- a/session.go +++ b/session.go @@ -34,7 +34,8 @@ func NewSession(session *gocql.Session) Session { // the created session to gocqlx.Session. // // Example: -// session, err := gocqlx.WrapSession(cluster.CreateSession()) +// +// session, err := gocqlx.WrapSession(cluster.CreateSession()) func WrapSession(session *gocql.Session, err error) (Session, error) { return Session{ Session: session, diff --git a/table/table_test.go b/table/table_test.go index 32871de..c69a86f 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/scylladb/gocqlx/v2/qb" ) diff --git a/udt.go b/udt.go index e17ac06..1da938e 100644 --- a/udt.go +++ b/udt.go @@ -24,8 +24,8 @@ var ( ) type udt struct { - value reflect.Value field map[string]reflect.Value + value reflect.Value unsafe bool }