mirror of https://github.com/lib/pq.git
159 lines
3.5 KiB
Go
159 lines
3.5 KiB
Go
package pq
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestIssue494(t *testing.T) {
|
|
db := openTestConn(t)
|
|
defer db.Close()
|
|
|
|
query := `CREATE TEMP TABLE t (i INT PRIMARY KEY)`
|
|
if _, err := db.Exec(query); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
txn, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := txn.Prepare(CopyIn("t", "i")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := txn.Query("SELECT 1"); err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
}
|
|
|
|
func TestIssue1046(t *testing.T) {
|
|
ctxTimeout := time.Second * 2
|
|
|
|
db := openTestConn(t)
|
|
defer db.Close()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), ctxTimeout)
|
|
defer cancel()
|
|
|
|
stmt, err := db.PrepareContext(ctx, `SELECT pg_sleep(10) AS id`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var d []uint8
|
|
err = stmt.QueryRowContext(ctx).Scan(&d)
|
|
dl, _ := ctx.Deadline()
|
|
since := time.Since(dl)
|
|
if since > ctxTimeout {
|
|
t.Logf("FAIL %s: query returned after context deadline: %v\n", t.Name(), since)
|
|
t.Fail()
|
|
}
|
|
if pgErr := (*Error)(nil); !(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
|
|
t.Logf("ctx.Err(): [%T]%+v\n", ctx.Err(), ctx.Err())
|
|
t.Logf("got err: [%T] %+v expected errCode: %v", err, err, cancelErrorCode)
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestIssue1062(t *testing.T) {
|
|
db := openTestConn(t)
|
|
defer db.Close()
|
|
|
|
// Ensure that cancelling a QueryRowContext does not result in an ErrBadConn.
|
|
|
|
for i := 0; i < 100; i++ {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
go cancel()
|
|
row := db.QueryRowContext(ctx, "select 1")
|
|
|
|
var v int
|
|
err := row.Scan(&v)
|
|
if pgErr := (*Error)(nil); err != nil &&
|
|
err != context.Canceled &&
|
|
!(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
|
|
t.Fatalf("Scan resulted in unexpected error %v for canceled QueryRowContext at attempt %d", err, i+1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func connIsValid(t *testing.T, db *sql.DB) {
|
|
t.Helper()
|
|
|
|
ctx := context.Background()
|
|
conn, err := db.Conn(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
// the connection must be valid
|
|
err = conn.PingContext(ctx)
|
|
if err != nil {
|
|
t.Errorf("PingContext err=%#v", err)
|
|
}
|
|
// close must not return an error
|
|
err = conn.Close()
|
|
if err != nil {
|
|
t.Errorf("Close err=%#v", err)
|
|
}
|
|
}
|
|
|
|
func TestQueryCancelRace(t *testing.T) {
|
|
db := openTestConn(t)
|
|
defer db.Close()
|
|
|
|
// cancel a query while executing on Postgres: must return the cancelled error code
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
go func() {
|
|
time.Sleep(10 * time.Millisecond)
|
|
cancel()
|
|
}()
|
|
row := db.QueryRowContext(ctx, "select pg_sleep(0.5)")
|
|
var pgSleepVoid string
|
|
err := row.Scan(&pgSleepVoid)
|
|
if pgErr := (*Error)(nil); !(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
|
|
t.Fatalf("expected cancelled error; err=%#v", err)
|
|
}
|
|
|
|
// get a connection: it must be a valid
|
|
connIsValid(t, db)
|
|
}
|
|
|
|
// Test cancelling a scan after it is started. This broke with 1.10.4.
|
|
func TestQueryCancelledReused(t *testing.T) {
|
|
db := openTestConn(t)
|
|
defer db.Close()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
// run a query that returns a lot of data
|
|
rows, err := db.QueryContext(ctx, "select generate_series(1, 10000)")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// scan the first value
|
|
if !rows.Next() {
|
|
t.Error("expected rows.Next() to return true")
|
|
}
|
|
var i int
|
|
err = rows.Scan(&i)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if i != 1 {
|
|
t.Error(i)
|
|
}
|
|
|
|
// cancel the context and close rows, ignoring errors
|
|
cancel()
|
|
rows.Close()
|
|
|
|
// get a connection: it must be valid
|
|
connIsValid(t, db)
|
|
}
|