Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect RowsAffected() result after updated #204

Open
knullism opened this issue Jul 9, 2024 · 3 comments
Open

Incorrect RowsAffected() result after updated #204

knullism opened this issue Jul 9, 2024 · 3 comments

Comments

@knullism
Copy link

knullism commented Jul 9, 2024

Describe the bug
RowsAffected() returned incorrect value.

To Reproduce

package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"

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

func main() {
	server := "???"
	user := "???"
	password := "???"
	port := 1433

	connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d", server, user, password, port)

	conn, err := sql.Open("mssql", connString)

	if err != nil {
		panic(err)
	}

	defer conn.Close()

	ctx := context.Background()

	countrow := conn.QueryRow("select count(id) from objects where id = 1;")

	if err := countrow.Err(); err != nil {
		panic(err)
	}

	var count int64

	err = countrow.Scan(&count)

	if err != nil {
		panic(err)
	}

	log.Println("count", count) // output: 1

	result, err := conn.ExecContext(ctx, "update objects set value = 'test' where id = 1;")

	if err != nil {
		panic(err)
	}

	rowsAffected, _ := result.RowsAffected()

	log.Println("rowsAffected", rowsAffected) // output: 3
}

Output

2024/07/09 13:28:15 count 1
2024/07/09 13:28:15 rowsAffected 3

Expected behavior
Following the reproduce code, it should be 1 that returned from result.RowsAffected().

Further technical details

SQL Server version: SQL Server 2017
go-mssqldb: v1.7.2

@shueybubbles
Copy link
Collaborator

thx for opening an issue!
What was the last version of the driver you used where it returned the correct value?

@shueybubbles
Copy link
Collaborator

Can you add a logger to your repro and add the traces here?
You should see traces like this:

e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.5018429 -0500 CDT m=+1.289748201 [token.go:1049]: got DONE or DONEPROC status=16
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.5018429 -0500 CDT m=+1.289748201 [token.go:1061]: (Rows affected: 1)
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.5018429 -0500 CDT m=+1.289748201 [mssql.go:528]: update #foo set val = N'test' where bar = 1
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.6575046 -0500 CDT m=+1.445412201 [token.go:993]: got token tokenDone
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.658402 -0500 CDT m=+1.446309601 [token.go:1049]: got DONE or DONEPROC status=16
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.658402 -0500 CDT m=+1.446309601 [token.go:1061]: (Rows affected: 1)
    e:\git\go-mssqldb\tds_test.go:387: 2024-07-09 17:22:09.7354126 -0500 CDT m=+1.523321301 [token.go:993]: got token tokenEnvChange

I can't reproduce the issue when I modify TestAffectedRows. This version of the test passes:

func TestAffectedRows(t *testing.T) {
	conn, logger := open(t)
	defer conn.Close()
	defer logger.StopLogging()

	tx, err := conn.Begin()
	if err != nil {
		t.Fatal("Begin tran failed", err)
	}
	defer tx.Rollback()

	res, err := tx.Exec("create table #foo (bar int, val nvarchar(10) null)")
	if err != nil {
		t.Fatal("create table failed")
	}
	n, err := res.RowsAffected()
	if err != nil {
		t.Fatal("rows affected failed")
	}
	if n != 0 {
		t.Error("Expected 0 rows affected, got ", n)
	}

	res, err = tx.Exec("insert into #foo (bar) values (1)")
	if err != nil {
		t.Fatal("insert failed")
	}
	n, err = res.RowsAffected()
	if err != nil {
		t.Fatal("rows affected failed")
	}
	if n != 1 {
		t.Error("Expected 1 row affected, got ", n)
	}

	res, err = tx.Exec("insert into #foo (bar) values (@p1)", 2)
	if err != nil {
		t.Fatal("insert failed", err)
	}
	n, err = res.RowsAffected()
	if err != nil {
		t.Fatal("rows affected failed")
	}
	if n != 1 {
		t.Error("Expected 1 row affected, got ", n)
	}
	// Regression test for https://github.com/microsoft/go-mssqldb/issues/204
	countrow := tx.QueryRow("select count(bar) from #foo where bar = 1;")
	if err := countrow.Err(); err != nil {
		t.Fatal("QueryRow failed ", err)
	}
	var count int64
	err = countrow.Scan(&count)
	if err != nil || count != 1 {
		t.Fatal("Unexpected error or count from QueryRow:", err, count)
	}
	res, err = tx.Exec("update #foo set val = N'test' where bar = 1")
	if err != nil {
		t.Fatal("update failed", err)
	}
	n, err = res.RowsAffected()
	if err != nil {
		t.Fatal("rows affected failed after update")
	}
	if n != 1 {
		t.Error("Expected 1 row affected for update, got ", n)
	}

}

@brijesh-amin
Copy link

Not able to re produce

image

docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Test1234@" -p 1433:1433 mcr.microsoft.com/mssql/server:2017-latest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants