From 4a44d25ff4e324887886da7d5708a004782d983b Mon Sep 17 00:00:00 2001 From: Michael Demmer Date: Mon, 29 Jan 2018 14:59:29 -0800 Subject: [PATCH] add proxy support for other statements This allows EXPLAIN and other such statements to go through without query normalization. --- go/vt/mysqlproxy/mysqlproxy.go | 20 ++++++++++++++------ go/vt/vtqueryserver/endtoend_test.go | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/go/vt/mysqlproxy/mysqlproxy.go b/go/vt/mysqlproxy/mysqlproxy.go index 23e5e4b7e5c..e89471d7039 100644 --- a/go/vt/mysqlproxy/mysqlproxy.go +++ b/go/vt/mysqlproxy/mysqlproxy.go @@ -70,10 +70,12 @@ func (mp *Proxy) Execute(ctx context.Context, session *ProxySession, sql string, err = mp.doRollback(ctx, session) case sqlparser.StmtSet: result, err = mp.doSet(ctx, session, sql, bindVariables) + case sqlparser.StmtInsert, sqlparser.StmtUpdate, sqlparser.StmtDelete, sqlparser.StmtReplace: + result, err = mp.executeDML(ctx, session, sql, bindVariables) case sqlparser.StmtSelect: - result, err = mp.doSelect(ctx, session, sql, bindVariables) + result, err = mp.executeSelect(ctx, session, sql, bindVariables) default: - result, err = mp.doExecuteDML(ctx, session, sql, bindVariables) + result, err = mp.executeOther(ctx, session, sql, bindVariables) } if err != nil { @@ -162,12 +164,13 @@ func (mp *Proxy) doSet(ctx context.Context, session *ProxySession, sql string, b return &sqltypes.Result{}, nil } -// doSelect runs the given select -func (mp *Proxy) doSelect(ctx context.Context, session *ProxySession, sql string, bindVariables map[string]*querypb.BindVariable) (*sqltypes.Result, error) { +// executeSelect runs the given select statement +func (mp *Proxy) executeSelect(ctx context.Context, session *ProxySession, sql string, bindVariables map[string]*querypb.BindVariable) (*sqltypes.Result, error) { if mp.normalize { query, comments := sqlparser.SplitTrailingComments(sql) stmt, err := sqlparser.Parse(query) if err != nil { + fmt.Printf("YYY parse error %s\n", query) return nil, err } sqlparser.Normalize(stmt, bindVariables, "vtp") @@ -178,8 +181,8 @@ func (mp *Proxy) doSelect(ctx context.Context, session *ProxySession, sql string return mp.qs.Execute(ctx, mp.target, sql, bindVariables, session.TransactionID, session.Options) } -// doExecuteDML runs the given query handling autocommit semantics -func (mp *Proxy) doExecuteDML(ctx context.Context, session *ProxySession, sql string, bindVariables map[string]*querypb.BindVariable) (*sqltypes.Result, error) { +// executeDML runs the given query handling autocommit semantics +func (mp *Proxy) executeDML(ctx context.Context, session *ProxySession, sql string, bindVariables map[string]*querypb.BindVariable) (*sqltypes.Result, error) { if mp.normalize { query, comments := sqlparser.SplitTrailingComments(sql) stmt, err := sqlparser.Parse(query) @@ -216,3 +219,8 @@ func (mp *Proxy) doExecuteDML(ctx context.Context, session *ProxySession, sql st return result, nil } } + +// executeOther runs the given other statement bypassing the normalizer +func (mp *Proxy) executeOther(ctx context.Context, session *ProxySession, sql string, bindVariables map[string]*querypb.BindVariable) (*sqltypes.Result, error) { + return mp.qs.Execute(ctx, mp.target, sql, bindVariables, session.TransactionID, session.Options) +} diff --git a/go/vt/vtqueryserver/endtoend_test.go b/go/vt/vtqueryserver/endtoend_test.go index b855559a7e7..b04a0bb8a58 100644 --- a/go/vt/vtqueryserver/endtoend_test.go +++ b/go/vt/vtqueryserver/endtoend_test.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/youtube/vitess/go/mysql" + "github.com/youtube/vitess/go/sqltypes" "github.com/youtube/vitess/go/vt/dbconfigs" "github.com/youtube/vitess/go/vt/vttablet/tabletserver" "github.com/youtube/vitess/go/vt/vttablet/tabletserver/tabletenv" @@ -113,7 +114,7 @@ create table test(id int, val varchar(256), primary key(id)); create table valtest(intval int default 0, floatval float default null, charval varchar(256) default null, binval varbinary(256) default null, primary key(intval)); ` -func testFetch(t *testing.T, conn *mysql.Conn, sql string, expectedRows int) { +func testFetch(t *testing.T, conn *mysql.Conn, sql string, expectedRows int) *sqltypes.Result { t.Helper() result, err := conn.ExecuteFetch(sql, 1000, false) @@ -124,6 +125,8 @@ func testFetch(t *testing.T, conn *mysql.Conn, sql string, expectedRows int) { if len(result.Rows) != expectedRows { t.Errorf("expected %d rows but got %d", expectedRows, len(result.Rows)) } + + return result } func testDML(t *testing.T, conn *mysql.Conn, sql string, expectedNumQueries int64, expectedRowsAffected uint64) { @@ -297,3 +300,15 @@ func TestNoAutocommit(t *testing.T) { testFetch(t, conn, "select * from test", 0) testFetch(t, conn2, "select * from test", 0) } + +func TestOther(t *testing.T) { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &proxyConnParams) + if err != nil { + t.Fatal(err) + } + + testFetch(t, conn, "explain select * from test", 1) + testFetch(t, conn, "select table_name, table_rows from information_schema.tables where table_name='test'", 1) + +}