Compare commits

..

10 Commits

Author SHA1 Message Date
renovate[bot]
d9ec9f889d chore(deps): update module github.com/scylladb/gocql to v1.17.0 (#357)
Some checks failed
Build / Build (push) Has been cancelled
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-12 20:55:31 -04:00
renovate[bot]
b5ec0d955f fix(deps): update module golang.org/x/sync to v0.18.0 (#356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-09 01:14:58 -04:00
Dmitry Kropachev
38001d64ac Update gocql version to v1.16.1 (#353)
* Update gocql version to v1.16.1

1. Update gocql to v1.16.1
2. Update golang to 1.25, since new gocql version requres it

* Update golangci to 2.5.0

It is needed since 1.64.8 does not support golang 1.25.
1. Update golangci to 2.5.0
2. Migrate from golangci config v1 to v2
3. Integrate fieldaligment to golangci
4. Drop fieldaligment from Makefile
5. Address complaints
2025-10-28 14:52:22 -04:00
Dmitry Kropachev
96f0b49bdd Update golang to 1.24.x and dependencies (#349) 2025-10-16 14:25:19 -04:00
Dmitry Kropachev
20fef0caf4 Make renovate to maintain only 2 PRs 2025-10-16 13:30:07 -04:00
Dmitry Kropachev
ce13945e3f Update README.md (#347)
* Update README.md

1. Remove test code, replace it with production code, t.Log -> log.
2. Add import part
3. Add gocqlx instalation step

* Fix typo in installation instructions
2025-09-17 07:41:11 -04:00
renovate[bot]
acb61eb06f fix(deps): update module github.com/scylladb/gocqlx/v3 to v3.0.4 (#345)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 22:48:29 -04:00
Dmitry Kropachev
cdd1c07b35 Add claude files to .gitignore 2025-09-16 22:34:31 -04:00
Dmitry Kropachev
2dd6668d11 Add renovate.json 2025-09-16 22:34:11 -04:00
Fuad Hasan
101d498909 Add comment handling and related tests for migration functionality (#344) 2025-09-13 10:04:04 -04:00
25 changed files with 319 additions and 251 deletions

View File

@@ -29,10 +29,10 @@ jobs:
with: with:
fetch-depth: '0' fetch-depth: '0'
- name: Install Go 1.20 - name: Install Go 1.25
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: "1.20" go-version: 1.25
- name: Cache Dependencies - name: Cache Dependencies
uses: actions/cache@v4 uses: actions/cache@v4

4
.gitignore vendored
View File

@@ -17,3 +17,7 @@ vendor
cmd/schemagen/schemagen cmd/schemagen/schemagen
cmd/schemagen/testdata/go.sum cmd/schemagen/testdata/go.sum
# Claude / AI assistant metadata
CLAUDE.md
.claude/

View File

@@ -1,25 +1,54 @@
run: version: "2"
deadline: 5m
tests: true
allow-parallel-runners: true
modules-download-mode: readonly
build-tags: [ all, integration ]
linters-settings: formatters:
enable:
- goimports
settings:
goimports:
local-prefixes:
- github.com/scylladb/gocqlx
golines:
max-len: 120
gofumpt:
extra-rules: true
linters:
exclusions:
rules:
- path: '(.+)_test\.go'
text: "fieldalignment"
linters:
- govet
default: none
enable:
- nolintlint
- errcheck
- gocritic
- goheader
- govet
- ineffassign
- lll
- misspell
- predeclared
- revive
- staticcheck
- thelper
- tparallel
- unused
- forbidigo
settings:
revive: revive:
rules: rules:
- name: package-comments - name: package-comments
disabled: true disabled: true
goimports:
local-prefixes: github.com/scylladb/gocqlx
gofumpt:
extra-rules: true
govet: govet:
enable-all: true enable-all: true
disable: disable:
- shadow - shadow
errcheck: errcheck:
check-blank: true check-blank: false
gocognit: gocognit:
min-complexity: 50 min-complexity: 50
gocritic: gocritic:
@@ -36,45 +65,12 @@ linters-settings:
- whyNoLint - whyNoLint
lll: lll:
line-length: 180 line-length: 180
nolintlint:
allow-no-explanation: [ golines ]
require-explanation: true
require-specific: true
linters: run:
disable-all: true build-tags:
enable: - integration
- errcheck - all
- 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

View File

@@ -24,8 +24,7 @@ export PATH := $(GOBIN):$(PATH)
GOOS := $(shell uname | tr '[:upper:]' '[:lower:]') GOOS := $(shell uname | tr '[:upper:]' '[:lower:]')
GOARCH := $(shell go env GOARCH) GOARCH := $(shell go env GOARCH)
GOLANGCI_VERSION := 1.64.8 GOLANGCI_VERSION := 2.5.0
FIELDALIGNMENT_VERSION := 0.24.0
ifeq ($(GOARCH),arm64) ifeq ($(GOARCH),arm64)
GOLANGCI_DOWNLOAD_URL := "https://github.com/golangci/golangci-lint/releases/download/v$(GOLANGCI_VERSION)/golangci-lint-$(GOLANGCI_VERSION)-$(GOOS)-arm64.tar.gz" GOLANGCI_DOWNLOAD_URL := "https://github.com/golangci/golangci-lint/releases/download/v$(GOLANGCI_VERSION)/golangci-lint-$(GOLANGCI_VERSION)-$(GOOS)-arm64.tar.gz"
@@ -97,7 +96,6 @@ get-deps:
get-tools: get-tools:
@echo "==> Installing tools at $(GOBIN)..." @echo "==> Installing tools at $(GOBIN)..."
@$(MAKE) install-golangci-lint @$(MAKE) install-golangci-lint
@$(MAKE) install-fieldalignment
.require-golangci-lint: .require-golangci-lint:
ifeq ($(shell if golangci-lint --version 2>/dev/null | grep ${GOLANGCI_VERSION} 1>/dev/null 2>&1; then echo "ok"; else echo "need-install"; fi), need-install) ifeq ($(shell if golangci-lint --version 2>/dev/null | grep ${GOLANGCI_VERSION} 1>/dev/null 2>&1; then echo "ok"; else echo "need-install"; fi), need-install)
@@ -108,15 +106,6 @@ install-golangci-lint:
@echo "==> Installing golangci-lint ${GOLANGCI_VERSION} at $(GOBIN)..." @echo "==> Installing golangci-lint ${GOLANGCI_VERSION} at $(GOBIN)..."
$(call dl_tgz,golangci-lint,$(GOLANGCI_DOWNLOAD_URL)) $(call dl_tgz,golangci-lint,$(GOLANGCI_DOWNLOAD_URL))
.require-fieldalignment:
ifeq ($(shell if fieldalignment -V=full 1>/dev/null 2>&1; then echo "ok"; else echo "need-install"; fi), need-install)
$(MAKE) install-golangci-lint
endif
install-fieldalignment:
@echo "==> Installing fieldalignment ${FIELDALIGNMENT_VERSION} at $(GOBIN)..."
@go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@v${FIELDALIGNMENT_VERSION}
define dl_tgz define dl_tgz
@mkdir "$(GOBIN)" 2>/dev/null || true @mkdir "$(GOBIN)" 2>/dev/null || true
@echo "Downloading $(GOBIN)/$(1)"; @echo "Downloading $(GOBIN)/$(1)";

View File

@@ -11,7 +11,7 @@ If you are using GocqlX v3.0.0 or newer, you must ensure your `go.mod` includes
```go ```go
// Use the latest version of scylladb/gocql; check for updates at https://github.com/scylladb/gocql/releases // Use the latest version of scylladb/gocql; check for updates at https://github.com/scylladb/gocql/releases
replace github.com/gocql/gocql => github.com/scylladb/gocql v1.15.3 replace github.com/gocql/gocql => github.com/scylladb/gocql v1.16.0
``` ```
This is required because GocqlX relies on ScyllaDB-specific extensions and bug fixes introduced in the gocql fork. Attempting to use the standard gocql driver with GocqlX v3.0.0+ may lead to build or runtime issues. This is required because GocqlX relies on ScyllaDB-specific extensions and bug fixes introduced in the gocql fork. Attempting to use the standard gocql driver with GocqlX v3.0.0+ may lead to build or runtime issues.
@@ -30,8 +30,18 @@ Subpackages provide additional functionality:
* CRUD operations based on table model ([package table](https://github.com/scylladb/gocqlx/blob/master/table)) * CRUD operations based on table model ([package table](https://github.com/scylladb/gocqlx/blob/master/table))
* Database migrations ([package migrate](https://github.com/scylladb/gocqlx/blob/master/migrate)) * Database migrations ([package migrate](https://github.com/scylladb/gocqlx/blob/master/migrate))
## Installation ## Installation GocqlX
Add GocqlX to your Go module:
```bash
go get github.com/scylladb/gocqlx/v3
```
## Installation schemagen
Unfortunately you can't install it via `go install`, since `go.mod` contains `replace` directive.
So, you have to check it out and install manually:
```bash ```bash
git clone git@github.com:scylladb/gocqlx.git git clone git@github.com:scylladb/gocqlx.git
cd gocqlx/cmd/schemagen/ cd gocqlx/cmd/schemagen/
@@ -40,6 +50,20 @@ go install .
## Getting started ## Getting started
First, import the required packages:
```go
import (
"fmt"
"log"
"github.com/gocql/gocql"
"github.com/scylladb/gocqlx/v3"
"github.com/scylladb/gocqlx/v3/qb"
"github.com/scylladb/gocqlx/v3/table"
)
```
Wrap gocql Session: Wrap gocql Session:
```go ```go
@@ -48,8 +72,9 @@ cluster := gocql.NewCluster(hosts...)
// Wrap session on creation, gocqlx session embeds gocql.Session pointer. // Wrap session on creation, gocqlx session embeds gocql.Session pointer.
session, err := gocqlx.WrapSession(cluster.CreateSession()) session, err := gocqlx.WrapSession(cluster.CreateSession())
if err != nil { if err != nil {
t.Fatal(err) log.Fatal(err)
} }
defer session.Close()
``` ```
Specify table model: Specify table model:
@@ -90,7 +115,7 @@ p := Person{
} }
q := session.Query(personTable.Insert()).BindStruct(p) q := session.Query(personTable.Insert()).BindStruct(p)
if err := q.ExecRelease(); err != nil { if err := q.ExecRelease(); err != nil {
t.Fatal(err) log.Fatal(err)
} }
``` ```
@@ -104,9 +129,9 @@ p := Person{
} }
q := session.Query(personTable.Get()).BindStruct(p) q := session.Query(personTable.Get()).BindStruct(p)
if err := q.GetRelease(&p); err != nil { if err := q.GetRelease(&p); err != nil {
t.Fatal(err) log.Fatal(err)
} }
t.Log(p) fmt.Println(p)
// stdout: {Michał Matczuk [michal@scylladb.com]} // stdout: {Michał Matczuk [michal@scylladb.com]}
``` ```
@@ -116,9 +141,9 @@ Load all rows in to a slice:
var people []Person var people []Person
q := session.Query(personTable.Select()).BindMap(qb.M{"first_name": "Michał"}) q := session.Query(personTable.Select()).BindMap(qb.M{"first_name": "Michał"})
if err := q.SelectRelease(&people); err != nil { if err := q.SelectRelease(&people); err != nil {
t.Fatal(err) log.Fatal(err)
} }
t.Log(people) fmt.Println(people)
// stdout: [{Michał Matczuk [michal@scylladb.com]}] // stdout: [{Michał Matczuk [michal@scylladb.com]}]
``` ```

View File

@@ -162,12 +162,13 @@ func BenchmarkBaseGocqlSelect(b *testing.B) {
v := make([]*benchPerson, 100) v := make([]*benchPerson, 100)
p := new(benchPerson) p := new(benchPerson)
for iter.Scan(&p.ID, &p.FirstName, &p.LastName, &p.Email, &p.Gender, &p.IPAddress) { for iter.Scan(&p.ID, &p.FirstName, &p.LastName, &p.Email, &p.Gender, &p.IPAddress) {
v = append(v, p) // nolint:staticcheck v = append(v, p)
p = new(benchPerson) p = new(benchPerson)
} }
if err := iter.Close(); err != nil { if err := iter.Close(); err != nil {
b.Fatal(err) b.Fatal(err)
} }
_ = v
} }
} }

View File

@@ -16,7 +16,7 @@ func camelize(s string) string {
l := len(buf) l := len(buf)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
if !(allowedBindRune(buf[i]) || buf[i] == '_') { if !allowedBindRune(buf[i]) && buf[i] != '_' {
panic(fmt.Sprint("not allowed name ", s)) panic(fmt.Sprint("not allowed name ", s))
} }

View File

@@ -1,21 +1,21 @@
module schemagentest module schemagentest
go 1.21 go 1.25.0
require ( require (
github.com/gocql/gocql v1.7.0 github.com/gocql/gocql v1.7.0
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
github.com/scylladb/gocqlx/v3 v3.0.0 github.com/scylladb/gocqlx/v3 v3.0.4
) )
require ( require (
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.18.1 // indirect
github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
) )
replace ( replace (
github.com/gocql/gocql => github.com/scylladb/gocql v1.15.3 github.com/gocql/gocql => github.com/scylladb/gocql v1.17.0
github.com/scylladb/gocqlx/v3 => ../../.. github.com/scylladb/gocqlx/v3 => ../../..
) )

View File

@@ -1,53 +1,30 @@
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ=
github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc=
github.com/scylladb/gocql v1.15.1 h1:t75NkDFys0XxipPsnTrSEbwx8B8R/jTUt5OAY9W7i+c= github.com/scylladb/gocql v1.16.1 h1:mxqUoOoHPrhzBNN+S0X195N+wCPZ5nrstfFz4QtBaZs=
github.com/scylladb/gocql v1.15.1/go.mod h1:+rInt+HjERaMEYC4N8LocQQEAdREhYKU4QPkE00K5dA= github.com/scylladb/gocql v1.16.1/go.mod h1:MSg2nr90XMcU0doVnISX3OtarTac5tSCGk6Q6QJd6oQ=
github.com/scylladb/gocql v1.15.2 h1:Vv7iaIyTMMjMtux1INQMi0waH8j8O/ppKS6JcM1vh14= github.com/scylladb/gocql v1.17.0 h1:sSjNTgSoC90+1XYXOMeWsQ8+AZbFYQWcspuScmUT53E=
github.com/scylladb/gocql v1.15.2/go.mod h1:+rInt+HjERaMEYC4N8LocQQEAdREhYKU4QPkE00K5dA= github.com/scylladb/gocql v1.17.0/go.mod h1:0VgVuYnAPOoYN17KXkYdWDxhL2/rH3V3vOisPMngpAw=
github.com/scylladb/gocql v1.15.3/go.mod h1:+rInt+HjERaMEYC4N8LocQQEAdREhYKU4QPkE00K5dA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

View File

@@ -29,6 +29,8 @@ func ExampleUDT() {
FirstName string FirstName string
LastName string LastName string
} }
_ = FullName{}
} }
func ExampleUDT_wraper() { func ExampleUDT_wraper() {
@@ -42,4 +44,6 @@ func ExampleUDT_wraper() {
gocqlx.UDT gocqlx.UDT
*FullName *FullName
} }
_ = FullNameUDT{}
} }

View File

@@ -35,7 +35,7 @@ func TestExample(t *testing.T) {
} }
defer session.Close() defer session.Close()
session.ExecStmt(`DROP KEYSPACE examples`) _ = session.ExecStmt(`DROP KEYSPACE examples`)
basicCreateAndPopulateKeyspace(t, session, "examples") basicCreateAndPopulateKeyspace(t, session, "examples")
createAndPopulateKeyspaceAllTypes(t, session) createAndPopulateKeyspaceAllTypes(t, session)
@@ -270,7 +270,7 @@ func createAndPopulateKeyspaceAllTypes(t *testing.T, session gocqlx.Session) {
copy(byteID[:], id) copy(byteID[:], id)
date := time.Date(2021, time.December, 11, 10, 23, 0, 0, time.UTC) date := time.Date(2021, time.December, 11, 10, 23, 0, 0, time.UTC)
var double float64 = 1.2 // nolint:revive var double float64 = 1.2 //nolint:staticcheck // type needs to be enforces
var float float32 = 1.3 var float float32 = 1.3
var integer int32 = 123 var integer int32 = 123
listInt := []int32{1, 2, 3} listInt := []int32{1, 2, 3}

8
go.mod
View File

@@ -1,19 +1,19 @@
module github.com/scylladb/gocqlx/v3 module github.com/scylladb/gocqlx/v3
go 1.21 go 1.25.0
require ( require (
github.com/gocql/gocql v1.7.0 github.com/gocql/gocql v1.7.0
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b
github.com/scylladb/go-reflectx v1.0.1 github.com/scylladb/go-reflectx v1.0.1
golang.org/x/sync v0.11.0 golang.org/x/sync v0.18.0
gopkg.in/inf.v0 v0.9.1 gopkg.in/inf.v0 v0.9.1
) )
require ( require (
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.18.1 // indirect
) )
replace github.com/gocql/gocql => github.com/scylladb/gocql v1.15.3 replace github.com/gocql/gocql => github.com/scylladb/gocql v1.17.0

59
go.sum
View File

@@ -1,54 +1,45 @@
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-hostpool v0.1.1 h1:SsovT4BFqgJQBAESkk2QgeeL7bqKq9oJie8JnD00R+Q=
github.com/bitly/go-hostpool v0.1.1/go.mod h1:iwXQOF7+y3cO8vituSqGpBYf02TYTzxK4S2c4rf4cJs=
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/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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b h1:xzjEJAHum+mV5Dd5KyohRlCyP03o4yq6vNpEUtAJQzI= github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b h1:xzjEJAHum+mV5Dd5KyohRlCyP03o4yq6vNpEUtAJQzI=
github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI= github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI=
github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ=
github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc=
github.com/scylladb/gocql v1.15.3 h1:0vJT5pm7g5v8/pCs3tuXuRAfSRWvc1kib8J846Z+Z4g= github.com/scylladb/gocql v1.16.1 h1:mxqUoOoHPrhzBNN+S0X195N+wCPZ5nrstfFz4QtBaZs=
github.com/scylladb/gocql v1.15.3/go.mod h1:+rInt+HjERaMEYC4N8LocQQEAdREhYKU4QPkE00K5dA= github.com/scylladb/gocql v1.16.1/go.mod h1:MSg2nr90XMcU0doVnISX3OtarTac5tSCGk6Q6QJd6oQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/scylladb/gocql v1.17.0 h1:sSjNTgSoC90+1XYXOMeWsQ8+AZbFYQWcspuScmUT53E=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/scylladb/gocql v1.17.0/go.mod h1:0VgVuYnAPOoYN17KXkYdWDxhL2/rH3V3vOisPMngpAw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

View File

@@ -20,15 +20,15 @@ func structOnlyError(t reflect.Type) error {
return fmt.Errorf("expected a struct but got %s", t.Kind()) return fmt.Errorf("expected a struct but got %s", t.Kind())
} }
if isUnmarshaller := reflect.PtrTo(t).Implements(unmarshallerInterface); isUnmarshaller { if isUnmarshaller := reflect.PointerTo(t).Implements(unmarshallerInterface); isUnmarshaller {
return fmt.Errorf("expected a struct but the provided struct type %s implements gocql.Unmarshaler", t.Name()) return fmt.Errorf("expected a struct but the provided struct type %s implements gocql.Unmarshaler", t.Name())
} }
if isUDTUnmarshaller := reflect.PtrTo(t).Implements(udtUnmarshallerInterface); isUDTUnmarshaller { if isUDTUnmarshaller := reflect.PointerTo(t).Implements(udtUnmarshallerInterface); isUDTUnmarshaller {
return fmt.Errorf("expected a struct but the provided struct type %s implements gocql.UDTUnmarshaler", t.Name()) return fmt.Errorf("expected a struct but the provided struct type %s implements gocql.UDTUnmarshaler", t.Name())
} }
if isAutoUDT := reflect.PtrTo(t).Implements(autoUDTInterface); isAutoUDT { if isAutoUDT := reflect.PointerTo(t).Implements(autoUDTInterface); isAutoUDT {
return fmt.Errorf("expected a struct but the provided struct type %s implements gocqlx.UDT", t.Name()) return fmt.Errorf("expected a struct but the provided struct type %s implements gocqlx.UDT", t.Name())
} }

View File

@@ -62,7 +62,7 @@ func (iter *Iterx) StructOnly() *Iterx {
// If no rows were selected, ErrNotFound is returned. // If no rows were selected, ErrNotFound is returned.
func (iter *Iterx) Get(dest interface{}) error { func (iter *Iterx) Get(dest interface{}) error {
iter.scanAny(dest) iter.scanAny(dest)
iter.Close() _ = iter.Close()
return iter.checkErrAndNotFound() return iter.checkErrAndNotFound()
} }
@@ -119,7 +119,7 @@ func (iter *Iterx) scanAny(dest interface{}) bool {
// If no rows were selected, ErrNotFound is NOT returned. // If no rows were selected, ErrNotFound is NOT returned.
func (iter *Iterx) Select(dest interface{}) error { func (iter *Iterx) Select(dest interface{}) error {
iter.scanAll(dest) iter.scanAll(dest)
iter.Close() _ = iter.Close()
return iter.err return iter.err
} }
@@ -209,7 +209,7 @@ func (iter *Iterx) scanAll(dest interface{}) bool {
// - it is not a struct // - it is not a struct
// - it has no exported fields // - it has no exported fields
func (iter *Iterx) isScannable(t reflect.Type) bool { func (iter *Iterx) isScannable(t reflect.Type) bool {
ptr := reflect.PtrTo(t) ptr := reflect.PointerTo(t)
switch { switch {
case ptr.Implements(unmarshallerInterface): case ptr.Implements(unmarshallerInterface):
return true return true
@@ -260,7 +260,7 @@ func (iter *Iterx) structScan(value reflect.Value) bool {
} }
if iter.fields == nil { if iter.fields == nil {
columns := columnNames(iter.Iter.Columns()) columns := columnNames(iter.Columns())
cas := len(columns) > 0 && columns[0] == appliedColumn cas := len(columns) > 0 && columns[0] == appliedColumn
iter.fields = iter.Mapper.TraversalsByName(value.Type(), columns) iter.fields = iter.Mapper.TraversalsByName(value.Type(), columns)
@@ -342,7 +342,7 @@ func (iter *Iterx) Close() error {
func (iter *Iterx) checkErrAndNotFound() error { func (iter *Iterx) checkErrAndNotFound() error {
if iter.err != nil { if iter.err != nil {
return iter.err return iter.err
} else if iter.Iter.NumRows() == 0 { } else if iter.NumRows() == 0 {
return gocql.ErrNotFound return gocql.ErrNotFound
} }
return nil return nil

View File

@@ -260,7 +260,7 @@ func TestIterxUDT(t *testing.T) {
} }
t.Cleanup(func() { t.Cleanup(func() {
session.Query(deleteStmt, nil).Bind(testuuid).ExecRelease() // nolint:errcheck _ = session.Query(deleteStmt, nil).Bind(testuuid).ExecRelease()
}) })
t.Run("insert-bind", func(t *testing.T) { t.Run("insert-bind", func(t *testing.T) {
@@ -930,7 +930,9 @@ func TestIterxPaging(t *testing.T) {
AllowFiltering(). AllowFiltering().
Columns("id", "val").ToCql() Columns("id", "val").ToCql()
iter := session.Query(stmt, names).Bind(100).PageSize(10).Iter() iter := session.Query(stmt, names).Bind(100).PageSize(10).Iter()
defer iter.Close() defer func() {
_ = iter.Close()
}()
var cnt int var cnt int
for { for {

View File

@@ -23,7 +23,9 @@ func fileChecksum(f fs.FS, path string) (string, error) {
if err != nil { if err != nil {
return "", nil return "", nil
} }
defer file.Close() defer func() {
_ = file.Close()
}()
h := md5.New() h := md5.New()
if _, err := io.Copy(h, file); err != nil { if _, err := io.Copy(h, file); err != nil {

View File

@@ -3,3 +3,7 @@ package migrate
func IsCallback(stmt string) (name string) { func IsCallback(stmt string) (name string) {
return isCallback(stmt) return isCallback(stmt)
} }
func IsComment(stmt string) bool {
return isComment(stmt)
}

View File

@@ -201,6 +201,23 @@ func FromFS(ctx context.Context, session gocqlx.Session, f fs.FS) error {
return nil return nil
} }
// applyMigration executes a single migration file by parsing and applying its statements.
// It handles three types of content in migration files:
// - SQL statements: executed against the database
// - Callback commands: processed via registered callback handlers (format: -- CALL function_name;)
// - Regular comments: silently skipped (format: -- any comment text)
//
// The function maintains migration state by tracking the number of completed statements,
// allowing for resumption of partially completed migrations.
//
// Parameters:
// - ctx: context for cancellation and timeouts
// - session: database session for executing statements
// - f: filesystem containing the migration file
// - path: path to the migration file within the filesystem
// - done: number of statements already completed (for resuming partial migrations)
//
// Returns an error if the migration fails at any point.
func applyMigration(ctx context.Context, session gocqlx.Session, f fs.FS, path string, done int) error { func applyMigration(ctx context.Context, session gocqlx.Session, f fs.FS, path string, done int) error {
file, err := f.Open(path) file, err := f.Open(path)
if err != nil { if err != nil {
@@ -208,7 +225,7 @@ func applyMigration(ctx context.Context, session gocqlx.Session, f fs.FS, path s
} }
b, err := io.ReadAll(file) b, err := io.ReadAll(file)
file.Close() _ = file.Close()
if err != nil { if err != nil {
return err return err
} }
@@ -272,19 +289,23 @@ func applyMigration(ctx context.Context, session gocqlx.Session, f fs.FS, path s
// trim new lines and all whitespace characters // trim new lines and all whitespace characters
stmt = strings.TrimSpace(stmt) stmt = strings.TrimSpace(stmt)
// Process statement based on its type
if cb := isCallback(stmt); cb != "" { if cb := isCallback(stmt); cb != "" {
// Handle callback commands (e.g., "-- CALL function_name;")
if Callback == nil { if Callback == nil {
return fmt.Errorf("statement %d: missing callback handler while trying to call %s", i, cb) return fmt.Errorf("statement %d: missing callback handler while trying to call %s", i, cb)
} }
if err := Callback(ctx, session, CallComment, cb); err != nil { if err := Callback(ctx, session, CallComment, cb); err != nil {
return fmt.Errorf("callback %s: %s", cb, err) return fmt.Errorf("callback %s: %s", cb, err)
} }
} else { } else if stmt != "" && !isComment(stmt) {
// Execute SQL statements (skip empty statements and comments)
q := session.ContextQuery(ctx, stmt, nil).RetryPolicy(nil) q := session.ContextQuery(ctx, stmt, nil).RetryPolicy(nil)
if err := q.ExecRelease(); err != nil { if err := q.ExecRelease(); err != nil {
return fmt.Errorf("statement %d: %s", i, err) return fmt.Errorf("statement %d: %s", i, err)
} }
} }
// Regular comments and empty statements are silently skipped
// update info // update info
info.Done = i info.Done = i
@@ -315,3 +336,10 @@ func isCallback(stmt string) (name string) {
} }
return s[1] return s[1]
} }
// isComment returns true if the statement is a SQL comment that should be ignored.
// It distinguishes between regular comments (which should be skipped) and
// callback commands (which should be processed).
func isComment(stmt string) bool {
return strings.HasPrefix(stmt, "--") && isCallback(stmt) == ""
}

View File

@@ -56,7 +56,7 @@ func TestPending(t *testing.T) {
defer recreateTables(t, session) defer recreateTables(t, session)
f := memfs.New() f := memfs.New()
writeFile(f, 0, fmt.Sprintf(insertMigrate, 0)+";") writeFile(t, f, 0, fmt.Sprintf(insertMigrate, 0)+";")
pending, err := migrate.Pending(ctx, session, f) pending, err := migrate.Pending(ctx, session, f)
if err != nil { if err != nil {
@@ -80,7 +80,7 @@ func TestPending(t *testing.T) {
} }
for i := 1; i < 3; i++ { for i := 1; i < 3; i++ {
writeFile(f, i, fmt.Sprintf(insertMigrate, i)+";") writeFile(t, f, i, fmt.Sprintf(insertMigrate, i)+";")
} }
pending, err = migrate.Pending(ctx, session, f) pending, err = migrate.Pending(ctx, session, f)
@@ -101,7 +101,7 @@ func TestMigration(t *testing.T) {
ctx := context.Background() ctx := context.Background()
t.Run("init", func(t *testing.T) { t.Run("init", func(t *testing.T) {
if err := migrate.FromFS(ctx, session, makeTestFS(2)); err != nil { if err := migrate.FromFS(ctx, session, makeTestFS(t, 2)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if c := countMigrations(t, session); c != 2 { if c := countMigrations(t, session); c != 2 {
@@ -110,7 +110,7 @@ func TestMigration(t *testing.T) {
}) })
t.Run("update", func(t *testing.T) { t.Run("update", func(t *testing.T) {
if err := migrate.FromFS(ctx, session, makeTestFS(4)); err != nil { if err := migrate.FromFS(ctx, session, makeTestFS(t, 4)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if c := countMigrations(t, session); c != 4 { if c := countMigrations(t, session); c != 4 {
@@ -119,7 +119,7 @@ func TestMigration(t *testing.T) {
}) })
t.Run("ahead", func(t *testing.T) { t.Run("ahead", func(t *testing.T) {
err := migrate.FromFS(ctx, session, makeTestFS(2)) err := migrate.FromFS(ctx, session, makeTestFS(t, 2))
if err == nil || !strings.Contains(err.Error(), "ahead") { if err == nil || !strings.Contains(err.Error(), "ahead") {
t.Fatal("expected error") t.Fatal("expected error")
} else { } else {
@@ -128,8 +128,8 @@ func TestMigration(t *testing.T) {
}) })
t.Run("tempered with file", func(t *testing.T) { t.Run("tempered with file", func(t *testing.T) {
f := makeTestFS(4) f := makeTestFS(t, 4)
writeFile(f, 3, "SELECT * FROM bla;") writeFile(t, f, 3, "SELECT * FROM bla;")
if err := migrate.FromFS(ctx, session, f); err == nil || !strings.Contains(err.Error(), "tampered") { if err := migrate.FromFS(ctx, session, f); err == nil || !strings.Contains(err.Error(), "tampered") {
t.Fatal("expected error") t.Fatal("expected error")
@@ -148,8 +148,11 @@ func TestMigrationNoSemicolon(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
f := makeTestFS(0) f := makeTestFS(t, 0)
f.WriteFile("0.cql", []byte(fmt.Sprintf(insertMigrate, 0)+";"+fmt.Sprintf(insertMigrate, 1)), fs.ModePerm) err := f.WriteFile("0.cql", []byte(fmt.Sprintf(insertMigrate, 0)+";"+fmt.Sprintf(insertMigrate, 1)), fs.ModePerm)
if err != nil {
t.Fatal(err)
}
ctx := context.Background() ctx := context.Background()
if err := migrate.FromFS(ctx, session, f); err != nil { if err := migrate.FromFS(ctx, session, f); err != nil {
@@ -160,6 +163,32 @@ func TestMigrationNoSemicolon(t *testing.T) {
} }
} }
func TestMigrationWithTrailingComment(t *testing.T) {
session := gocqlxtest.CreateSession(t)
defer session.Close()
recreateTables(t, session)
if err := session.ExecStmt(migrateSchema); err != nil {
t.Fatal(err)
}
f := makeTestFS(t, 0)
// Create a migration with a trailing comment (this should reproduce the issue)
migrationContent := fmt.Sprintf(insertMigrate, 0) + "; -- ttl 1 hour"
err := f.WriteFile("0.cql", []byte(migrationContent), fs.ModePerm)
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
if err := migrate.FromFS(ctx, session, f); err != nil {
t.Fatal("Migration should succeed with trailing comment, but got error:", err)
}
if c := countMigrations(t, session); c != 1 {
t.Fatal("expected 1 migration got", c)
}
}
func TestIsCallback(t *testing.T) { func TestIsCallback(t *testing.T) {
table := []struct { table := []struct {
Name string Name string
@@ -211,6 +240,60 @@ func TestIsCallback(t *testing.T) {
} }
} }
func TestIsComment(t *testing.T) {
table := []struct {
Name string
Stmt string
IsComment bool
}{
{
Name: "CQL statement",
Stmt: "SELECT * from X;",
IsComment: false,
},
{
Name: "Regular comment",
Stmt: "-- This is a comment",
IsComment: true,
},
{
Name: "Comment with additional text",
Stmt: "-- ttl 1 hour",
IsComment: true,
},
{
Name: "Callback command (not a regular comment)",
Stmt: "-- CALL Foo;",
IsComment: false,
},
{
Name: "Callback with spaces (not a regular comment)",
Stmt: "-- CALL Bar;",
IsComment: false,
},
{
Name: "Empty statement",
Stmt: "",
IsComment: false,
},
{
Name: "Whitespace only",
Stmt: " ",
IsComment: false,
},
}
for i := range table {
test := table[i]
t.Run(test.Name, func(t *testing.T) {
result := migrate.IsComment(test.Stmt)
if result != test.IsComment {
t.Errorf("IsComment(%q) = %v, expected %v", test.Stmt, result, test.IsComment)
}
})
}
}
func TestMigrationCallback(t *testing.T) { func TestMigrationCallback(t *testing.T) {
var ( var (
beforeCalled int beforeCalled int
@@ -264,7 +347,7 @@ func TestMigrationCallback(t *testing.T) {
ctx := context.Background() ctx := context.Background()
t.Run("init", func(t *testing.T) { t.Run("init", func(t *testing.T) {
f := makeTestFS(2) f := makeTestFS(t, 2)
reset() reset()
if err := migrate.FromFS(ctx, session, f); err != nil { if err := migrate.FromFS(ctx, session, f); err != nil {
@@ -274,7 +357,7 @@ func TestMigrationCallback(t *testing.T) {
}) })
t.Run("no duplicate calls", func(t *testing.T) { t.Run("no duplicate calls", func(t *testing.T) {
f := makeTestFS(4) f := makeTestFS(t, 4)
reset() reset()
if err := migrate.FromFS(ctx, session, f); err != nil { if err := migrate.FromFS(ctx, session, f); err != nil {
@@ -284,9 +367,9 @@ func TestMigrationCallback(t *testing.T) {
}) })
t.Run("in calls", func(t *testing.T) { t.Run("in calls", func(t *testing.T) {
f := makeTestFS(4) f := makeTestFS(t, 4)
writeFile(f, 4, "\n-- CALL Foo;\n") writeFile(t, f, 4, "\n-- CALL Foo;\n")
writeFile(f, 5, "\n-- CALL Bar;\n") writeFile(t, f, 5, "\n-- CALL Bar;\n")
reset() reset()
if err := migrate.FromFS(ctx, session, f); err != nil { if err := migrate.FromFS(ctx, session, f); err != nil {
@@ -306,14 +389,19 @@ func countMigrations(tb testing.TB, session gocqlx.Session) int {
return v return v
} }
func makeTestFS(n int) *memfs.FS { func makeTestFS(tb testing.TB, n int) *memfs.FS {
tb.Helper()
f := memfs.New() f := memfs.New()
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
writeFile(f, i, fmt.Sprintf(insertMigrate, i)+";") writeFile(tb, f, i, fmt.Sprintf(insertMigrate, i)+";")
} }
return f return f
} }
func writeFile(f *memfs.FS, i int, text string) { func writeFile(tb testing.TB, f *memfs.FS, i int, text string) {
f.WriteFile(fmt.Sprint(i, ".cql"), []byte(text), fs.ModePerm) tb.Helper()
err := f.WriteFile(fmt.Sprint(i, ".cql"), []byte(text), fs.ModePerm)
if err != nil {
tb.Fatal(err)
}
} }

View File

@@ -132,7 +132,7 @@ func (b *SelectBuilder) From(table string) *SelectBuilder {
} }
// Json sets the clause of the query. // Json sets the clause of the query.
func (b *SelectBuilder) Json() *SelectBuilder { // nolint: revive func (b *SelectBuilder) Json() *SelectBuilder {
b.json = true b.json = true
return b return b
} }

View File

@@ -181,7 +181,7 @@ func (q *Queryx) bindStructArgs(arg0 interface{}, arg1 map[string]interface{}) (
err := q.Mapper.TraversalsByNameFunc(v.Type(), q.Names, func(i int, t []int) error { err := q.Mapper.TraversalsByNameFunc(v.Type(), q.Names, func(i int, t []int) error {
if len(t) != 0 { if len(t) != 0 {
val := reflectx.FieldByIndexesReadOnly(v, t) // nolint:scopelint val := reflectx.FieldByIndexesReadOnly(v, t)
arglist = append(arglist, val.Interface()) arglist = append(arglist, val.Interface())
} else { } else {
val, ok := arg1[q.Names[i]] val, ok := arg1[q.Names[i]]

View File

@@ -16,7 +16,10 @@ func BenchmarkCompileNamedQuery(b *testing.B) {
q := []byte("INSERT INTO cycling.cyclist_name (id, user_uuid, firstname, stars) VALUES (:id, :user_uuid, :firstname, :stars)") q := []byte("INSERT INTO cycling.cyclist_name (id, user_uuid, firstname, stars) VALUES (:id, :user_uuid, :firstname, :stars)")
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
gocqlx.CompileNamedQuery(q) _, _, err := gocqlx.CompileNamedQuery(q)
if err != nil {
b.Fatal(err)
}
} }
} }

View File

@@ -3,51 +3,5 @@
"extends": [ "extends": [
"config:recommended" "config:recommended"
], ],
"schedule": [ "prConcurrentLimit": 2
"every weekend"
],
"labels": [
"renovate",
"dependencies"
],
"enabledManagers": [
"gomod",
"github-actions",
"helm-values"
],
"packageRules": [
{
"groupName": "All dependencies",
"groupSlug": "all-dependencies",
"matchManagers": [
"gomod"
],
"matchPackageNames": [
"!github.com/scylladb/gocql"
],
"enabled": true
},
{
"groupName": "all non-major dependencies",
"groupSlug": "all-minor-patch",
"matchPackageNames": [
"*"
],
"matchUpdateTypes": [
"minor",
"patch"
],
"enabled": false
},
{
"matchPackageNames": [
"github.com/scylladb/gocql"
],
"enabled": true
}
],
"vulnerabilityAlerts": {
"enabled": true
},
"osvVulnerabilityAlerts": true
} }

View File

@@ -37,7 +37,7 @@ type Table struct {
} }
// New creates new Table based on table schema read from Metadata. // New creates new Table based on table schema read from Metadata.
func New(m Metadata) *Table { // nolint: gocritic func New(m Metadata) *Table {
t := &Table{ t := &Table{
metadata: m, metadata: m,
} }