go-ora: Error "write tcp ...: i/o timeout" from sql.Conn.QueryRowContext together with sql.DB.PingContext
I have noticed that sql.Conn.QueryRowContext delivers an error in a case where sql.DB.PingContext was used before to check the database connection. I have stripped down the issue to a test case that I have provided below. It looks like this error occurs only when PingContext is used and the timeout of the context for PingContext is reached before the query runs, even though the context is canceled after after PingContext. This error does not occur when PingContext is used with context.Background() as ctx.
package main
import (
"context"
"database/sql"
"fmt"
"os"
"time"
_ "github.com/sijms/go-ora/v2"
)
func dieOnError(msg string, err error) {
if err != nil {
fmt.Println(msg, err)
os.Exit(1)
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage:")
fmt.Println("\thello_sql oracle://user:pass@server/service_name")
fmt.Println()
os.Exit(1)
}
connStr := os.ExpandEnv(os.Args[1])
db, err := sql.Open("oracle", connStr)
dieOnError("Can't open connection:", err)
defer db.Close()
ctx1 := context.Background()
ctx2, cancel := context.WithTimeout(ctx1, 1*time.Second)
if err = db.PingContext(ctx2); err != nil {
fmt.Printf("connection ping failed: %s\n", err)
}
cancel()
fmt.Println("Successfully connected.")
conn, err := db.Conn(ctx1)
defer conn.Close()
val := 0
r := conn.QueryRowContext(ctx1, "select 1 from dual where 1 = 1")
err = r.Scan(&val)
if err != nil {
if err == sql.ErrNoRows {
fmt.Println("no rows")
} else {
dieOnError("unknown error:", err)
}
}
fmt.Println("1 done")
time.Sleep(2 * time.Second)
r = conn.QueryRowContext(ctx1, "select 1 from dual where 1 = 1")
err = r.Scan(&val)
if err != nil {
if err == sql.ErrNoRows {
fmt.Println("no rows")
} else {
dieOnError("unknown error:", err)
}
}
fmt.Println("2 done")
}
Terminal output:
go run main.go oracle://user:pass@db:1521/service
Successfully connected.
1 done
unknown error: write tcp 10.0.2.15:34744->172.23.2.197:1521: i/o timeout
exit status 1
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 18 (5 by maintainers)
Commits related to this issue
- Fixed https://github.com/sijms/go-ora/issues/213 When using QueryRow or QueryRowContext the context is permanently attached to a new Connection, because Connect is called with the same Context. Accor... — committed to falco467/go-ora by falco467 2 years ago
- Merge pull request #238 from falco467/patch-1 Fixed https://github.com/sijms/go-ora/issues/213 — committed to sijms/go-ora by sijms 2 years ago
- Fixed context and deadline in v2 https://github.com/sijms/go-ora/issues/213 — committed to falco467/go-ora by falco467 2 years ago
Starting and ending the context of the session in OpenWithContext() looks like the right thing to do for me. In addition, I can confirm the testcase is now fixed in the PR fork falco467/go-ora. 👍