mattn / go-sqlite3

sqlite3 driver for go using database/sql

Home Page:http://mattn.github.io/go-sqlite3

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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)
}