denisenkom / go-mssqldb

Microsoft SQL server driver written in go language
BSD 3-Clause "New" or "Revised" License
1.81k stars 493 forks source link

connection not closed when database name is incorrect #798

Open jatinn opened 4 months ago

jatinn commented 4 months ago

Describe the bug

If a database name is provided that does not exist, we get back an error however even though db.Close() is executed the network connection still remains open.

To Reproduce

package main

import (
    "context"
    "database/sql"
    "flag"
    "fmt"
    "os"
    "os/signal"

    _ "github.com/denisenkom/go-mssqldb"
)

func main() {
    var (
        username = "sa"
        password = "Password123"
        hostname = "127.0.0.1"
        port     = 1433
        database = flag.String("db", "master", "database name")
        count    = flag.Int("count", 1, "number of calls to make to the database")
    )

    flag.Parse()

    dsn := fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", username, password, hostname, port, *database)

    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    defer stop()

    for i := 0; i < *count; i++ {
        if err := doQuery(ctx, dsn); err != nil {
            fmt.Println("error running query", i+1, err.Error())
        } else {
            fmt.Printf("run %d done\n", i+1)
        }
    }
    fmt.Println("waiting for ctrl+c to exit")
    <-ctx.Done()
}

func doQuery(ctx context.Context, dsn string) error {
    db, err := sql.Open("sqlserver", dsn)
    if err != nil {
        return fmt.Errorf("error open db %w", err)
    }
    defer db.Close()

    row := db.QueryRowContext(ctx, "SELECT 1")
    var result int
    if err := row.Scan(&result); err != nil {
        return fmt.Errorf("error scanning row %w", err)
    }

    return nil
}

If you provide a database name that exists then should see the following, before sending the exit signal if you look for connections to the database it will be in TIME_WAIT

❯ go run main.go -db exists
run 1 done
waiting for ctrl+c to exit

# new terminal
❯ netstat -an | grep '1.1433'
tcp4       0      0  127.0.0.1.60859        127.0.0.1.1433         TIME_WAIT

However if you provide a database name that does not exist then the connection remains ESTABLISHED even though it should have been closed.

❯ go run main.go -db unknown
error running query 1 error scanning row mssql: login error: Cannot open database "unknown" that was requested by the login. Using the user default database "master" instead.
waiting for ctrl+c to exit

# new terminal
❯ netstat -an | grep '1.1433'
tcp4       0      0  127.0.0.1.1433         127.0.0.1.60894        ESTABLISHED
tcp4       0      0  127.0.0.1.60894        127.0.0.1.1433         ESTABLISHED

Expected behavior The network connection should be closed

Further technical details

SQL Server version: docker image mcr.microsoft.com/mssql/server:2022-latest Operating system: macOS 13.6.3