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

Commit a658b4c

Browse files
committed
sql: implement SHOW CREATE DATABASE statement
Signed-off-by: Miguel Molina <miguel@erizocosmi.co>
1 parent 6a6452a commit a658b4c

File tree

7 files changed

+183
-12
lines changed

7 files changed

+183
-12
lines changed

engine_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,13 @@ var queries = []struct {
506506
`,
507507
[]sql.Row{},
508508
},
509+
{
510+
`SHOW CREATE DATABASE mydb`,
511+
[]sql.Row{{
512+
"mydb",
513+
"CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */",
514+
}},
515+
},
509516
}
510517

511518
func TestQueries(t *testing.T) {

sql/analyzer/resolve_database.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ func resolveDatabase(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error
4545
return nil, err
4646
}
4747

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+
}
56+
4857
nc := *v
4958
nc.Database = db
5059
return &nc, nil

sql/parse/parse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"strconv"
1010
"strings"
1111

12-
"github.com/opentracing/opentracing-go"
12+
opentracing "github.com/opentracing/opentracing-go"
1313
"github.com/sirupsen/logrus"
1414
"gopkg.in/src-d/go-errors.v1"
1515
"gopkg.in/src-d/go-mysql-server.v0/sql"

sql/parse/parse_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,10 @@ var fixtures = map[string]sql.Node{
825825
{Table: plan.NewUnresolvedTable("bar", ""), Write: true},
826826
{Table: plan.NewUnresolvedTable("baz", "")},
827827
}),
828+
`SHOW CREATE DATABASE foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false),
829+
`SHOW CREATE SCHEMA foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false),
830+
`SHOW CREATE DATABASE IF NOT EXISTS foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true),
831+
`SHOW CREATE SCHEMA IF NOT EXISTS foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true),
828832
}
829833

830834
func TestParse(t *testing.T) {

sql/parse/show_create.go

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,70 @@ func parseShowCreate(s string) (sql.Node, error) {
1717
r := bufio.NewReader(strings.NewReader(s))
1818

1919
var thingToShow string
20-
var name string
21-
steps := []parseFunc{
20+
err := parseFuncs{
2221
expect("show"),
2322
skipSpaces,
2423
expect("create"),
2524
skipSpaces,
2625
readIdent(&thingToShow),
2726
skipSpaces,
28-
readIdent(&name),
29-
skipSpaces,
30-
checkEOF,
27+
}.exec(r)
28+
if err != nil {
29+
return nil, err
3130
}
3231

33-
for _, step := range steps {
34-
if err := step(r); err != nil {
32+
switch strings.ToLower(thingToShow) {
33+
case "table":
34+
var name string
35+
36+
err := parseFuncs{
37+
readIdent(&name),
38+
skipSpaces,
39+
checkEOF,
40+
}.exec(r)
41+
if err != nil {
3542
return nil, err
3643
}
37-
}
3844

39-
switch strings.ToLower(thingToShow) {
40-
case "table":
4145
return plan.NewShowCreateTable(
4246
sql.UnresolvedDatabase("").Name(),
4347
nil,
4448
name), nil
49+
case "database", "schema":
50+
var ifNotExists bool
51+
var next string
52+
if err := readIdent(&next)(r); err != nil {
53+
return nil, err
54+
}
55+
56+
if next == "if" {
57+
ifNotExists = true
58+
err := parseFuncs{
59+
skipSpaces,
60+
expect("not"),
61+
skipSpaces,
62+
expect("exists"),
63+
skipSpaces,
64+
readIdent(&next),
65+
}.exec(r)
66+
if err != nil {
67+
return nil, err
68+
}
69+
}
70+
71+
err = parseFuncs{
72+
skipSpaces,
73+
checkEOF,
74+
}.exec(r)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
return plan.NewShowCreateDatabase(
80+
sql.UnresolvedDatabase(next),
81+
ifNotExists,
82+
), nil
4583
default:
46-
return nil, errUnsupportedShowCreateQuery.New(name)
84+
return nil, errUnsupportedShowCreateQuery.New(thingToShow)
4785
}
4886
}

sql/plan/show_create_database.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package plan
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"gopkg.in/src-d/go-mysql-server.v0/sql"
8+
)
9+
10+
// ShowCreateDatabase returns the SQL for creating a database.
11+
type ShowCreateDatabase struct {
12+
Database sql.Database
13+
IfNotExists bool
14+
}
15+
16+
const defaultCharacterSet = "utf8mb4"
17+
18+
var showCreateDatabaseSchema = sql.Schema{
19+
{Name: "Database", Type: sql.Text},
20+
{Name: "Create Database", Type: sql.Text},
21+
}
22+
23+
// NewShowCreateDatabase creates a new ShowCreateDatabase node.
24+
func NewShowCreateDatabase(db sql.Database, ifNotExists bool) *ShowCreateDatabase {
25+
return &ShowCreateDatabase{db, ifNotExists}
26+
}
27+
28+
// RowIter implements the sql.Node interface.
29+
func (s *ShowCreateDatabase) RowIter(ctx *sql.Context) (sql.RowIter, error) {
30+
var name = s.Database.Name()
31+
32+
var buf bytes.Buffer
33+
34+
buf.WriteString("CREATE DATABASE ")
35+
if s.IfNotExists {
36+
buf.WriteString("/*!32312 IF NOT EXISTS*/ ")
37+
}
38+
39+
buf.WriteRune('`')
40+
buf.WriteString(name)
41+
buf.WriteRune('`')
42+
buf.WriteString(fmt.Sprintf(
43+
" /*!40100 DEFAULT CHARACTER SET %s COLLATE %s */",
44+
defaultCharacterSet,
45+
defaultCollation,
46+
))
47+
48+
return sql.RowsToRowIter(
49+
sql.NewRow(name, buf.String()),
50+
), nil
51+
}
52+
53+
// Schema implements the sql.Node interface.
54+
func (s *ShowCreateDatabase) Schema() sql.Schema {
55+
return showCreateDatabaseSchema
56+
}
57+
58+
func (s *ShowCreateDatabase) String() string {
59+
return fmt.Sprintf("SHOW CREATE DATABASE %s", s.Database.Name())
60+
}
61+
62+
// Children implements the sql.Node interface.
63+
func (s *ShowCreateDatabase) Children() []sql.Node { return nil }
64+
65+
// Resolved implements the sql.Node interface.
66+
func (s *ShowCreateDatabase) Resolved() bool {
67+
_, ok := s.Database.(sql.UnresolvedDatabase)
68+
return !ok
69+
}
70+
71+
// TransformExpressionsUp implements the sql.Node interface.
72+
func (s *ShowCreateDatabase) TransformExpressionsUp(f sql.TransformExprFunc) (sql.Node, error) {
73+
return s, nil
74+
}
75+
76+
// TransformUp implements the sql.Node interface.
77+
func (s *ShowCreateDatabase) TransformUp(f sql.TransformNodeFunc) (sql.Node, error) {
78+
return f(s)
79+
}

sql/plan/show_create_database_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package plan
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
"gopkg.in/src-d/go-mysql-server.v0/sql"
8+
)
9+
10+
func TestShowCreateDatabase(t *testing.T) {
11+
require := require.New(t)
12+
13+
node := NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true)
14+
iter, err := node.RowIter(sql.NewEmptyContext())
15+
require.NoError(err)
16+
17+
rows, err := sql.RowIterToRows(iter)
18+
require.NoError(err)
19+
20+
require.Equal([]sql.Row{
21+
{"foo", "CREATE DATABASE /*!32312 IF NOT EXISTS*/ `foo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */"},
22+
}, rows)
23+
24+
node = NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false)
25+
iter, err = node.RowIter(sql.NewEmptyContext())
26+
require.NoError(err)
27+
28+
rows, err = sql.RowIterToRows(iter)
29+
require.NoError(err)
30+
31+
require.Equal([]sql.Row{
32+
{"foo", "CREATE DATABASE `foo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */"},
33+
}, rows)
34+
}

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