Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit e9244aa

Browse files
authored
Merge pull request #588 from erizocosmico/fix/full-tables
sql/*: fix show tables to match MySQL spec
2 parents fa02b97 + d65ee98 commit e9244aa

File tree

7 files changed

+205
-80
lines changed

7 files changed

+205
-80
lines changed

engine_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,49 @@ var queries = []struct {
800800
{nil},
801801
},
802802
},
803+
{
804+
"SHOW TABLES",
805+
[]sql.Row{
806+
{"mytable"},
807+
{"othertable"},
808+
{"tabletest"},
809+
},
810+
},
811+
{
812+
"SHOW FULL TABLES",
813+
[]sql.Row{
814+
{"mytable", "BASE TABLE"},
815+
{"othertable", "BASE TABLE"},
816+
{"tabletest", "BASE TABLE"},
817+
},
818+
},
819+
{
820+
"SHOW FULL TABLES",
821+
[]sql.Row{
822+
{"mytable", "BASE TABLE"},
823+
{"othertable", "BASE TABLE"},
824+
{"tabletest", "BASE TABLE"},
825+
},
826+
},
827+
{
828+
"SHOW TABLES FROM foo",
829+
[]sql.Row{
830+
{"other_table"},
831+
},
832+
},
833+
{
834+
"SHOW TABLES LIKE '%table'",
835+
[]sql.Row{
836+
{"mytable"},
837+
{"othertable"},
838+
},
839+
},
840+
{
841+
"SHOW TABLES WHERE `Table` = 'mytable'",
842+
[]sql.Row{
843+
{"mytable"},
844+
},
845+
},
803846
}
804847

805848
func TestQueries(t *testing.T) {

sql/analyzer/resolve_database.go

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,53 +11,60 @@ func resolveDatabase(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error
1111

1212
a.Log("resolve database, node of type: %T", n)
1313

14-
switch v := n.(type) {
15-
case *plan.ShowIndexes:
16-
db, err := a.Catalog.Database(a.Catalog.CurrentDatabase())
17-
if err != nil {
18-
return nil, err
19-
}
14+
return n.TransformUp(func(n sql.Node) (sql.Node, error) {
15+
switch v := n.(type) {
16+
case *plan.ShowIndexes:
17+
db, err := a.Catalog.Database(a.Catalog.CurrentDatabase())
18+
if err != nil {
19+
return nil, err
20+
}
2021

21-
nc := *v
22-
nc.Database = db
23-
return &nc, nil
24-
case *plan.ShowTables:
25-
db, err := a.Catalog.Database(a.Catalog.CurrentDatabase())
26-
if err != nil {
27-
return nil, err
28-
}
22+
nc := *v
23+
nc.Database = db
24+
return &nc, nil
25+
case *plan.ShowTables:
26+
var dbName = v.Database.Name()
27+
if dbName == "" {
28+
dbName = a.Catalog.CurrentDatabase()
29+
}
2930

30-
nc := *v
31-
nc.Database = db
32-
return &nc, nil
33-
case *plan.CreateTable:
34-
db, err := a.Catalog.Database(a.Catalog.CurrentDatabase())
35-
if err != nil {
36-
return nil, err
37-
}
31+
db, err := a.Catalog.Database(dbName)
32+
if err != nil {
33+
return nil, err
34+
}
3835

39-
nc := *v
40-
nc.Database = db
41-
return &nc, nil
42-
case *plan.Use:
43-
db, err := a.Catalog.Database(v.Database.Name())
44-
if err != nil {
45-
return nil, err
46-
}
36+
nc := *v
37+
nc.Database = db
38+
return &nc, nil
39+
case *plan.CreateTable:
40+
db, err := a.Catalog.Database(a.Catalog.CurrentDatabase())
41+
if err != nil {
42+
return nil, err
43+
}
4744

48-
nc := *v
49-
nc.Database = db
50-
return &nc, nil
51-
case *plan.ShowCreateDatabase:
52-
db, err := a.Catalog.Database(v.Database.Name())
53-
if err != nil {
54-
return nil, err
55-
}
45+
nc := *v
46+
nc.Database = db
47+
return &nc, nil
48+
case *plan.Use:
49+
db, err := a.Catalog.Database(v.Database.Name())
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
nc := *v
55+
nc.Database = db
56+
return &nc, nil
57+
case *plan.ShowCreateDatabase:
58+
db, err := a.Catalog.Database(v.Database.Name())
59+
if err != nil {
60+
return nil, err
61+
}
5662

57-
nc := *v
58-
nc.Database = db
59-
return &nc, nil
60-
default:
61-
return n, nil
62-
}
63+
nc := *v
64+
nc.Database = db
65+
return &nc, nil
66+
default:
67+
return n, nil
68+
}
69+
})
6370
}

sql/parse/parse.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,35 @@ func convertSet(ctx *sql.Context, n *sqlparser.Set) (sql.Node, error) {
210210
func convertShow(s *sqlparser.Show, query string) (sql.Node, error) {
211211
switch s.Type {
212212
case sqlparser.KeywordString(sqlparser.TABLES):
213-
return plan.NewShowTables(sql.UnresolvedDatabase("")), nil
213+
var dbName string
214+
var filter sql.Expression
215+
var full bool
216+
if s.ShowTablesOpt != nil {
217+
dbName = s.ShowTablesOpt.DbName
218+
full = s.ShowTablesOpt.Full != ""
219+
220+
if s.ShowTablesOpt.Filter != nil {
221+
if s.ShowTablesOpt.Filter.Filter != nil {
222+
var err error
223+
filter, err = exprToExpression(s.ShowTablesOpt.Filter.Filter)
224+
if err != nil {
225+
return nil, err
226+
}
227+
} else if s.ShowTablesOpt.Filter.Like != "" {
228+
filter = expression.NewLike(
229+
expression.NewUnresolvedColumn("Table"),
230+
expression.NewLiteral(s.ShowTablesOpt.Filter.Like, sql.Text),
231+
)
232+
}
233+
}
234+
}
235+
236+
var node sql.Node = plan.NewShowTables(sql.UnresolvedDatabase(dbName), full)
237+
if filter != nil {
238+
node = plan.NewFilter(filter, node)
239+
}
240+
241+
return node, nil
214242
case sqlparser.KeywordString(sqlparser.DATABASES):
215243
return plan.NewShowDatabases(), nil
216244
case sqlparser.KeywordString(sqlparser.FIELDS), sqlparser.KeywordString(sqlparser.COLUMNS):

sql/parse/parse_test.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,54 @@ var fixtures = map[string]sql.Node{
246246
}}),
247247
[]string{"col1", "col2"},
248248
),
249-
`SHOW TABLES`: plan.NewShowTables(sql.UnresolvedDatabase("")),
249+
`SHOW TABLES`: plan.NewShowTables(sql.UnresolvedDatabase(""), false),
250+
`SHOW FULL TABLES`: plan.NewShowTables(sql.UnresolvedDatabase(""), true),
251+
`SHOW TABLES FROM foo`: plan.NewShowTables(sql.UnresolvedDatabase("foo"), false),
252+
`SHOW TABLES IN foo`: plan.NewShowTables(sql.UnresolvedDatabase("foo"), false),
253+
`SHOW FULL TABLES FROM foo`: plan.NewShowTables(sql.UnresolvedDatabase("foo"), true),
254+
`SHOW FULL TABLES IN foo`: plan.NewShowTables(sql.UnresolvedDatabase("foo"), true),
255+
`SHOW TABLES LIKE 'foo'`: plan.NewFilter(
256+
expression.NewLike(
257+
expression.NewUnresolvedColumn("Table"),
258+
expression.NewLiteral("foo", sql.Text),
259+
),
260+
plan.NewShowTables(sql.UnresolvedDatabase(""), false),
261+
),
262+
"SHOW TABLES WHERE `Table` = 'foo'": plan.NewFilter(
263+
expression.NewEquals(
264+
expression.NewUnresolvedColumn("Table"),
265+
expression.NewLiteral("foo", sql.Text),
266+
),
267+
plan.NewShowTables(sql.UnresolvedDatabase(""), false),
268+
),
269+
`SHOW FULL TABLES LIKE 'foo'`: plan.NewFilter(
270+
expression.NewLike(
271+
expression.NewUnresolvedColumn("Table"),
272+
expression.NewLiteral("foo", sql.Text),
273+
),
274+
plan.NewShowTables(sql.UnresolvedDatabase(""), true),
275+
),
276+
"SHOW FULL TABLES WHERE `Table` = 'foo'": plan.NewFilter(
277+
expression.NewEquals(
278+
expression.NewUnresolvedColumn("Table"),
279+
expression.NewLiteral("foo", sql.Text),
280+
),
281+
plan.NewShowTables(sql.UnresolvedDatabase(""), true),
282+
),
283+
`SHOW FULL TABLES FROM bar LIKE 'foo'`: plan.NewFilter(
284+
expression.NewLike(
285+
expression.NewUnresolvedColumn("Table"),
286+
expression.NewLiteral("foo", sql.Text),
287+
),
288+
plan.NewShowTables(sql.UnresolvedDatabase("bar"), true),
289+
),
290+
"SHOW FULL TABLES FROM bar WHERE `Table` = 'foo'": plan.NewFilter(
291+
expression.NewEquals(
292+
expression.NewUnresolvedColumn("Table"),
293+
expression.NewLiteral("foo", sql.Text),
294+
),
295+
plan.NewShowTables(sql.UnresolvedDatabase("bar"), true),
296+
),
250297
`SELECT DISTINCT foo, bar FROM foo;`: plan.NewDistinct(
251298
plan.NewProject(
252299
[]sql.Expression{

sql/plan/show_create_table.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"gopkg.in/src-d/go-mysql-server.v0/sql"
1010
)
1111

12+
// ErrTableNotFound is returned when the table could not be found.
1213
var ErrTableNotFound = errors.NewKind("Table `%s` not found")
1314

1415
// ShowCreateTable is a node that shows the CREATE TABLE statement for a table.
@@ -56,8 +57,8 @@ func (n *ShowCreateTable) String() string {
5657
}
5758

5859
type showCreateTablesIter struct {
59-
db sql.Database
60-
table string
60+
db sql.Database
61+
table string
6162
didIteration bool
6263
}
6364

sql/plan/show_tables.go

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package plan
22

33
import (
4-
"io"
54
"sort"
65

76
"gopkg.in/src-d/go-mysql-server.v0/sql"
@@ -10,12 +9,23 @@ import (
109
// ShowTables is a node that shows the database tables.
1110
type ShowTables struct {
1211
Database sql.Database
12+
Full bool
13+
}
14+
15+
var showTablesSchema = sql.Schema{
16+
{Name: "Table", Type: sql.Text},
17+
}
18+
19+
var showTablesFullSchema = sql.Schema{
20+
{Name: "Table", Type: sql.Text},
21+
{Name: "Table_type", Type: sql.Text},
1322
}
1423

1524
// NewShowTables creates a new show tables node given a database.
16-
func NewShowTables(database sql.Database) *ShowTables {
25+
func NewShowTables(database sql.Database, full bool) *ShowTables {
1726
return &ShowTables{
1827
Database: database,
28+
Full: full,
1929
}
2030
}
2131

@@ -31,12 +41,12 @@ func (*ShowTables) Children() []sql.Node {
3141
}
3242

3343
// Schema implements the Node interface.
34-
func (*ShowTables) Schema() sql.Schema {
35-
return sql.Schema{{
36-
Name: "table",
37-
Type: sql.Text,
38-
Nullable: false,
39-
}}
44+
func (p *ShowTables) Schema() sql.Schema {
45+
if p.Full {
46+
return showTablesFullSchema
47+
}
48+
49+
return showTablesSchema
4050
}
4151

4252
// RowIter implements the Node interface.
@@ -48,12 +58,21 @@ func (p *ShowTables) RowIter(ctx *sql.Context) (sql.RowIter, error) {
4858

4959
sort.Strings(tableNames)
5060

51-
return &showTablesIter{tableNames: tableNames}, nil
61+
var rows = make([]sql.Row, len(tableNames))
62+
for i, n := range tableNames {
63+
row := sql.Row{n}
64+
if p.Full {
65+
row = append(row, "BASE TABLE")
66+
}
67+
rows[i] = row
68+
}
69+
70+
return sql.RowsToRowIter(rows...), nil
5271
}
5372

5473
// TransformUp implements the Transformable interface.
5574
func (p *ShowTables) TransformUp(f sql.TransformNodeFunc) (sql.Node, error) {
56-
return f(NewShowTables(p.Database))
75+
return f(NewShowTables(p.Database, p.Full))
5776
}
5877

5978
// TransformExpressionsUp implements the Transformable interface.
@@ -64,23 +83,3 @@ func (p *ShowTables) TransformExpressionsUp(f sql.TransformExprFunc) (sql.Node,
6483
func (p ShowTables) String() string {
6584
return "ShowTables"
6685
}
67-
68-
type showTablesIter struct {
69-
tableNames []string
70-
idx int
71-
}
72-
73-
func (i *showTablesIter) Next() (sql.Row, error) {
74-
if i.idx >= len(i.tableNames) {
75-
return nil, io.EOF
76-
}
77-
row := sql.NewRow(i.tableNames[i.idx])
78-
i.idx++
79-
80-
return row, nil
81-
}
82-
83-
func (i *showTablesIter) Close() error {
84-
i.tableNames = nil
85-
return nil
86-
}

sql/plan/show_tables_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func TestShowTables(t *testing.T) {
1313
require := require.New(t)
1414
ctx := sql.NewEmptyContext()
1515

16-
unresolvedShowTables := NewShowTables(sql.UnresolvedDatabase(""))
16+
unresolvedShowTables := NewShowTables(sql.UnresolvedDatabase(""), false)
1717

1818
require.False(unresolvedShowTables.Resolved())
1919
require.Nil(unresolvedShowTables.Children())
@@ -23,7 +23,7 @@ func TestShowTables(t *testing.T) {
2323
db.AddTable("test2", mem.NewTable("test2", nil))
2424
db.AddTable("test3", mem.NewTable("test3", nil))
2525

26-
resolvedShowTables := NewShowTables(db)
26+
resolvedShowTables := NewShowTables(db, false)
2727
require.True(resolvedShowTables.Resolved())
2828
require.Nil(resolvedShowTables.Children())
2929

0 commit comments

Comments
 (0)