diff --git a/go/go.mod b/go/go.mod index 3508673ce70..53276525520 100644 --- a/go/go.mod +++ b/go/go.mod @@ -61,7 +61,7 @@ require ( github.com/dolthub/dolt-mcp v0.2.2 github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 - github.com/dolthub/go-mysql-server v0.20.1-0.20260106231211-877fb58d389e + github.com/dolthub/go-mysql-server v0.20.1-0.20260108001605-ff0a497ea62f github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 github.com/edsrzf/mmap-go v1.2.0 github.com/esote/minmaxheap v1.0.0 diff --git a/go/go.sum b/go/go.sum index 3f32140f1c7..9822ec66542 100644 --- a/go/go.sum +++ b/go/go.sum @@ -195,8 +195,8 @@ github.com/dolthub/fslock v0.0.0-20251215194149-ef20baba2318 h1:n+vdH5G5Db+1qnDC github.com/dolthub/fslock v0.0.0-20251215194149-ef20baba2318/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0= github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790 h1:zxMsH7RLiG+dlZ/y0LgJHTV26XoiSJcuWq+em6t6VVc= github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790/go.mod h1:F3cnm+vMRK1HaU6+rNqQrOCyR03HHhR1GWG2gnPOqaE= -github.com/dolthub/go-mysql-server v0.20.1-0.20260106231211-877fb58d389e h1:Ro9BWRdOTiZ4HaVc8U8Zj+hJSauf3inWpXw5vuy+qcg= -github.com/dolthub/go-mysql-server v0.20.1-0.20260106231211-877fb58d389e/go.mod h1:T+oVXfQAETbWm9R55daMqg0HE7W7Fz7bzh+pGiQgaPI= +github.com/dolthub/go-mysql-server v0.20.1-0.20260108001605-ff0a497ea62f h1:pKwWXc4w96VvPKQ81S8uVBXRJxsxRInvKZIS/hpoCg4= +github.com/dolthub/go-mysql-server v0.20.1-0.20260108001605-ff0a497ea62f/go.mod h1:T+oVXfQAETbWm9R55daMqg0HE7W7Fz7bzh+pGiQgaPI= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q= github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE= diff --git a/go/libraries/doltcore/doltdb/root_val.go b/go/libraries/doltcore/doltdb/root_val.go index 7ec545520b4..1df571d16ec 100644 --- a/go/libraries/doltcore/doltdb/root_val.go +++ b/go/libraries/doltcore/doltdb/root_val.go @@ -57,9 +57,10 @@ var DoltFeatureVersion FeatureVersion = 7 // last bumped when fixing bug related // RootValue is the value of the Database and is the committed value in every Dolt or Doltgres commit. type RootValue interface { Rootish - // CreateDatabaseSchema creates the given schema. This differs from a table's schema. CreateDatabaseSchema(ctx context.Context, dbSchema schema.DatabaseSchema) (RootValue, error) + // DropDatabaseSchema drops the given schema. This differs from a table's schema. + DropDatabaseSchema(ctx context.Context, dbSchema schema.DatabaseSchema) (RootValue, error) // DebugString returns a human readable string with the contents of this root. If |transitive| is true, row data from // all tables is also included. This method is very expensive for large root values, so |transitive| should only be used // when debugging tests. @@ -1060,6 +1061,54 @@ func (root *rootValue) CreateDatabaseSchema(ctx context.Context, dbSchema schema return root.withStorage(r), nil } +// DropDatabaseSchema drops a database schema from the root value. +// This is currently unused in Dolt because dolt always has only a single (unnamed) schema. But it's implemented +// because technically Dolt can support multiple schemas whenever we decide to. +func (root *rootValue) DropDatabaseSchema(ctx context.Context, dbSchema schema.DatabaseSchema) (RootValue, error) { + schemas, err := root.st.GetSchemas(ctx) + if err != nil { + return nil, err + } + + found := false + schemaName := dbSchema.Name + for i, s := range schemas { + if strings.EqualFold(s.Name, dbSchema.Name) { + found = true + schemaName = s.Name + // remove this element in the slice + schemas = append(schemas[:i], schemas[i+1:]...) + break + } + } + + if !found { + return nil, fmt.Errorf("No schema with the name %s exists", dbSchema.Name) + } + + tableMap, err := root.getTableMap(ctx, schemaName) + if err != nil { + return nil, err + } + + tablesInSchema := false + tableMap.Iter(ctx, func(name string, addr hash.Hash) (bool, error) { + tablesInSchema = true + return true, nil + }) + + if tablesInSchema { + return nil, fmt.Errorf("Cannot drop schema %s because it still contains tables", schemaName) + } + + r, err := root.st.SetSchemas(ctx, schemas) + if err != nil { + return nil, err + } + + return root.withStorage(r), nil +} + // HashOf gets the hash of the root value func (root *rootValue) HashOf() (hash.Hash, error) { if root.rootHash.IsEmpty() { diff --git a/go/libraries/doltcore/sqle/clusterdb/database.go b/go/libraries/doltcore/sqle/clusterdb/database.go index 99fef42e98d..5e9f0ff5267 100644 --- a/go/libraries/doltcore/sqle/clusterdb/database.go +++ b/go/libraries/doltcore/sqle/clusterdb/database.go @@ -205,10 +205,18 @@ func (db database) GetSchema(ctx *sql.Context, schemaName string) (sql.DatabaseS panic(fmt.Sprintf("GetSchema is not implemented for database %T", db)) } +func (db database) SupportsDatabaseSchemas() bool { + return false +} + func (db database) CreateSchema(ctx *sql.Context, schemaName string) error { panic(fmt.Sprintf("CreateSchema is not implemented for database %T", db)) } +func (db database) DropSchema(ctx *sql.Context, schemaName string) error { + panic(fmt.Sprintf("DropSchema is not implemented for database %T", db)) +} + func (db database) AllSchemas(ctx *sql.Context) ([]sql.DatabaseSchema, error) { panic(fmt.Sprintf("AllSchemas is not implemented for database %T", db)) } diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 170cd2dbbf2..4ffdc2b72be 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2173,6 +2173,14 @@ func (db Database) CreateTemporaryTable(ctx *sql.Context, tableName string, pkSc return nil } +// SupportsDatabaseSchemas implements sql.SchemaDatabase +// TODO: this interface is only necessary because we don't have a separate sql.Database implementation for doltgres, +// which has additional capabilities (like schema creation). Dolt technically can create schemas (multiple DBs in +// the same commit graph), but there's no way for users to access this functionality currently. +func (db Database) SupportsDatabaseSchemas() bool { + return resolve.UseSearchPath +} + // CreateSchema implements sql.SchemaDatabase func (db Database) CreateSchema(ctx *sql.Context, schemaName string) error { if err := dsess.CheckAccessForDb(ctx, db, branch_control.Permissions_Write); err != nil { @@ -2203,6 +2211,36 @@ func (db Database) CreateSchema(ctx *sql.Context, schemaName string) error { return db.SetRoot(ctx, root) } +// DropSchema implements sql.SchemaDatabase +func (db Database) DropSchema(ctx *sql.Context, schemaName string) error { + if err := dsess.CheckAccessForDb(ctx, db, branch_control.Permissions_Write); err != nil { + return err + } + + root, err := db.GetRoot(ctx) + if err != nil { + return err + } + + _, exists, err := doltdb.ResolveDatabaseSchema(ctx, root, schemaName) + if err != nil { + return err + } + + if !exists { + return sql.ErrDatabaseSchemaNotFound.New(schemaName) + } + + root, err = root.DropDatabaseSchema(ctx, schema.DatabaseSchema{ + Name: schemaName, + }) + if err != nil { + return err + } + + return db.SetRoot(ctx, root) +} + // GetSchema implements sql.SchemaDatabase func (db Database) GetSchema(ctx *sql.Context, schemaName string) (sql.DatabaseSchema, bool, error) { // For doltgres, the information_schema database should be a schema. @@ -2558,13 +2596,13 @@ func (db Database) CreateTrigger(ctx *sql.Context, definition sql.TriggerDefinit definition.Name, definition.CreateStatement, definition.CreatedAt, - fmt.Errorf("triggers `%s` already exists", definition.Name), //TODO: add a sql error and return that instead + fmt.Errorf("triggers `%s` already exists", definition.Name), // TODO: add a sql error and return that instead ) } // DropTrigger implements sql.TriggerDatabase. func (db Database) DropTrigger(ctx *sql.Context, name string) error { - //TODO: add a sql error and use that as the param error instead + // TODO: add a sql error and use that as the param error instead return db.dropFragFromSchemasTable(ctx, "trigger", name, sql.ErrTriggerDoesNotExist.New(name)) } diff --git a/go/libraries/doltcore/sqle/user_space_database.go b/go/libraries/doltcore/sqle/user_space_database.go index a5653544981..e6c4b182e2c 100644 --- a/go/libraries/doltcore/sqle/user_space_database.go +++ b/go/libraries/doltcore/sqle/user_space_database.go @@ -152,10 +152,18 @@ func (db *UserSpaceDatabase) GetSchema(ctx *sql.Context, schemaName string) (sql panic(fmt.Sprintf("GetSchema is not implemented for database %T", db)) } +func (db UserSpaceDatabase) SupportsDatabaseSchemas() bool { + return false +} + func (db *UserSpaceDatabase) CreateSchema(ctx *sql.Context, schemaName string) error { panic(fmt.Sprintf("CreateSchema is not implemented for database %T", db)) } +func (db *UserSpaceDatabase) DropSchema(ctx *sql.Context, schemaName string) error { + panic(fmt.Sprintf("DropSchema is not implemented for database %T", db)) +} + func (db *UserSpaceDatabase) AllSchemas(ctx *sql.Context) ([]sql.DatabaseSchema, error) { panic(fmt.Sprintf("AllSchemas is not implemented for database %T", db)) }