Skip to content

contrib/database/sql: panic: sqltrace.OpenDB: driver is not registered via sqltrace.Register #1634

@tsbkw

Description

@tsbkw

TL;DR

If we use some driver which implement driver.DriverContext interface, and call Register with driver struct(not a pointer to driver struct), it panic with panic: sqltrace.OpenDB: driver is not registered via sqltrace.Register.

It may be better to prevent error even if struct is passed when calling Register, but at least document should be fixed.

Details

In the example below, driver.Driver is passed as struct, and reflect.TypeOf(driver) is added to map.

// sqltrace.Register("pq", pq.Driver{})
// db, err := sqltrace.Open("pq", "postgres://pqgotest:password@localhost...")

Later when user call OpenDB, reflect.TypeOf(driver) is looked up in d.keys, therefore driver added and looked up must have same type. For example, if added type is struct, looked up by struct. And if added type is pointer of struct, looked up by pointer of struct.

name, ok := d.keys[reflect.TypeOf(driver)]

This behavior is not a problem when driver doesn't implement driver.DriverContext interface, because in this case driver get from map driver is used when lookup and type of these always same.

return OpenDB(&dsnConnector{dsn: dataSourceName, driver: d}, opts...), nil

However when driver implement driver.DriverContext, user must care whether type is pointer or not when calling Register.

Driver in lib/pq currently not implement driver.DriverContext but soon it will implement. see: lib/pq#900

The problem can be reproduced by code below with github.com/go-sql-driver/mysql. (You can see full code at https://go.dev/play/p/4g6-qwh9TqF but you have to run it locally.)

	sqltrace.Register("mysql", mysql.MySQLDriver{})
	_, err := sqltrace.Open("mysql", "user:password@tcp(localhost:3306)/db")
	fmt.Printf("err with mysql.MySQLDriver{} %v\n", err)

This print panic: sqltrace.OpenDB: driver is not registered via sqltrace.Register with stacktrace.

The error can be avoided by passing by pointer like below.

	sqltrace.Register("mysql", &mysql.MySQLDriver{})
	_, err2 := sqltrace.Open("mysql", "user:password@tcp(localhost:3306)/dbe")
	fmt.Printf("err with &mysql.MySQLDriver{} %v\n", err2)

This print err with &mysql.MySQLDriver{} <nil>.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apm:ecosystemcontrib/* related feature requests or bugsbugunintended behavior that has to be fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions