Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
fail-fast: false
matrix:
pg: ['14', '15', '16', '17', '18']
go: ['1.21', '1.26']
go: ['1.23', '1.26']
steps:
- uses: 'actions/checkout@v6'
- uses: 'actions/setup-go@v6'
Expand Down
8 changes: 4 additions & 4 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"strings"
)

var typeByteSlice = reflect.TypeOf([]byte{})
var typeDriverValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
var typeSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
var typeByteSlice = reflect.TypeFor[[]byte]()
var typeDriverValuer = reflect.TypeFor[driver.Valuer]()
var typeSQLScanner = reflect.TypeFor[sql.Scanner]()

// Array returns the optimal driver.Valuer and sql.Scanner for an array or
// slice of any dimension.
Expand Down Expand Up @@ -129,7 +129,7 @@ func (a BoolArray) Value() (driver.Value, error) {
// and N-1 bytes of delimiters.
b := make([]byte, 1+2*n)

for i := 0; i < n; i++ {
for i := range n {
b[2*i] = ','
if a[i] {
b[1+2*i] = 't'
Expand Down
2 changes: 1 addition & 1 deletion array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ func BenchmarkArray(b *testing.B) {
byts = make([][]byte, 10)
strs = make([]string, 10)
)
for i := 0; i < len(bools); i++ {
for i := range bools {
bools[i] = rnd.Intn(2) == 0
floats[i] = rnd.NormFloat64()
ints[i] = rnd.Int63()
Expand Down
20 changes: 7 additions & 13 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"io"
"maps"
"math"
"net"
"os"
Expand Down Expand Up @@ -69,7 +70,6 @@ func TestOpen(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run(tt.dsn, func(t *testing.T) {
t.Parallel()
_, err := pqtest.DB(t, tt.dsn)
Expand All @@ -96,9 +96,7 @@ func TestPgpass(t *testing.T) {
"client_encoding": "UTF8",
"datestyle": "ISO, MDY",
}
for k, v := range extra {
o[k] = v
}
maps.Copy(o, extra)
have := pgpass.PasswordFromPgpass(o["passfile"], o["user"], o["password"], o["host"], o["port"], o["dbname"])
if have != want {
t.Fatalf("wrong password\nhave: %q\nwant: %q", have, want)
Expand Down Expand Up @@ -1212,7 +1210,6 @@ func TestStmtQueryContext(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
if !pqtest.Pgpool() {
t.Parallel()
Expand Down Expand Up @@ -1256,7 +1253,6 @@ func TestStmtExecContext(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
if !pqtest.Pgpool() {
t.Parallel()
Expand Down Expand Up @@ -1301,7 +1297,7 @@ func TestContextCancelExec(t *testing.T) {
t.Fatalf("unexpected error: %s", err)
}

for i := 0; i < 100; i++ {
for range 100 {
func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down Expand Up @@ -1337,7 +1333,7 @@ func TestContextCancelQuery(t *testing.T) {
t.Fatalf("unexpected error: %s", err)
}

for i := 0; i < 100; i++ {
for range 100 {
func() {
ctx, cancel := context.WithCancel(context.Background())
rows, err := db.QueryContext(ctx, "select 1")
Expand All @@ -1364,7 +1360,7 @@ func TestIssue617(t *testing.T) {
const N = 10

numGoroutineStart := runtime.NumGoroutine()
for i := 0; i < N; i++ {
for range N {
func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand All @@ -1379,7 +1375,7 @@ func TestIssue617(t *testing.T) {
iterations := int(waitTime / delayTime)

var numGoroutineFinish int
for i := 0; i < iterations; i++ {
for range iterations {
time.Sleep(delayTime)

numGoroutineFinish = runtime.NumGoroutine()
Expand Down Expand Up @@ -1426,7 +1422,7 @@ func TestContextCancelBegin(t *testing.T) {
t.Fatalf("unexpected error: %s", err)
}

for i := 0; i < 100; i++ {
for range 100 {
func() {
ctx, cancel := context.WithCancel(context.Background())
tx, err := db.BeginTx(ctx, nil)
Expand Down Expand Up @@ -1692,7 +1688,6 @@ func TestBytea(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
db := pqtest.MustDB(t)
pqtest.Exec(t, db, `create temp table tbl (b bytea)`)
Expand Down Expand Up @@ -1743,7 +1738,6 @@ func TestPreProtocolError(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
f := pqtest.NewFake(t, func(f pqtest.Fake, cn net.Conn) {
Expand Down
28 changes: 10 additions & 18 deletions connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/tls"
"database/sql/driver"
"fmt"
"maps"
"math/rand"
"net"
"net/netip"
Expand Down Expand Up @@ -515,9 +516,7 @@ func NewConfig(dsn string) (Config, error) {
// Clone returns a copy of the [Config].
func (cfg Config) Clone() Config {
rt := make(map[string]string)
for k, v := range cfg.Runtime {
rt[k] = v
}
maps.Copy(rt, cfg.Runtime)
c := cfg
c.Runtime = rt
c.set = append([]string{}, cfg.set...)
Expand Down Expand Up @@ -817,7 +816,7 @@ func (cfg *Config) setFromTag(o map[string]string, tag string, service bool) err
f = "pq: wrong value for $%s: "
}
var (
types = reflect.TypeOf(cfg).Elem()
types = reflect.TypeFor[Config]()
values = reflect.ValueOf(cfg).Elem()
)
for i := 0; i < types.NumField(); i++ {
Expand Down Expand Up @@ -856,7 +855,7 @@ func (cfg *Config) setFromTag(o map[string]string, tag string, service bool) err
default:
return fmt.Errorf("don't know how to set %s: unknown type %s", rt.Name, rt.Type.Kind())
case reflect.Struct:
if rt.Type == reflect.TypeOf(netip.Addr{}) {
if rt.Type == reflect.TypeFor[netip.Addr]() {
if hostaddr {
vv := strings.Split(v, ",")
v = vv[0]
Expand Down Expand Up @@ -949,21 +948,16 @@ func (cfg *Config) setFromTag(o map[string]string, tag string, service bool) err
}
}

// Set run-time; we delete map keys as they're set in the struct. For the
// service file we don't support extra parameters and error out.
if service && len(o) > 0 {
// TODO(go1.23): use maps.Keys once we require Go 1.23.
var key string
for k := range o {
key = k
break
}
maps.Keys(o)(func(k string) bool { key = k; return false })
return fmt.Errorf("pq: unknown setting %q in service file for service %q", key, cfg.Service)
}

// Set run-time; we delete map keys as they're set in the struct.
if !service && tag == "postgres" {
// Make sure database= sets dbname=, as that previously worked (kind of
// by accident).
// TODO(v2): remove
// by accident). TODO(v2): remove
if d, ok := o["database"]; ok {
cfg.Database = d
delete(o, "database")
Expand All @@ -985,7 +979,7 @@ func (cfg Config) tomap() map[string]string {
var (
o = make(map[string]string)
values = reflect.ValueOf(cfg)
types = reflect.TypeOf(cfg)
types = reflect.TypeFor[Config]()
)
for i := 0; i < types.NumField(); i++ {
var (
Expand Down Expand Up @@ -1022,9 +1016,7 @@ func (cfg Config) tomap() map[string]string {
}
}
}
for k, v := range cfg.Runtime {
o[k] = v
}
maps.Copy(o, cfg.Runtime)
return o
}

Expand Down
8 changes: 3 additions & 5 deletions connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func TestNewConnector(t *testing.T) {
`or:pq: database "two" does not exist (3D000)|pq: no such database: two (08P01)`

// Make sure database= consistently take precedence over dbname=
for i := 0; i < 10; i++ {
for range 10 {
_, err := pqtest.DB(t, "database=err")
if !pqtest.ErrorContains(err, want1) {
t.Errorf("wrong error:\nhave: %s\nwant: %s", err, want1)
Expand Down Expand Up @@ -653,7 +653,7 @@ func TestConnectMulti(t *testing.T) {

t.Run("load_balance_hosts=random", func(t *testing.T) {
hosts := [3]int{}
for i := 0; i < 25; i++ {
for range 25 {
connectedTo = [3]bool{}
_ = pqtest.MustDB(t, fmt.Sprintf("host=%s,%s,%s port=%s,%s,%s load_balance_hosts=random",
f1.Host(), f2.Host(), f3.Host(), f1.Port(), f2.Port(), f3.Port()))
Expand Down Expand Up @@ -706,7 +706,6 @@ func TestConnectionTargetSessionAttrs(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -763,7 +762,7 @@ func TestProtocolVersion(t *testing.T) {
key30 = []byte{1, 2, 3, 4}
key32 = make([]byte, 32)
)
for i := 0; i < 32; i++ {
for i := range 32 {
key32[i] = byte(i)
}
accept := func(version float32) (*[]byte, func(f pqtest.Fake, cn net.Conn)) {
Expand Down Expand Up @@ -826,7 +825,6 @@ func TestProtocolVersion(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
have, a := accept(tt.serverVersion)
Expand Down
5 changes: 1 addition & 4 deletions copy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ func TestCopyInError(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
tx := pqtest.Begin(t, pqtest.MustDB(t))
Expand Down Expand Up @@ -96,7 +95,6 @@ func TestCopyInNull(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
db := pqtest.MustDB(t)
Expand Down Expand Up @@ -130,15 +128,14 @@ func TestCopyInMultipleValues(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
db := pqtest.MustDB(t)
tx := pqtest.Begin(t, db)
pqtest.Exec(t, tx, `create temp table tbl (a int, b varchar)`)

stmt := pqtest.Prepare(t, tx, tt.query, db)
for i := 0; i < 500; i++ {
for i := range 500 {
stmt.MustExec(t, int64(i), strings.Repeat("#", 500))
}

Expand Down
2 changes: 0 additions & 2 deletions deprecated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ func TestCopyInStmt(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
have := CopyIn(tt.inTable, tt.inCols...)
Expand Down Expand Up @@ -43,7 +42,6 @@ func TestCopyInSchemaStmt(t *testing.T) {
}

for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
t.Parallel()
have := CopyInSchema(tt.inSchema, tt.inTable, tt.inCols...)
Expand Down
4 changes: 2 additions & 2 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,14 +436,14 @@ func BenchmarkDecode(b *testing.B) {
x := []byte("2013-09-17 22:15:32.360754-07")
f := func(wg *sync.WaitGroup, loops int) {
defer wg.Done()
for i := 0; i < loops; i++ {
for range loops {
decode(&parameterStatus{}, x, oid.T_timestamptz, formatText)
}
}

wg := &sync.WaitGroup{}
b.ResetTimer()
for j := 0; j < 10; j++ {
for range 10 {
wg.Add(1)
go f(wg, b.N/10)
}
Expand Down
2 changes: 1 addition & 1 deletion error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func TestRetryError(t *testing.T) {
})

// Make write fail once so that safeRetryError{} is used.
for i := 0; i < 10; i++ {
for range 10 {
os.Setenv("PQTEST_FAILNUM", "1")
tx, err := db.Begin()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/lib/pq

go 1.21
go 1.23
8 changes: 0 additions & 8 deletions internal/pqtest/pqtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,3 @@ func QueryRow[T any](t testing.TB, db interface {
}
return nil
}

// Null represents a value that may be null.
//
// TODO(go1.22): replace with sql.Null
type Null[T any] struct {
V T
Valid bool
}
4 changes: 2 additions & 2 deletions internal/pqtime/loc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ func BenchmarkLocationCacheMultiThread(b *testing.B) {

f := func(wg *sync.WaitGroup, loops int) {
defer wg.Done()
for i := 0; i < loops; i++ {
for range loops {
globalLocationCache.getLocation(rand.Intn(10000))
}
}

wg := &sync.WaitGroup{}
b.ResetTimer()
for j := 0; j < 10; j++ {
for range 10 {
wg.Add(1)
go f(wg, b.N/10)
}
Expand Down
2 changes: 0 additions & 2 deletions internal/pqtime/pqtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ func TestParse(t *testing.T) {
db := pqtest.MustDB(t, "timezone='Etc/UTC'")
t.Parallel()
for _, tt := range tests {
tt := tt
t.Run(tt.str, func(t *testing.T) {
{ // Parse()
have, err := Parse(nil, tt.str)
Expand Down Expand Up @@ -139,7 +138,6 @@ func TestFormat(t *testing.T) {
db := pqtest.MustDB(t)
t.Parallel()
for _, tt := range tests {
tt := tt
t.Run("", func(t *testing.T) {
{ // Format()
have := string(Format(tt.in))
Expand Down
Loading