Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sql/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ type Database interface {
// SchemaDatabase is a database comprising multiple schemas that can each be queried for tables.
type SchemaDatabase interface {
Nameable
// SupportsDatabaseSchemas returns whether this database supports multiple schemas. This is necessary because some
// integrators may use implementations that fulfill the interface without actually supporting multiple schemas in
// all configurations.
SupportsDatabaseSchemas() bool
// GetSchema returns the database with the schema name provided, matched case-insensitive.
// If the schema does not exist, the boolean return value should be false.
GetSchema(ctx *Context, schemaName string) (DatabaseSchema, bool, error)
Expand All @@ -87,6 +91,8 @@ type SchemaDatabase interface {
CreateSchema(ctx *Context, schemaName string) error
// AllSchemas returns all schemas in the database.
AllSchemas(ctx *Context) ([]DatabaseSchema, error)
// DropSchema drops the schema with the name given.
DropSchema(ctx *Context, schemaName string) error
}

// DatabaseSchema is a schema that can be queried for tables. It is functionally equivalent to a Database
Expand Down
17 changes: 17 additions & 0 deletions sql/plan/dbddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ func NewDropDatabase(dbName string, ifExists bool) *DropDB {
}
}

// DropSchema removes a schema from the Catalog using the currently selected database.
type DropSchema struct {
*DropDB
}

var _ sql.Node = (*DropSchema)(nil)

// NewDropSchema returns a new DropSchema.
func NewDropSchema(schemaName string, ifExists bool) *DropSchema {
return &DropSchema{
&DropDB{
DbName: schemaName,
IfExists: ifExists,
},
}
}

// AlterDB alters a database from the Catalog.
type AlterDB struct {
Catalog sql.Catalog
Expand Down
21 changes: 15 additions & 6 deletions sql/planbuilder/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ func (b *Builder) resolveDb(name string) sql.Database {
}

// todo show tables as of expects privileged
//if privilegedDatabase, ok := database.(mysql_db.PrivilegedDatabase); ok {
// if privilegedDatabase, ok := database.(mysql_db.PrivilegedDatabase); ok {
// database = privilegedDatabase.Unwrap()
//}
// }
return database
}

Expand Down Expand Up @@ -848,7 +848,7 @@ func (b *Builder) buildIndexDefs(_ *scope, spec *ast.TableSpec) (idxDefs sql.Ind
}
idxDefs = append(idxDefs, &sql.IndexDef{
Name: idxDef.Info.Name.String(),
Storage: sql.IndexUsing_Default, //TODO: add vitess support for USING
Storage: sql.IndexUsing_Default, // TODO: add vitess support for USING
Constraint: constraint,
Columns: columns,
Comment: comment,
Expand Down Expand Up @@ -1857,13 +1857,22 @@ func (b *Builder) buildDBDDL(inScope *scope, c *ast.DBDDL) (outScope *scope) {
createSchema := plan.NewCreateSchema(c.DBName, c.IfNotExists, collation)
createSchema.Catalog = b.cat
node = createSchema
default:
b.handleErr(sql.ErrUnsupportedSyntax.New(ast.String(c)))
}

outScope.node = node
case ast.DropStr:
dropDb := plan.NewDropDatabase(c.DBName, c.IfExists)
dropDb.Catalog = b.cat
outScope.node = dropDb
switch c.SchemaOrDatabase {
case "database":
node := plan.NewDropDatabase(c.DBName, c.IfExists)
node.Catalog = b.cat
outScope.node = node
case "schema":
node := plan.NewDropSchema(c.DBName, c.IfExists)
node.Catalog = b.cat
outScope.node = node
}
case ast.AlterStr:
if len(c.CharsetCollate) == 0 {
if len(c.DBName) > 0 {
Expand Down
75 changes: 71 additions & 4 deletions sql/rowexec/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ func (b *BaseBuilder) buildCreateSchema(ctx *sql.Context, n *plan.CreateSchema,
// If no database is selected, first try to fall back to CREATE DATABASE
// since CREATE SCHEMA is a synonym for CREATE DATABASE in MySQL
// https://dev.mysql.com/doc/refman/8.4/en/create-database.html
// TODO: For PostgreSQL, return an error if no database is selected.
// TODO: For PostgreSQL, return an error if no database is selected (should be impossible)
if database == "" {
return b.buildCreateDB(ctx, &plan.CreateDB{
Catalog: n.Catalog,
Expand All @@ -466,8 +466,12 @@ func (b *BaseBuilder) buildCreateSchema(ctx *sql.Context, n *plan.CreateSchema,
return nil, err
}

if pdb, ok := db.(mysql_db.PrivilegedDatabase); ok {
db = pdb.Unwrap()
}

sdb, ok := db.(sql.SchemaDatabase)
if !ok {
if !ok || !sdb.SupportsDatabaseSchemas() {
// If schemas aren't supported, treat CREATE SCHEMA as a synonym for CREATE DATABASE (as is the case in MySQL)
return b.buildCreateDB(ctx, &plan.CreateDB{
Catalog: n.Catalog,
Expand Down Expand Up @@ -882,6 +886,69 @@ func (b *BaseBuilder) buildDropDB(ctx *sql.Context, n *plan.DropDB, row sql.Row)
return sql.RowsToRowIter(rows...), nil
}

func (b *BaseBuilder) buildDropSchema(ctx *sql.Context, n *plan.DropSchema, row sql.Row) (sql.RowIter, error) {
database := ctx.GetCurrentDatabase()

// If no database is selected, first try to fall back to CREATE DATABASE
// since CREATE SCHEMA is a synonym for CREATE DATABASE in MySQL
// https://dev.mysql.com/doc/refman/8.4/en/create-database.html
// TODO: For PostgreSQL, return an error if no database is selected (should be impossible)
if database == "" {
return b.buildDropDB(ctx, &plan.DropDB{
Catalog: n.Catalog,
DbName: n.DbName,
IfExists: n.IfExists,
}, row)
}

db, err := n.Catalog.Database(ctx, database)
if err != nil {
return nil, err
}

if pdb, ok := db.(mysql_db.PrivilegedDatabase); ok {
db = pdb.Unwrap()
}

sdb, ok := db.(sql.SchemaDatabase)
if !ok || !sdb.SupportsDatabaseSchemas() {
// If schemas aren't supported, treat DROP SCHEMA as a synonym for DROP DATABASE (as is the case in MySQL)
return b.buildDropDB(ctx, &plan.DropDB{
Catalog: n.Catalog,
DbName: n.DbName,
IfExists: n.IfExists,
}, row)
}

_, exists, err := sdb.GetSchema(ctx, n.DbName)
if err != nil {
return nil, err
}

rows := []sql.Row{{types.OkResult{RowsAffected: 1}}}

if !exists {
if n.IfExists && ctx != nil && ctx.Session != nil {
ctx.Session.Warn(&sql.Warning{
Level: "Note",
Code: mysql.ERDbCreateExists,
Message: fmt.Sprintf("Can't drop schema %s; schema does not exist", n.DbName),
})

return sql.RowsToRowIter(rows...), nil
} else {
return nil, sql.ErrDatabaseSchemaNotFound.New(n.DbName)
}
}

err = sdb.DropSchema(ctx, n.DbName)
if err != nil {
return nil, err
}

return sql.RowsToRowIter(rows...), nil
}

func (b *BaseBuilder) buildRenameColumn(ctx *sql.Context, n *plan.RenameColumn, row sql.Row) (sql.RowIter, error) {
if b.EngineOverrides.Hooks.TableRenameColumn.PreSQLExecution != nil {
nn, err := b.EngineOverrides.Hooks.TableRenameColumn.PreSQLExecution(ctx, n)
Expand Down Expand Up @@ -1128,8 +1195,8 @@ func (b *BaseBuilder) buildCreateTable(ctx *sql.Context, n *plan.CreateTable, ro
}
}

//TODO: in the event that foreign keys or indexes aren't supported, you'll be left with a created table and no foreign keys/indexes
//this also means that if a foreign key or index fails, you'll only have what was declared up to the failure
// TODO: in the event that foreign keys or indexes aren't supported, you'll be left with a created table and no foreign keys/indexes
// this also means that if a foreign key or index fails, you'll only have what was declared up to the failure
tableNode, ok, err := n.Db.GetTableInsensitive(ctx, n.Name())
if err != nil {
return sql.RowsToRowIter(), err
Expand Down
2 changes: 2 additions & 0 deletions sql/rowexec/node_builder.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ func (b *BaseBuilder) buildNodeExecNoAnalyze(ctx *sql.Context, n sql.Node, row s
return b.buildRenameColumn(ctx, n, row)
case *plan.DropDB:
return b.buildDropDB(ctx, n, row)
case *plan.DropSchema:
return b.buildDropSchema(ctx, n, row)
case *plan.Distinct:
return b.buildDistinct(ctx, n, row)
case *plan.Having:
Expand Down
Loading