dolthub/go-mysql-server

Can't turn on multiStatements when using memory driver

seanlaff opened this issue · 2 comments

If I create an in-memory server and supply multiStatements=true in the connection dsn, mutli statements work. However, I have not been able to find a way to reproduce this behavior when using the the in-memory driver directly- is that an expected limitation?

My usecase: I have tests that depend on mysql and I'm interested in running an in-memory go-mysql-server in such a way that I wouldn't have to worry about port coordination. I thought I could use the driver directly to avoid the networking stack, but maybe I misunderstand the abstractions.

I copied the example from driver/example (Im using main d5876b4)

import (
	"database/sql"
	"testing"

	"github.com/dolthub/go-mysql-server/driver"
	"github.com/dolthub/go-mysql-server/memory"
	msql "github.com/dolthub/go-mysql-server/sql"
)

var provider = memory.NewDBProvider(memory.NewDatabase("mydb"))

type factory struct{}

func (factory) Resolve(name string, options *driver.Options) (string, msql.DatabaseProvider, error) {
	return name, provider, nil
}

func TestMultiStatement(t *testing.T) {
	sql.Register("sqle", driver.New(factory{}, nil))
	db, err := sql.Open("sqle", "")
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("USE mydb")
	if err != nil {
		panic(err)
	}
	const createTwoTables = `CREATE TABLE table1 (id int); CREATE TABLE table2 (id int);`
	_, err = db.Exec(createTwoTables)
	if err != nil {
		panic(err)
	}
	res, err := db.Query("show tables")
	if err != nil {
		panic(err)
	}

	tables := []string{}
	for res.Next() {
		var table string
		res.Scan(&table)
		tables = append(tables, table)
	}
	if len(tables) != 2 {
		t.Fatalf("didn't find both tables, tables: %s", tables)
	}
}

This test fails- which I assume is expected since I have yet to supply the multiStatements flag. I tried a few variations:

Building a conn from the driver, supplying the multiStatements flag, no luck:

	drv := driver.New(factory{}, nil)
	conn, err := drv.OpenConnector("/mydb?multiStatements=true")
        if err != nil {
		panic(err)
	}
	db := sql.OpenDB(conn)

Also tried having my factory implement SessionBuilder, and then supplying the raw Capabilities bit flag directly

func (factory) NewSession(ctx context.Context, id uint32, conn *driver.Connector) (msql.Session, error) {
	sess := msql.NewBaseSessionWithClientServer(conn.Server(), msql.Client{
		Address:      "",
		Capabilities: 1 << 16, // copied from "vitess.io/vitess/go/mysql".CapabilityClientMultiStatements
	}, id)
	return memory.NewSession(sess, provider), nil
}

also no luck.

Would anyone be able to point me in the right direction? I am also happy to make a PR if needed. (I have a mysqldump of my db schema which I'm trying to load, as a precursor to tests).

Looking further, it seems like the driver dir is a separate implementation from the main server. Perhaps I'd be better off trying something like https://pkg.go.dev/google.golang.org/grpc/test/bufconn as a way to avoid using the host's networking stack- though I'm not sure if I'll be able to thread that through as Handler is all private

Closing in favor of #2319, which seems like a better approach