Update golangci-lint and turn it on in CI
This commit is contained in:
committed by
Sylwia Szunejko
parent
a9ab270196
commit
ab80d70106
17
.github/workflows/main.yml
vendored
17
.github/workflows/main.yml
vendored
@@ -17,7 +17,8 @@ jobs:
|
||||
steps:
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- name: Install Go 1.17
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
@@ -33,18 +34,14 @@ jobs:
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: Make Directory for GOBIN
|
||||
run: mkdir -p ${GOBIN}
|
||||
run: mkdir -p "${GOBIN}"
|
||||
|
||||
- name: Download Dependencies
|
||||
run: make get-deps
|
||||
|
||||
# - name: Lint
|
||||
# uses: golangci/golangci-lint-action@v3
|
||||
# with:
|
||||
# version: v1.45.2
|
||||
|
||||
- run: go vet ./...
|
||||
run: git --version && make get-deps && make get-tools
|
||||
|
||||
- name: Lint
|
||||
run: make check
|
||||
|
||||
- name: Run Scylla Container
|
||||
run: make run-scylla
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
14
Makefile
14
Makefile
@@ -28,6 +28,12 @@ fmt:
|
||||
check:
|
||||
@$(GOBIN)/golangci-lint run ./...
|
||||
|
||||
.PHONY: fix
|
||||
fix:
|
||||
@$(GOBIN)/golangci-lint run --fix ./...
|
||||
@fieldalignment -V=full >/dev/null 2>&1 || go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@v0.11.0
|
||||
@$(GOBIN)/fieldalignment -test=false -fix ./...
|
||||
|
||||
GOTEST := go test -cpu $(GOTEST_CPU) -count=1 -cover -race -tags all
|
||||
|
||||
.PHONY: test
|
||||
@@ -51,12 +57,12 @@ run-examples:
|
||||
run-scylla:
|
||||
@echo "==> Running test instance of Scylla $(SCYLLA_VERSION)"
|
||||
@docker pull scylladb/scylla:$(SCYLLA_VERSION)
|
||||
@docker run --name scylla -p 9042:9042 --cpuset-cpus=$(SCYLLA_CPU) --memory 1G --rm -d scylladb/scylla:$(SCYLLA_VERSION)
|
||||
@until docker exec scylla cqlsh -e "DESCRIBE SCHEMA"; do sleep 2; done
|
||||
@docker run --name gocqlx-scylla -p 9042:9042 --cpuset-cpus=$(SCYLLA_CPU) --memory 1G --rm -d scylladb/scylla:$(SCYLLA_VERSION)
|
||||
@until docker exec gocqlx-scylla cqlsh -e "DESCRIBE SCHEMA"; do sleep 2; done
|
||||
|
||||
.PHONY: stop-scylla
|
||||
stop-scylla:
|
||||
@docker stop scylla
|
||||
@docker stop gocqlx-scylla
|
||||
|
||||
.PHONY: get-deps
|
||||
get-deps:
|
||||
@@ -69,4 +75,4 @@ 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)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/gocql/gocql"
|
||||
)
|
||||
|
||||
// Batch is a wrapper around gocql.Batch
|
||||
type Batch struct {
|
||||
*gocql.Batch
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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_type,", "my_type"] ["my_other_type>", "my_other_type"]]
|
||||
var userTypes = regexp.MustCompile(`(?:<|\s)(\w+)(?:>|,)`) // match all types contained in set<X>, list<X>, tuple<A, B> etc.
|
||||
var userTypes = regexp.MustCompile(`(?:<|\s)(\w+)[>,]`) // match all types contained in set<X>, list<X>, tuple<A, B> 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 {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/gocql/gocql"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/scylladb/gocqlx/v2/gocqlxtest"
|
||||
)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -6,6 +6,7 @@ package gocqlx_test
|
||||
|
||||
import (
|
||||
"github.com/gocql/gocql"
|
||||
|
||||
"github.com/scylladb/gocqlx/v2"
|
||||
"github.com/scylladb/gocqlx/v2/qb"
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
5
go.sum
5
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=
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
15
iterx.go
15
iterx.go
@@ -19,17 +19,16 @@ 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
|
||||
|
||||
// Cache memory for a rows during iteration in structScan.
|
||||
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 +205,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 {
|
||||
|
||||
@@ -16,10 +16,11 @@ import (
|
||||
"github.com/gocql/gocql"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/scylladb/gocqlx/v2"
|
||||
. "github.com/scylladb/gocqlx/v2/gocqlxtest"
|
||||
"github.com/scylladb/gocqlx/v2/qb"
|
||||
"gopkg.in/inf.v0"
|
||||
|
||||
"github.com/scylladb/gocqlx/v2"
|
||||
"github.com/scylladb/gocqlx/v2/gocqlxtest"
|
||||
"github.com/scylladb/gocqlx/v2/qb"
|
||||
)
|
||||
|
||||
type FullName struct {
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -171,11 +172,11 @@ func TestMigrationCallback(t *testing.T) {
|
||||
migrate.Callback = func(ctx context.Context, session gocqlx.Session, ev migrate.CallbackEvent, name 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)
|
||||
|
||||
|
||||
16
qb/batch.go
16
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 {
|
||||
|
||||
@@ -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 ",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -19,9 +19,9 @@ import (
|
||||
type DeleteBuilder struct {
|
||||
table string
|
||||
columns columns
|
||||
using using
|
||||
where where
|
||||
_if _if
|
||||
using using
|
||||
exists bool
|
||||
}
|
||||
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
|
||||
12
qb/select.go
12
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 ",
|
||||
},
|
||||
}
|
||||
|
||||
11
queryx.go
11
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.
|
||||
@@ -151,7 +150,7 @@ func (q *Queryx) bindStructArgs(arg0 interface{}, arg1 map[string]interface{}) (
|
||||
|
||||
// grab the indirected value of arg
|
||||
v := reflect.ValueOf(arg0)
|
||||
for v = reflect.ValueOf(arg0); v.Kind() == reflect.Ptr; {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/scylladb/gocqlx/v2/qb"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user