{renderItems([
{ action: 'new-table', icon:
, title: '新建表', kbd: '⌘N', featured: true },
+ ...(supportsSchemaActions ? [{ action: 'new-schema', icon:
, title: '新建模式' }] : []),
{ action: 'new-query', icon:
, title: '新建查询' },
{ action: 'run-sql', icon:
, title: '运行外部 SQL 文件' },
])}
diff --git a/frontend/wailsjs/go/app/App.d.ts b/frontend/wailsjs/go/app/App.d.ts
index 999ee30..b98bc63 100755
--- a/frontend/wailsjs/go/app/App.d.ts
+++ b/frontend/wailsjs/go/app/App.d.ts
@@ -28,6 +28,8 @@ export function ConfigureGlobalProxy(arg1:boolean,arg2:connection.ProxyConfig):P
export function CreateDatabase(arg1:connection.ConnectionConfig,arg2:string):Promise
;
+export function CreateSchema(arg1:connection.ConnectionConfig,arg2:string,arg3:string):Promise;
+
export function DBConnect(arg1:connection.ConnectionConfig):Promise;
export function DBGetAllColumns(arg1:connection.ConnectionConfig,arg2:string):Promise;
diff --git a/frontend/wailsjs/go/app/App.js b/frontend/wailsjs/go/app/App.js
index 8665175..190c254 100755
--- a/frontend/wailsjs/go/app/App.js
+++ b/frontend/wailsjs/go/app/App.js
@@ -46,6 +46,10 @@ export function CreateDatabase(arg1, arg2) {
return window['go']['app']['App']['CreateDatabase'](arg1, arg2);
}
+export function CreateSchema(arg1, arg2, arg3) {
+ return window['go']['app']['App']['CreateSchema'](arg1, arg2, arg3);
+}
+
export function DBConnect(arg1) {
return window['go']['app']['App']['DBConnect'](arg1);
}
diff --git a/internal/app/methods_db.go b/internal/app/methods_db.go
index 4662b8c..6305913 100644
--- a/internal/app/methods_db.go
+++ b/internal/app/methods_db.go
@@ -149,6 +149,56 @@ func (a *App) CreateDatabase(config connection.ConnectionConfig, dbName string)
return connection.QueryResult{Success: true, Message: "数据库创建成功"}
}
+func isPostgresSchemaDDLDBType(dbType string) bool {
+ switch resolveDDLDBType(connection.ConnectionConfig{Type: dbType}) {
+ case "postgres", "kingbase", "highgo", "vastbase", "opengauss":
+ return true
+ default:
+ return false
+ }
+}
+
+func buildCreateSchemaSQL(dbType string, schemaName string) (string, error) {
+ schemaName = strings.TrimSpace(schemaName)
+ if schemaName == "" {
+ return "", fmt.Errorf("模式名称不能为空")
+ }
+
+ if !isPostgresSchemaDDLDBType(dbType) {
+ return "", fmt.Errorf("当前数据源(%s)暂不支持通过此入口新建模式", dbType)
+ }
+
+ return fmt.Sprintf("CREATE SCHEMA %s", quoteIdentByType(dbType, schemaName)), nil
+}
+
+func (a *App) CreateSchema(config connection.ConnectionConfig, dbName string, schemaName string) connection.QueryResult {
+ dbType := resolveDDLDBType(config)
+ targetDbName := strings.TrimSpace(dbName)
+ if targetDbName == "" {
+ targetDbName = strings.TrimSpace(config.Database)
+ }
+ if targetDbName == "" {
+ return connection.QueryResult{Success: false, Message: "目标数据库不能为空"}
+ }
+
+ query, err := buildCreateSchemaSQL(dbType, schemaName)
+ if err != nil {
+ return connection.QueryResult{Success: false, Message: err.Error()}
+ }
+
+ runConfig := buildRunConfigForDDL(config, dbType, targetDbName)
+ dbInst, err := a.getDatabase(runConfig)
+ if err != nil {
+ return connection.QueryResult{Success: false, Message: err.Error()}
+ }
+
+ if _, err := dbInst.Exec(query); err != nil {
+ return connection.QueryResult{Success: false, Message: err.Error()}
+ }
+
+ return connection.QueryResult{Success: true, Message: "模式创建成功"}
+}
+
func resolveDDLDBType(config connection.ConnectionConfig) string {
dbType := strings.ToLower(strings.TrimSpace(config.Type))
if dbType == "doris" {
diff --git a/internal/app/methods_db_create_test.go b/internal/app/methods_db_create_test.go
index f7c4768..c27514c 100644
--- a/internal/app/methods_db_create_test.go
+++ b/internal/app/methods_db_create_test.go
@@ -115,3 +115,58 @@ func TestCreateDatabase_SQLServerUsesBracketIdentifiers(t *testing.T) {
t.Fatalf("unexpected SQL Server create database SQL, want %q got %q", want, fakeDB.execQueries[0])
}
}
+
+func TestBuildCreateSchemaSQL_PostgresQuotesSchemaName(t *testing.T) {
+ got, err := buildCreateSchemaSQL("postgresql", `sales"Ops`)
+ if err != nil {
+ t.Fatalf("expected postgres create schema SQL, got error: %v", err)
+ }
+ const want = `CREATE SCHEMA "sales""Ops"`
+ if got != want {
+ t.Fatalf("unexpected create schema SQL, want %q got %q", want, got)
+ }
+}
+
+func TestBuildCreateSchemaSQL_RejectsUnsupportedDatabaseType(t *testing.T) {
+ if _, err := buildCreateSchemaSQL("mysql", "sales"); err == nil {
+ t.Fatalf("expected unsupported database type error")
+ }
+}
+
+func TestCreateSchema_CustomPostgresUsesSelectedDatabase(t *testing.T) {
+ originalNewDatabaseFunc := newDatabaseFunc
+ originalResolveDialConfigWithProxyFunc := resolveDialConfigWithProxyFunc
+ t.Cleanup(func() {
+ newDatabaseFunc = originalNewDatabaseFunc
+ resolveDialConfigWithProxyFunc = originalResolveDialConfigWithProxyFunc
+ })
+
+ fakeDB := &fakeCreateDatabaseDB{}
+ newDatabaseFunc = func(dbType string) (db.Database, error) {
+ return fakeDB, nil
+ }
+ resolveDialConfigWithProxyFunc = func(raw connection.ConnectionConfig) (connection.ConnectionConfig, error) {
+ return raw, nil
+ }
+
+ app := NewAppWithSecretStore(secretstore.NewUnavailableStore("test"))
+ result := app.CreateSchema(connection.ConnectionConfig{
+ Type: "custom",
+ Driver: "pgx",
+ Database: "postgres",
+ }, "tenant_db", `tenant"schema`)
+
+ if !result.Success {
+ t.Fatalf("expected create schema success, got failure: %s", result.Message)
+ }
+ if fakeDB.connectConfig.Database != "tenant_db" {
+ t.Fatalf("expected create schema connection to use selected database tenant_db, got %q", fakeDB.connectConfig.Database)
+ }
+ if len(fakeDB.execQueries) != 1 {
+ t.Fatalf("expected one create schema statement, got %d: %#v", len(fakeDB.execQueries), fakeDB.execQueries)
+ }
+ const want = `CREATE SCHEMA "tenant""schema"`
+ if fakeDB.execQueries[0] != want {
+ t.Fatalf("unexpected create schema SQL, want %q got %q", want, fakeDB.execQueries[0])
+ }
+}