Skip to content

Commit

Permalink
*:add feat 'SHOW COLUMNS'
Browse files Browse the repository at this point in the history
  • Loading branch information
hustjieke authored and BohuTANG committed Sep 1, 2018
1 parent bac6baa commit af431e4
Show file tree
Hide file tree
Showing 8 changed files with 1,722 additions and 1,460 deletions.
4 changes: 4 additions & 0 deletions src/proxy/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ func (spanner *Spanner) ComQuery(session *driver.Session, query string, callback
if qr, err = spanner.handleShowCreateTable(session, query, node); err != nil {
log.Error("proxy.show.create.table[%s].from.session[%v].error:%+v", query, session.ID(), err)
}
case sqlparser.ShowColumnsStr:
if qr, err = spanner.handleShowColumns(session, query, node); err != nil {
log.Error("proxy.show.colomns[%s].from.session[%v].error:%+v", query, session.ID(), err)
}
case sqlparser.ShowProcesslistStr:
if qr, err = spanner.handleShowProcesslist(session, query, node); err != nil {
log.Error("proxy.show.processlist[%s].from.session[%v].error:%+v", query, session.ID(), err)
Expand Down
34 changes: 34 additions & 0 deletions src/proxy/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ func (spanner *Spanner) handleShowCreateTable(session *driver.Session, query str
return qr, nil
}

// handleShowColumns used to handle the 'SHOW COLUMNS' command.
func (spanner *Spanner) handleShowColumns(session *driver.Session, query string, node sqlparser.Statement) (*sqltypes.Result, error) {
router := spanner.router
ast := node.(*sqlparser.Show)

table := ast.Table.Name.String()
database := session.Schema()
if !ast.Table.Qualifier.IsEmpty() {
database = ast.Table.Qualifier.String()
}
if database == "" {
return nil, sqldb.NewSQLError(sqldb.ER_NO_DB_ERROR, "")
}
// Check the database ACL.
if err := router.DatabaseACL(database); err != nil {
return nil, err
}

// Get one table from the router.
parts, err := router.Lookup(database, table, nil, nil)
if err != nil {
return nil, err
}
partTable := parts[0].Table
backend := parts[0].Backend
rewritten := fmt.Sprintf("SHOW COLUMNS FROM %s.%s", database, partTable)
qr, err := spanner.ExecuteOnThisBackend(backend, rewritten)
if err != nil {
return nil, err
}

return qr, nil
}

// handleShowProcesslist used to handle the query "SHOW PROCESSLIST".
func (spanner *Spanner) handleShowProcesslist(session *driver.Session, query string, node sqlparser.Statement) (*sqltypes.Result, error) {
sessions := spanner.sessions
Expand Down
179 changes: 179 additions & 0 deletions src/proxy/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ func TestProxyShowTables(t *testing.T) {
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}

// show tables error with sys database.
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show tables from MYSQL"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}
}

func TestProxyShowCreateTable(t *testing.T) {
Expand Down Expand Up @@ -178,6 +188,175 @@ func TestProxyShowCreateTable(t *testing.T) {
got := fmt.Sprintf("%+v", qr.Rows[0])
assert.Equal(t, want, got)
}

// show create table err(no database).
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show create table t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}

// show create table err(system database).
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show create table MYSQL.t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}

// show create table err(database not exist).
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show create table xxx.t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}
}

func TestProxyShowColumns(t *testing.T) {
r1 := &sqltypes.Result{
Fields: []*querypb.Field{
{
Name: "table",
Type: querypb.Type_VARCHAR,
},
{
Name: "create table",
Type: querypb.Type_VARCHAR,
},
},
Rows: [][]sqltypes.Value{
{
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("t1_0000")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("show create table t1_0000")),
},
},
}

r2 := &sqltypes.Result{
Fields: []*querypb.Field{
{
Name: "Field",
Type: querypb.Type_VARCHAR,
},
{
Name: "Type",
Type: querypb.Type_VARCHAR,
},
{
Name: "Null",
Type: querypb.Type_VARCHAR,
},
{
Name: "Key",
Type: querypb.Type_VARCHAR,
},
{
Name: "Default",
Type: querypb.Type_VARCHAR,
},
{
Name: "Extra",
Type: querypb.Type_VARCHAR,
},
},
Rows: [][]sqltypes.Value{
{
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("col_a")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("int(11)")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("YES")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("NULL")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("NULL")),
sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("NULL")),
},
},
}

log := xlog.NewStdLog(xlog.Level(xlog.ERROR))
fakedbs, proxy, cleanup := MockProxy(log)
defer cleanup()
address := proxy.Address()

// fakedbs.
{
fakedbs.AddQueryPattern("use .*", &sqltypes.Result{})
fakedbs.AddQueryPattern("create .*", &sqltypes.Result{})
fakedbs.AddQueryPattern("show create .*", r1)
fakedbs.AddQueryPattern("show columns .*", r2)
}

// create test table.
{
client, err := driver.NewConn("mock", "mock", address, "test", "utf8")
assert.Nil(t, err)
query := "create table t1(id int, b int) partition by hash(id)"
_, err = client.FetchAll(query, -1)
assert.Nil(t, err)
client.Quit()
}

// show create table.
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show create table test.t1"
qr, err := client.FetchAll(query, -1)
assert.Nil(t, err)
want := "[t1 show create table t1]"
got := fmt.Sprintf("%+v", qr.Rows[0])
assert.Equal(t, want, got)
}

// show columns from table
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show columns from test.t1"
qr, err := client.FetchAll(query, -1)
assert.Nil(t, err)
want := "[col_a int(11) YES NULL NULL NULL]"
got := fmt.Sprintf("%+v", qr.Rows[0])
assert.Equal(t, want, got)
}

// show columns from table err(database is empty)
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show columns from t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}

// show columns from table err(sys database:MYSQL)
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show columns from MYSQL.t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}

// show columns from table err(database not exist)
{
client, err := driver.NewConn("mock", "mock", address, "", "utf8")
assert.Nil(t, err)
defer client.Close()
query := "show columns from xxx.t1"
_, err = client.FetchAll(query, -1)
assert.NotNil(t, err)
}
}

func TestProxyShowProcesslist(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions src/vendor/github.com/xelabs/go-mysqlstack/sqlparser/ast.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit af431e4

Please sign in to comment.