-
Notifications
You must be signed in to change notification settings - Fork 44
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
runtime error: comparing uncomparable type mssql.Error #56
Comments
can you provide the code you are using? |
package mssql_test
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"net"
"testing"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
gomssql "github.com/microsoft/go-mssqldb"
"github.com/qustavo/sqlhooks/v2"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
const ddlTestFunc = `create procedure test_proc AS
begin
DECLARE @ErrorMsg varchar(7000)
SET NOCOUNT ON;
select @ErrorMsg = 'Test error'
raiserror(@ErrorMsg, 16, 1)
return
end;`
func TestMsSQL(t *testing.T) {
ctx := context.Background()
req := testcontainers.ContainerRequest{
Image: "mcr.microsoft.com/mssql/server:2019-latest",
ExposedPorts: []string{"1433/tcp"},
SkipReaper: true,
Env: map[string]string{
"ACCEPT_EULA": "Y",
"MSSQL_PID": "Evaluation",
"MSSQL_SA_PASSWORD": "Test87654321",
},
WaitingFor: wait.ForSQL("1433/tcp", "sqlserver", func(host string, port nat.Port) string {
return fmt.Sprintf("sqlserver://sa:Test87654321@%s/master", net.JoinHostPort(host, port.Port()))
}),
HostConfigModifier: func(hc *container.HostConfig) {
hc.AutoRemove = true
},
}
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
Logger: testcontainers.TestLogger(t),
})
require.NoError(t, err)
t.Cleanup(func() {
container.Stop(ctx, nil)
})
hostPort, err := container.PortEndpoint(ctx, "1433/tcp", "")
require.NoError(t, err)
connStr := fmt.Sprintf("sqlserver://sa:Test87654321@%s/master", hostPort)
t.Log(connStr)
db := openDB(connStr, []sqlhooks.Hooks{simpleHook{}})
_, err = db.Exec(ddlTestFunc)
require.NoError(t, err)
_, err = db.Exec(`EXEC test_proc`)
require.Error(t, err, "error is: %v", err)
}
type simpleHook struct{}
func (h simpleHook) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
return ctx, nil
}
func (h simpleHook) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
return ctx, nil
}
func (h simpleHook) OnError(ctx context.Context, err error, query string, args ...interface{}) error {
return err
}
// openDB opens new sql DB pool with an optional hooks and optional tracing.
func openDB(dsn string, hooks []sqlhooks.Hooks) *sql.DB {
var drv driver.Driver = &gomssql.Driver{}
if len(hooks) > 0 {
drv = sqlhooks.Wrap(drv, sqlhooks.Compose(hooks...))
}
// Open DB connections pool.
return sql.OpenDB(&connector{
driver: drv, dsn: dsn,
})
}
// connector is a connector with dsn and driver.
type connector struct {
driver driver.Driver
dsn string
}
// Connect returns a connection to the database.
func (c *connector) Connect(_ context.Context) (driver.Conn, error) {
return c.driver.Open(c.dsn)
}
// Driver returns the underlying Driver of the Connector.
func (c *connector) Driver() driver.Driver {
return c.driver
} |
@qustavo |
sorry @tochka for the late reply. Unfortunately I haven't had the capacity nor the possibility to experiment with mssql. Have you tried to debug it? |
@qustavo just test this code
|
And more complex example Will reproduce with any error containing a slice or map, passed by value, and if sqlhooks.Compose is used. package main
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"github.com/qustavo/sqlhooks/v2"
)
// similar to https://github.com/microsoft/go-mssqldb/blob/main/error.go#L13
type mssqlError struct{
All []string
}
func (m mssqlError) Error() string {
return ""
}
// fakeHook satisfies the sqlhook.fakeHook interface
type fakeHook struct{}
func (h *fakeHook) OnError(ctx context.Context, err error, query string, args ...interface{}) error {
return mssqlError{}
}
// Before hook will print the query with it's args and return the context with the timestamp
func (h *fakeHook) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
return ctx, nil
}
// After hook will get the timestamp registered on the Before hook and print the elapsed time
func (h *fakeHook) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
return ctx, nil
}
var _ driver.Connector = (*fakeConnector)(nil)
var _ sqlhooks.Hooks = (*fakeHook)(nil)
var _ sqlhooks.OnErrorer = (*fakeHook)(nil)
type fakeConnector struct {
driver driver.Driver
}
func (f fakeConnector) Connect(ctx context.Context) (driver.Conn, error) {
return f.driver.Open("fake")
}
func (f fakeConnector) Driver() driver.Driver {
//TODO implement me
panic("implement me")
}
type fakeDriver struct{}
func (f fakeDriver) Open(name string) (driver.Conn, error) {
//TODO implement me
return &fakeConn{}, nil
}
var _ driver.Driver = (*fakeDriver)(nil)
type fakeTx struct{}
func (f fakeTx) Commit() error {
//TODO implement me
panic("implement me")
}
func (f fakeTx) Rollback() error {
//TODO implement me
panic("implement me")
}
var _ driver.Tx = (*fakeTx)(nil)
type fakeConn struct{}
func (f fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
return nil, mssqlError{}
}
func (f fakeConn) Ping(ctx context.Context) error {
//TODO implement me
return nil
}
func (f fakeConn) Prepare(query string) (driver.Stmt, error) {
//TODO implement me
return fakeStmt{}, nil
}
func (f fakeConn) Close() error {
//TODO implement me
return nil
}
func (f fakeConn) Begin() (driver.Tx, error) {
//TODO implement me
panic("implement me")
}
func (f fakeConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
//TODO implement me
panic("implement me")
}
var _ driver.Conn = (*fakeConn)(nil)
var _ driver.ConnBeginTx = (*fakeConn)(nil)
var _ driver.Queryer = (*fakeConn)(nil)
type fakeStmt struct{}
func (f fakeStmt) Close() error {
//TODO implement me
return nil
}
func (f fakeStmt) NumInput() int {
//TODO implement me
return 0
}
func (f fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
//TODO implement me
panic("implement me")
}
func (f fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
//TODO implement me
return nil, mssqlError{}
}
var _ driver.Stmt = (*fakeStmt)(nil)
func main() {
drv := sqlhooks.Wrap(fakeDriver{}, sqlhooks.Compose(&fakeHook{}))
// Open DB connections pool.
db := sql.OpenDB(&fakeConnector{
driver: drv,
})
func() {
defer func() {
if recovered := recover(); recovered == nil {
fmt.Println("sqlhooks bug is already fixed. check codebase and upgrade. original issue https://github.com/qustavo/sqlhooks/issues/56")
} else {
fmt.Println("panic as expected: ", recovered)
}
}()
_, _ = db.Query("select 1")
}()
_ = db.Close()
} |
Hi from Testcontainers for Go 👋 I think it could be useful to allow developers to run the integration tests while developing this project. I saw they are skipped unless the DSN env var is set. Using tc-go would help in providing the same experience running the tests on CI and locally. Please let us know if we can help here 🙏 |
I've got a panic when using your library (2.1.0) with
github.com/microsoft/[email protected]
sql driver.Stack trace
The text was updated successfully, but these errors were encountered: