Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ updates:
directory: /
schedule:
interval: monthly
- package-ecosystem: gomod
directory: /dbtest
schedule:
interval: monthly
- package-ecosystem: github-actions
directory: /
schedule:
Expand Down
25 changes: 20 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,31 @@ jobs:
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: stable
- name: Root module requires no other module
# The database drivers belong to the dbtest module only; a requirement
# here would reach every consumer's module graph.
run: |
out="$(go list -m all)"
if [ "$out" != "$(go list -m)" ]; then echo "go.mod requires:"; echo "$out"; exit 1; fi
- name: go vet
run: go vet ./...
run: |
go vet ./...
(cd dbtest && go vet ./...)
- name: staticcheck
# v0.8.1 cannot read Go 1.27.2 export data ("export data version 5 is greater than maximum
# supported version 4"). This master build from 2026-10-09 can; pin a tagged release again
# once one is published.
run: go run honnef.co/go/tools/cmd/staticcheck@v0.7.0-0.dev.0.20261009230814-452d5bb86b45 -checks=all ./...
run: |
go run honnef.co/go/tools/cmd/staticcheck@v0.7.0-0.dev.0.20261009230814-452d5bb86b45 -checks=all ./...
(cd dbtest && go run honnef.co/go/tools/cmd/staticcheck@v0.7.0-0.dev.0.20261009230814-452d5bb86b45 -checks=all ./...)
- name: goimports
run: |
out="$(go run golang.org/x/tools/cmd/goimports@v0.52.0 -l -local "$(go list -m)" .)"
if [ -n "$out" ]; then echo "goimports would change:"; echo "$out"; exit 1; fi
- name: govulncheck
run: go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 ./...
run: |
go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 ./...
(cd dbtest && go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 ./...)

test:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -85,11 +97,14 @@ jobs:
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ matrix.go }}
- name: Test with the race detector against Postgres, MySQL and SQLite
- name: Unit tests with the race detector
run: go test -race -count=1 ./...
- name: Database tests with the race detector against Postgres, MySQL and SQLite
working-directory: dbtest
env:
SQLX_SQLITE_DSN: ${{ runner.temp }}/sqlx.db
run: |
go test -race -count=1 -v ./... 2>&1 | tee test.log
go test -race -count=1 -v ./... 2>&1 | tee ../test.log
test "${PIPESTATUS[0]}" -eq 0
- name: Fail if a database was skipped
# init() prints "Disabling ..." and the schema tests then run zero rounds for that database.
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ Notable changes to this fork, newest first. An entry that imports an upstream
pull request names its number and author. Releases up to v1.4.0 are releases of
upstream [jmoiron/sqlx](https://github.com/jmoiron/sqlx).

## Unreleased

### Module and toolchain

- sqlx's `go.mod` requires no other module. The tests that run against
Postgres, MySQL and SQLite move to the nested module `dbtest/`, which holds
the three drivers, so `go-sql-driver/mysql`, `lib/pq` and `go-sqlite3` no
longer enter the module graph of a program that imports sqlx. Before, Go's
minimum version selection raised a consumer's own MySQL driver to v1.10.1
even though sqlx only used it in tests (upstream #642, #569, #849). The
checks in three tests that read the unexported `unsafe` field now test its
effect instead: scanning into a struct that lacks some selected columns.

## v1.4.1 (2026-10-10)

The first fork release. It keeps every exported identifier of v1.4.0 (CI runs
Expand Down
12 changes: 8 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ Bug reports, fixes, tests and documentation are all welcome.
Open an issue with the bug report template. The driver and database
version, the SQL, the struct or map you bind or scan, and what you expected
are what make a report reproducible. A failing test in the style of
`sqlx_test.go` is the best report of all. Questions about how to use sqlx go
`dbtest/sqlx_test.go` is the best report of all. Questions about how to use sqlx go
to [Discussions](https://github.com/secondwindoss/sqlx/discussions).

## Making a change

1. Branch from `master`.
2. Add or update a test. The suite always runs against SQLite and also runs
against Postgres and MySQL when their DSN variables are set:
2. Add or update a test. Tests that need no database live next to the code
in the root module and run with `make test`. Tests that talk to a database
live in `dbtest/`, a separate module, so that the drivers never appear in
sqlx's own `go.mod` or in the module graph of anyone who imports it. The
database suite always runs against SQLite and also runs against Postgres
and MySQL when their DSN variables are set:

docker run -d --name sqlx-pg -e POSTGRES_PASSWORD=sqlx -p 5432:5432 postgres:16
docker run -d --name sqlx-mysql -e MYSQL_ROOT_PASSWORD=sqlx -e MYSQL_DATABASE=sqlx -p 3306:3306 mysql:8
Expand All @@ -31,7 +35,7 @@ to [Discussions](https://github.com/secondwindoss/sqlx/discussions).
`go test -run TestGolden -update`, review the diff of
`testdata/golden.txt`, and mention the changed lines in the pull request.
4. Open a pull request against `master`. CI runs the lint job and the race
tests on Go 1.23 to stable with all three databases and must be green
tests on Go 1.24 to stable with all three databases and must be green
before the merge.

Keep the exported API unchanged within v1 unless the change is purely
Expand Down
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ has-changes:
lint:
go vet ./...
staticcheck -checks=all ./...
cd dbtest && go vet ./... && staticcheck -checks=all ./...

fmt:
go list -f '{{.Dir}}' ./... | xargs -I {} goimports -local $(BASE_PACKAGE) -w {}
goimports -local $(BASE_PACKAGE) -w .

vuln-check:
govulncheck ./...
cd dbtest && govulncheck ./...

test-race:
go test -v -race -count=1 ./...
test:
go test -race -count=1 ./...

test-race: test
cd dbtest && go test -v -race -count=1 ./...

update-dependencies:
go get -u -t -v ./...
go mod tidy
cd dbtest && go get -u -t -v ./... && go mod tidy
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ tests on Go 1.24, 1.25, oldstable and stable.

**Databases.** CI tests every change against PostgreSQL 16, MySQL 8 and
SQLite. Any `database/sql` driver works; sqlx only needs to know its
placeholder style.
placeholder style. sqlx's `go.mod` requires no other module: the drivers used
by the database tests live in the separate `dbtest/` module, so importing sqlx
never changes which driver version your program builds with.

| Placeholder | Drivers |
|-------------|---------------------------------------------------------------------------|
Expand Down
28 changes: 20 additions & 8 deletions conn_preparex_test.go → dbtest/conn_preparex_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package sqlx
package dbtest

import (
"context"
"strings"
"testing"

. "github.com/secondwindoss/sqlx"

"github.com/secondwindoss/sqlx/reflectx"
)

// A Stmt prepared on a Conn inherits the Conn's Mapper and unsafe flag
// (upstream #975).
// (upstream #975). The unsafe flag is checked through its effect: scanning
// into a struct that lacks some of the selected columns.
func TestConnPreparexKeepsMapperAndUnsafe(t *testing.T) {
RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T, now string) {
loadDefaultFixture(db, t)
Expand All @@ -20,24 +23,33 @@ func TestConnPreparexKeepsMapperAndUnsafe(t *testing.T) {
t.Fatal(err)
}
defer conn.Close()
if !conn.unsafe {
t.Fatal("precondition: conn from db.Unsafe() should be unsafe")
}
stmt, err := conn.PreparexContext(ctx, conn.Rebind("SELECT * FROM person WHERE first_name=?"))
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if stmt.unsafe != conn.unsafe {
t.Errorf("unsafe: Stmt.unsafe=%v, want %v (conn.unsafe)", stmt.unsafe, conn.unsafe)
}
var partial struct {
FirstName string `db:"first_name"`
}
if err := stmt.Get(&partial, "Jason"); err != nil {
t.Errorf("unsafe: Get into partial struct through conn-prepared Stmt: %v", err)
}

// Control: the same statement on a safe Conn rejects the partial struct.
safeConn, err := db.Connx(ctx)
if err != nil {
t.Fatal(err)
}
defer safeConn.Close()
safeStmt, err := safeConn.PreparexContext(ctx, safeConn.Rebind("SELECT * FROM person WHERE first_name=?"))
if err != nil {
t.Fatal(err)
}
defer safeStmt.Close()
if err := safeStmt.Get(&partial, "Jason"); err == nil {
t.Error("safe: Get into partial struct through a safe Conn's Stmt succeeded, want missing destination error")
}

conn2, err := db.Connx(ctx)
if err != nil {
t.Fatal(err)
Expand Down
14 changes: 14 additions & 0 deletions dbtest/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/secondwindoss/sqlx/dbtest

go 1.24.0

require github.com/secondwindoss/sqlx v1.4.1

require (
filippo.io/edwards25519 v1.2.0 // indirect
github.com/go-sql-driver/mysql v1.10.1 // indirect
github.com/lib/pq v1.12.3 // indirect
github.com/mattn/go-sqlite3 v1.14.52 // indirect
)

replace github.com/secondwindoss/sqlx => ../
File renamed without changes.
35 changes: 35 additions & 0 deletions dbtest/in_empty_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dbtest

import (
"testing"

. "github.com/secondwindoss/sqlx"
)

func TestInEmptySliceAgainstDatabase(t *testing.T) {
RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T, now string) {
loadDefaultFixture(db, t)
for _, tt := range []struct {
query string
args []interface{}
}{
{"SELECT * FROM place WHERE telcode IN (?)", []interface{}{[]int{}}},
{"SELECT * FROM place WHERE country = ? AND telcode IN (?)", []interface{}{"Hong Kong", []int{}}},
{"SELECT * FROM place WHERE telcode IN (?) AND country = ?", []interface{}{[]int{}, "Hong Kong"}},
// NOT IN (NULL) matches no row either; this documents the caveat.
{"SELECT * FROM place WHERE telcode NOT IN (?)", []interface{}{[]int{}}},
} {
q, args, err := In(tt.query, tt.args...)
if err != nil {
t.Fatalf("%s: %v", tt.query, err)
}
var places []Place
if err := db.Select(&places, db.Rebind(q), args...); err != nil {
t.Fatalf("%s: %v", tt.query, err)
}
if len(places) != 0 {
t.Errorf("%s: got %d rows, want none", tt.query, len(places))
}
}
})
}
8 changes: 6 additions & 2 deletions multi_result_set_test.go → dbtest/multi_result_set_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sqlx
package dbtest

import "testing"
import (
"testing"

. "github.com/secondwindoss/sqlx"
)

// Scanning a second result set with a different column layout must not reuse
// the first set's field cache (upstream #380, #857; test from upstream #747).
Expand Down
8 changes: 6 additions & 2 deletions named_cast_test.go → dbtest/named_cast_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sqlx
package dbtest

import "testing"
import (
"testing"

. "github.com/secondwindoss/sqlx"
)

// A Postgres cast attached to a named parameter binds the parameter and keeps
// the cast (upstream #983); a cast elsewhere in the query is left alone
Expand Down
4 changes: 3 additions & 1 deletion named_context_test.go → dbtest/named_context_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//go:build go1.8
// +build go1.8

package sqlx
package dbtest

import (
"context"
"database/sql"
"testing"

. "github.com/secondwindoss/sqlx"
)

func TestNamedContextQueries(t *testing.T) {
Expand Down
8 changes: 6 additions & 2 deletions named_ptr_test.go → dbtest/named_ptr_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sqlx
package dbtest

import "testing"
import (
"testing"

. "github.com/secondwindoss/sqlx"
)

// Named queries accept a pointer to a slice, to a map and to a slice of maps
// (upstream #577, #729).
Expand Down
Loading
Loading