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

Commit

Permalink
Merge pull request #460 from erizocosmico/feature/show-create-db
Browse files Browse the repository at this point in the history
sql: implement SHOW CREATE DATABASE statement
  • Loading branch information
ajnavarro authored Oct 18, 2018
2 parents 6a6452a + a658b4c commit 380ccef
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 12 deletions.
7 changes: 7 additions & 0 deletions engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,13 @@ var queries = []struct {
`,
[]sql.Row{},
},
{
`SHOW CREATE DATABASE mydb`,
[]sql.Row{{
"mydb",
"CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */",
}},
},
}

func TestQueries(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions sql/analyzer/resolve_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ func resolveDatabase(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error
return nil, err
}

nc := *v
nc.Database = db
return &nc, nil
case *plan.ShowCreateDatabase:
db, err := a.Catalog.Database(v.Database.Name())
if err != nil {
return nil, err
}

nc := *v
nc.Database = db
return &nc, nil
Expand Down
2 changes: 1 addition & 1 deletion sql/parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"strconv"
"strings"

"github.com/opentracing/opentracing-go"
opentracing "github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus"
"gopkg.in/src-d/go-errors.v1"
"gopkg.in/src-d/go-mysql-server.v0/sql"
Expand Down
4 changes: 4 additions & 0 deletions sql/parse/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,10 @@ var fixtures = map[string]sql.Node{
{Table: plan.NewUnresolvedTable("bar", ""), Write: true},
{Table: plan.NewUnresolvedTable("baz", "")},
}),
`SHOW CREATE DATABASE foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false),
`SHOW CREATE SCHEMA foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false),
`SHOW CREATE DATABASE IF NOT EXISTS foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true),
`SHOW CREATE SCHEMA IF NOT EXISTS foo`: plan.NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true),
}

func TestParse(t *testing.T) {
Expand Down
60 changes: 49 additions & 11 deletions sql/parse/show_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,70 @@ func parseShowCreate(s string) (sql.Node, error) {
r := bufio.NewReader(strings.NewReader(s))

var thingToShow string
var name string
steps := []parseFunc{
err := parseFuncs{
expect("show"),
skipSpaces,
expect("create"),
skipSpaces,
readIdent(&thingToShow),
skipSpaces,
readIdent(&name),
skipSpaces,
checkEOF,
}.exec(r)
if err != nil {
return nil, err
}

for _, step := range steps {
if err := step(r); err != nil {
switch strings.ToLower(thingToShow) {
case "table":
var name string

err := parseFuncs{
readIdent(&name),
skipSpaces,
checkEOF,
}.exec(r)
if err != nil {
return nil, err
}
}

switch strings.ToLower(thingToShow) {
case "table":
return plan.NewShowCreateTable(
sql.UnresolvedDatabase("").Name(),
nil,
name), nil
case "database", "schema":
var ifNotExists bool
var next string
if err := readIdent(&next)(r); err != nil {
return nil, err
}

if next == "if" {
ifNotExists = true
err := parseFuncs{
skipSpaces,
expect("not"),
skipSpaces,
expect("exists"),
skipSpaces,
readIdent(&next),
}.exec(r)
if err != nil {
return nil, err
}
}

err = parseFuncs{
skipSpaces,
checkEOF,
}.exec(r)
if err != nil {
return nil, err
}

return plan.NewShowCreateDatabase(
sql.UnresolvedDatabase(next),
ifNotExists,
), nil
default:
return nil, errUnsupportedShowCreateQuery.New(name)
return nil, errUnsupportedShowCreateQuery.New(thingToShow)
}
}
79 changes: 79 additions & 0 deletions sql/plan/show_create_database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package plan

import (
"bytes"
"fmt"

"gopkg.in/src-d/go-mysql-server.v0/sql"
)

// ShowCreateDatabase returns the SQL for creating a database.
type ShowCreateDatabase struct {
Database sql.Database
IfNotExists bool
}

const defaultCharacterSet = "utf8mb4"

var showCreateDatabaseSchema = sql.Schema{
{Name: "Database", Type: sql.Text},
{Name: "Create Database", Type: sql.Text},
}

// NewShowCreateDatabase creates a new ShowCreateDatabase node.
func NewShowCreateDatabase(db sql.Database, ifNotExists bool) *ShowCreateDatabase {
return &ShowCreateDatabase{db, ifNotExists}
}

// RowIter implements the sql.Node interface.
func (s *ShowCreateDatabase) RowIter(ctx *sql.Context) (sql.RowIter, error) {
var name = s.Database.Name()

var buf bytes.Buffer

buf.WriteString("CREATE DATABASE ")
if s.IfNotExists {
buf.WriteString("/*!32312 IF NOT EXISTS*/ ")
}

buf.WriteRune('`')
buf.WriteString(name)
buf.WriteRune('`')
buf.WriteString(fmt.Sprintf(
" /*!40100 DEFAULT CHARACTER SET %s COLLATE %s */",
defaultCharacterSet,
defaultCollation,
))

return sql.RowsToRowIter(
sql.NewRow(name, buf.String()),
), nil
}

// Schema implements the sql.Node interface.
func (s *ShowCreateDatabase) Schema() sql.Schema {
return showCreateDatabaseSchema
}

func (s *ShowCreateDatabase) String() string {
return fmt.Sprintf("SHOW CREATE DATABASE %s", s.Database.Name())
}

// Children implements the sql.Node interface.
func (s *ShowCreateDatabase) Children() []sql.Node { return nil }

// Resolved implements the sql.Node interface.
func (s *ShowCreateDatabase) Resolved() bool {
_, ok := s.Database.(sql.UnresolvedDatabase)
return !ok
}

// TransformExpressionsUp implements the sql.Node interface.
func (s *ShowCreateDatabase) TransformExpressionsUp(f sql.TransformExprFunc) (sql.Node, error) {
return s, nil
}

// TransformUp implements the sql.Node interface.
func (s *ShowCreateDatabase) TransformUp(f sql.TransformNodeFunc) (sql.Node, error) {
return f(s)
}
34 changes: 34 additions & 0 deletions sql/plan/show_create_database_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package plan

import (
"testing"

"github.com/stretchr/testify/require"
"gopkg.in/src-d/go-mysql-server.v0/sql"
)

func TestShowCreateDatabase(t *testing.T) {
require := require.New(t)

node := NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), true)
iter, err := node.RowIter(sql.NewEmptyContext())
require.NoError(err)

rows, err := sql.RowIterToRows(iter)
require.NoError(err)

require.Equal([]sql.Row{
{"foo", "CREATE DATABASE /*!32312 IF NOT EXISTS*/ `foo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */"},
}, rows)

node = NewShowCreateDatabase(sql.UnresolvedDatabase("foo"), false)
iter, err = node.RowIter(sql.NewEmptyContext())
require.NoError(err)

rows, err = sql.RowIterToRows(iter)
require.NoError(err)

require.Equal([]sql.Row{
{"foo", "CREATE DATABASE `foo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8_bin */"},
}, rows)
}

0 comments on commit 380ccef

Please sign in to comment.