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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy