Skip to content

Commit b55bd4e

Browse files
authored
Merge pull request #2172 from dolthub/zachmu/drop-schema
drop schema support
2 parents cebe501 + 04df9b1 commit b55bd4e

9 files changed

Lines changed: 171 additions & 21 deletions

File tree

core/rootvalue.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package core
1717
import (
1818
"bytes"
1919
"context"
20+
"fmt"
2021
"slices"
2122
"sort"
2223
"strconv"
@@ -87,6 +88,62 @@ func (root *RootValue) CreateDatabaseSchema(ctx context.Context, dbSchema schema
8788
return root.withStorage(r), nil
8889
}
8990

91+
// DropDatabaseSchema implements the interface doltdb.RootValue.
92+
func (root *RootValue) DropDatabaseSchema(ctx context.Context, dbSchema schema.DatabaseSchema) (doltdb.RootValue, error) {
93+
schemas, err := root.st.GetSchemas(ctx)
94+
if err != nil {
95+
return nil, err
96+
}
97+
98+
found := false
99+
schemaName := dbSchema.Name
100+
for i, s := range schemas {
101+
if strings.EqualFold(s.Name, dbSchema.Name) {
102+
found = true
103+
schemaName = s.Name
104+
// remove this element in the slice
105+
schemas = append(schemas[:i], schemas[i+1:]...)
106+
break
107+
}
108+
}
109+
110+
if !found {
111+
return nil, fmt.Errorf("No schema with the name %s exists", dbSchema.Name)
112+
}
113+
114+
// Check for dangling objects in the schema and reject the drop if there are any
115+
danglingObjects := false
116+
root.IterRootObjects(ctx, func(name doltdb.TableName, table doltdb.RootObject) (stop bool, err error) {
117+
if strings.EqualFold(name.Schema, dbSchema.Name) {
118+
danglingObjects = true
119+
}
120+
return false, nil
121+
})
122+
123+
// check the tables specifically in addition to root objects. This is just an extra paranoid step to avoid
124+
// removing a schema that still has tables.
125+
tableMap, err := root.getTableMap(ctx, schemaName)
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
tableMap.Iter(ctx, func(name string, addr hash.Hash) (bool, error) {
131+
danglingObjects = true
132+
return true, nil
133+
})
134+
135+
if danglingObjects {
136+
return nil, fmt.Errorf("cannot drop schema %s because other objects depend on it", dbSchema.Name)
137+
}
138+
139+
r, err := root.st.SetSchemas(ctx, schemas)
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
return root.withStorage(r), nil
145+
}
146+
90147
// validateSchemaForCreate returns an error if a schema with the name given cannot be created
91148
func validateSchemaForCreate(existingSchemas []schema.DatabaseSchema, dbSchema schema.DatabaseSchema) error {
92149
if dbSchema.Name == "" {

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ require (
66
github.com/PuerkitoBio/goquery v1.8.1
77
github.com/cockroachdb/apd/v2 v2.0.3-0.20200518165714-d020e156310a
88
github.com/cockroachdb/errors v1.7.5
9-
github.com/dolthub/dolt/go v0.40.5-0.20260106173753-e3c81824fc90
9+
github.com/dolthub/dolt/go v0.40.5-0.20260108000424-ed62ee89285b
1010
github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca
1111
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
12-
github.com/dolthub/go-mysql-server v0.20.1-0.20260106170317-759307e19edd
12+
github.com/dolthub/go-mysql-server v0.20.1-0.20260108224859-4dd05696542e
1313
github.com/dolthub/pg_query_go/v6 v6.0.0-20251215122834-fb20be4254d1
1414
github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216
15-
github.com/dolthub/vitess v0.0.0-20251210200925-1d33d416d162
15+
github.com/dolthub/vitess v0.0.0-20260108222406-f8a2587c4954
1616
github.com/fatih/color v1.13.0
1717
github.com/goccy/go-json v0.10.2
1818
github.com/gogo/protobuf v1.3.2

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 h1:I
228228
github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12/go.mod h1:rN7X8BHwkjPcfMQQ2QTAq/xM3leUSGLfb+1Js7Y6TVo=
229229
github.com/dolthub/dolt-mcp v0.2.2 h1:bpROmam74n95uU4EA3BpOIVlTDT0pzeFMBwe/YRq2mI=
230230
github.com/dolthub/dolt-mcp v0.2.2/go.mod h1:S++DJ4QWTAXq+0TNzFa7Oq3IhoT456DJHwAINFAHgDQ=
231-
github.com/dolthub/dolt/go v0.40.5-0.20260106173753-e3c81824fc90 h1:lWOjwImXbtzaL34XjFYVCcnniJUt/jjGx9omvu4y5NU=
232-
github.com/dolthub/dolt/go v0.40.5-0.20260106173753-e3c81824fc90/go.mod h1:RrRSqn/03/yMFx3nxUyL1H8YkC60tJwhqq2UyuvIGNA=
231+
github.com/dolthub/dolt/go v0.40.5-0.20260108000424-ed62ee89285b h1:2DTDLbZwltHrge1NSe8EWkv9f+oCs4QCAE1OVVEF1gw=
232+
github.com/dolthub/dolt/go v0.40.5-0.20260108000424-ed62ee89285b/go.mod h1:z5e06zwixH1wM1gOwBsp4yMllZyZ8PnmXKdnjTf1Vcs=
233233
github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca h1:BGFz/0OlKIuC6qHIZQbvPapFvdAJkeEyGXWVgL5clmE=
234234
github.com/dolthub/eventsapi_schema v0.0.0-20250915094920-eadfd39051ca/go.mod h1:CoDLfgPqHyBtth0Cp+fi/CmC4R81zJNX4wPjShdZ+Bw=
235235
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww=
@@ -238,8 +238,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
238238
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
239239
github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790 h1:zxMsH7RLiG+dlZ/y0LgJHTV26XoiSJcuWq+em6t6VVc=
240240
github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790/go.mod h1:F3cnm+vMRK1HaU6+rNqQrOCyR03HHhR1GWG2gnPOqaE=
241-
github.com/dolthub/go-mysql-server v0.20.1-0.20260106170317-759307e19edd h1:AgpawshAhriZokzNFNTEeeojRDXX96t9Z/Vu6px8F+g=
242-
github.com/dolthub/go-mysql-server v0.20.1-0.20260106170317-759307e19edd/go.mod h1:NjewWKoa5bVSLdKwL7fg7eAfrcIxDybWUKoWEHWRTw4=
241+
github.com/dolthub/go-mysql-server v0.20.1-0.20260108224859-4dd05696542e h1:OKp5W4bgSJIAKESEtBtyOWF85HwvE7UIe+T204v5EN0=
242+
github.com/dolthub/go-mysql-server v0.20.1-0.20260108224859-4dd05696542e/go.mod h1:2bgnal91FRGVdJyirmUSMCd1Tp3Ci8dTDsrJWkTp/hs=
243243
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI=
244244
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q=
245245
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE=
@@ -250,8 +250,8 @@ github.com/dolthub/pg_query_go/v6 v6.0.0-20251215122834-fb20be4254d1 h1:GY17cGA4
250250
github.com/dolthub/pg_query_go/v6 v6.0.0-20251215122834-fb20be4254d1/go.mod h1:qnrZP3/1slFl2Bq5yw38HLOsArZareGwdpEceriblLc=
251251
github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216 h1:JWkKRE4EHUcEVQCMRBej8DYxjYjRz/9MdF/NNQh0o70=
252252
github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216/go.mod h1:e/FIZVvT2IR53HBCAo41NjqgtEnjMJGKca3Y/dAmZaA=
253-
github.com/dolthub/vitess v0.0.0-20251210200925-1d33d416d162 h1:6RW2VpUs/cUFdvk4mXSmJfQZLs9wJABVjke3CHGJBcs=
254-
github.com/dolthub/vitess v0.0.0-20251210200925-1d33d416d162/go.mod h1:FLWqdXsAeeBQyFwDjmBVu0GnbjI2MKeRf3tRVdJEKlI=
253+
github.com/dolthub/vitess v0.0.0-20260108222406-f8a2587c4954 h1:VN2ZjnYPyxcAN/XetvcdumFbI2Ad/Gb47Qwdo9REY3A=
254+
github.com/dolthub/vitess v0.0.0-20260108222406-f8a2587c4954/go.mod h1:FLWqdXsAeeBQyFwDjmBVu0GnbjI2MKeRf3tRVdJEKlI=
255255
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
256256
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
257257
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=

server/ast/drop_database.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ func nodeDropDatabase(ctx *Context, node *tree.DropDatabase) (*vitess.DBDDL, err
3131
return nil, errors.Errorf("WITH ( FORCE ) is not yet supported")
3232
}
3333
return &vitess.DBDDL{
34-
Action: vitess.DropStr,
35-
DBName: string(node.Name),
36-
IfExists: node.IfExists,
34+
Action: vitess.DropStr,
35+
SchemaOrDatabase: "database",
36+
DBName: string(node.Name),
37+
IfExists: node.IfExists,
3738
}, nil
3839
}

server/ast/drop_schema.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package ast
1717
import (
1818
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
1919

20+
"github.com/dolthub/doltgresql/server/auth"
21+
2022
"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
2123
)
2224

@@ -27,5 +29,26 @@ func nodeDropSchema(ctx *Context, node *tree.DropSchema) (vitess.Statement, erro
2729
return nil, nil
2830
}
2931

30-
return NotYetSupportedError("DROP SCHEMA is not yet supported")
32+
if len(node.Names) > 1 {
33+
return NotYetSupportedError("DROP SCHEMA with multiple schema names is not yet supported.")
34+
}
35+
36+
if node.DropBehavior == tree.DropCascade {
37+
return NotYetSupportedError("DROP SCHEMA with CASCADE behavior is not yet supported.")
38+
}
39+
40+
schemaName := node.Names[0]
41+
42+
return &vitess.DBDDL{
43+
Action: vitess.DropStr,
44+
SchemaOrDatabase: "schema",
45+
DBName: schemaName,
46+
CharsetCollate: nil,
47+
IfExists: node.IfExists,
48+
Auth: vitess.AuthInformation{
49+
AuthType: auth.AuthType_DELETE,
50+
TargetType: auth.AuthTargetType_SchemaIdentifiers,
51+
TargetNames: []string{"", schemaName},
52+
},
53+
}, nil
3154
}

server/ast/no_op.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ func NotYetSupportedError(errorMsg string) (vitess.Statement, error) {
5353
return NewNoOp(errorMsg), nil
5454
}
5555

56-
return nil, errors.New(errorMsg)
56+
return nil, errors.Errorf(errorMsg + " Please file an issue at https://github.com/dolthub/doltgresql/issues")
5757
}

testing/generation/command_docs/output/drop_schema_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ import "testing"
1818

1919
func TestDropSchema(t *testing.T) {
2020
tests := []QueryParses{
21-
Parses("DROP SCHEMA name"),
22-
Parses("DROP SCHEMA IF EXISTS name"),
21+
Converts("DROP SCHEMA name"),
22+
Converts("DROP SCHEMA IF EXISTS name"),
2323
Parses("DROP SCHEMA name , name"),
2424
Parses("DROP SCHEMA IF EXISTS name , name"),
2525
Parses("DROP SCHEMA name CASCADE"),
2626
Parses("DROP SCHEMA IF EXISTS name CASCADE"),
2727
Parses("DROP SCHEMA name , name CASCADE"),
2828
Parses("DROP SCHEMA IF EXISTS name , name CASCADE"),
29-
Parses("DROP SCHEMA name RESTRICT"),
30-
Parses("DROP SCHEMA IF EXISTS name RESTRICT"),
29+
Converts("DROP SCHEMA name RESTRICT"),
30+
Converts("DROP SCHEMA IF EXISTS name RESTRICT"),
3131
Parses("DROP SCHEMA name , name RESTRICT"),
3232
Parses("DROP SCHEMA IF EXISTS name , name RESTRICT"),
3333
}

testing/go/auth_quick_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ func TestAuthQuick(t *testing.T) {
104104
"CREATE SCHEMA newsch;",
105105
},
106106
},
107-
{ // This isn't supported yet, but it is supposed to fail since tester is not an owner
107+
{
108108
Queries: []string{
109109
"GRANT CREATE ON DATABASE postgres TO tester;",
110110
"CREATE SCHEMA newsch;",
111111
"DROP SCHEMA newsch;",
112112
},
113-
ExpectedErr: "not yet supported",
113+
ExpectedErr: "permission denied for schema",
114114
},
115115
{
116116
Queries: []string{

testing/go/schemas_test.go

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,80 @@ var SchemaTests = []ScriptTest{
869869
},
870870
},
871871
},
872+
{
873+
Name: "drop schema",
874+
SetUpScript: []string{
875+
"CREATE SCHEMA dropme",
876+
`CREATE schema "hasTables"`,
877+
"CREATE TABLE hasTables.t1 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
878+
},
879+
Assertions: []ScriptTestAssertion{
880+
{
881+
Query: "Show schemas",
882+
Expected: []sql.Row{
883+
{"dolt"},
884+
{"dropme"},
885+
{"hasTables"},
886+
{"pg_catalog"},
887+
{"public"},
888+
{"information_schema"},
889+
},
890+
},
891+
{
892+
Query: "DROP SCHEMA dropme;",
893+
Expected: []sql.Row{},
894+
},
895+
{
896+
Query: "Show schemas",
897+
Expected: []sql.Row{
898+
{"dolt"},
899+
{"hasTables"},
900+
{"pg_catalog"},
901+
{"public"},
902+
{"information_schema"},
903+
},
904+
},
905+
{
906+
Query: "DROP SCHEMA dropme;",
907+
ExpectedErr: "database schema not found",
908+
},
909+
{
910+
Query: "drop schema if exists dropme;",
911+
},
912+
{
913+
Query: "DROP SCHEMA hasTables;",
914+
ExpectedErr: "cannot drop schema hastables because other objects depend on it",
915+
},
916+
{
917+
Skip: true, // not implemented yet
918+
Query: "drop schema hasTables cascade;",
919+
},
920+
{
921+
Query: "create schema hastype;",
922+
},
923+
{
924+
Query: "create type hastype.mytype as enum('a', 'b', 'c');",
925+
},
926+
{
927+
Query: "DROP SCHEMA hastype;",
928+
ExpectedErr: "cannot drop schema hastype because other objects depend on it",
929+
},
930+
{
931+
Query: "create schema hassequence;",
932+
},
933+
{
934+
Query: "create sequence hassequence.myseq start 1 increment 1;",
935+
},
936+
{
937+
Query: "DROP SCHEMA hassequence;",
938+
ExpectedErr: "cannot drop schema hassequence because other objects depend on it",
939+
},
940+
},
941+
},
872942
// More tests:
873943
// * alter table statements, when they work better
874944
// * AS OF (when supported)
875945
// * revision qualifiers
876-
// * drop schema
877946
// * more statement types
878947
// * INSERT INTO schema1 SELECT FROM schema2
879948
// * Subqueries accessing different schemas in the same SELECT

0 commit comments

Comments
 (0)