Making Virtual Table Implementation Multi Tenant
mustafaakin opened this issue · comments
I'm building a virtual table implementation that connects to another store and lets users query this data. My current approach is to register driver per each tenant, but I'm not sure if that's the best approach.
driverName := "sqlite3_" + *accountId
sql.Register(driverName, &sqlite3.SQLiteDriver{
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
module := internal.NewSQLiteModule(db, *accountId, schema)
return conn.CreateModule("mymodule", module)
},
})
sqlite, err := sql.Open(driverName, ":memory:")
Is there anyway I can access the connection string with custom variables in modules so that driver is not duplicated?
sqlite, err := sql.Open(driverName, ":memory:?accountId=123")
There does not seem to be a method available on sqlite3.SQLiteConn
that I can use.
Perhaps OpenDB
will be of use. You can implement driver.Connector
yourself, and do whatever you need in the Connect
method.
I've used the following code (which could be much better):
type Driver struct {
db *sql.DB
schema *Schema
}
func RegisterDriver(db *sql.DB, schema *Schema) {
sql.Register(DriverName, &Driver{db, schema})
}
func (d *Driver) Open(name string) (driver.Conn, error) {
// todo: use actual URI parser
params := strings.Split(name, "?")
if len(params) <= 1 {
return nil, fmt.Errorf("no connection string")
}
params = strings.Split(params[1], "&")
found := false
var accountId string
for _, p := range params {
kv := strings.Split(p, "=")
if kv[0] == "account" {
accountId = kv[1]
found = true
}
}
if !found {
return nil, fmt.Errorf("account param not found")
}
store := NewStore(accountId, d.db)
myDriver := &sqlite3.SQLiteDriver{
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
module := NewSQLiteModule(store, schema)
return conn.CreateModule("my_module", module)
},
}
return myDriver.Open(name)
}