diff --git a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue index 4e44d27d64..7f90975279 100644 --- a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue +++ b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue @@ -90,6 +90,7 @@ import { supportsTableStructureEditing, supportsTransfer, usesTreeSchemaMode, + isSingleDatabase, } from "@/lib/database/databaseCapabilities"; import { copyNameForTreeNode, isDocumentBrowserTreeNode, objectSourceKindForTreeNode, shouldRunTreeNodeRowAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/sidebar/treeNodeClick"; import { dataTabOpenModeFromTreeClick, type DataTabOpenMode } from "@/lib/sidebar/dataTabOpenPolicy"; @@ -104,6 +105,7 @@ import { buildDropDatabaseSql, buildDropObjectSql, buildDropSchemaSql, + damengDropSchemaExecutionSchema, buildGetDatabaseCommentSql, buildGetSchemaCommentSql, buildUpdateDatabasePropertiesSql, @@ -2290,7 +2292,8 @@ const canCreateSchema = computed(() => { const canDropSchema = computed(() => { const config = activeNode.value.connectionId ? connectionStore.getConfig(activeNode.value.connectionId) : undefined; - return activeNode.value.type === "schema" && !isSqlServerLinkedNode(activeNode.value) && usesTreeSchemaMode(effectiveDatabaseTypeForConnection(config)) && !connectionUsesDatabaseObjectTreeMode(config); + const dbType = effectiveDatabaseTypeForConnection(config); + return activeNode.value.type === "schema" && !isSqlServerLinkedNode(activeNode.value) && (usesTreeSchemaMode(dbType) || dbType === "dameng") && !connectionUsesDatabaseObjectTreeMode(config); }); const canEditSchemaComment = computed(() => { @@ -2949,17 +2952,25 @@ async function confirmDropSchema() { if (!node.connectionId || !node.database) return; try { await connectionStore.ensureConnected(node.connectionId); + const config = connectionStore.getConfig(node.connectionId); + const dbType = effectiveDatabaseTypeForConnection(config); + let dropExecutionSchema: string | undefined; + if (dbType === "dameng") { + dropExecutionSchema = damengDropSchemaExecutionSchema(config?.username, node.label) ?? undefined; + if (!dropExecutionSchema) throw new Error(t("contextMenu.dropDamengSchemaRequiresDifferentDba")); + } const sql = dropSchemaPreviewSql.value || (await buildDropSchemaSql({ databaseType: databaseTypeForNode(node), name: node.label, })); - await executeTreeNodeSqlWithProductionGuard(node, sql, { database: node.database }); + await executeTreeNodeSqlWithProductionGuard(node, sql, { database: node.database, schema: dropExecutionSchema }); toast(t("contextMenu.dropSchemaSuccess", { name: node.label }), 3000); - const config = connectionStore.getConfig(node.connectionId); if (config?.db_type === "sqlserver") { await connectionStore.loadSqlServerDatabaseObjects(node.connectionId, node.database, { force: true }); + } else if (isSingleDatabase(dbType)) { + await connectionStore.loadDatabases(node.connectionId, { force: true }); } else { await connectionStore.loadSchemas(node.connectionId, node.database, { force: true }); } diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index af62d34d42..af2242149c 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -2257,6 +2257,7 @@ export default { confirmDropSchemaMessage: 'Are you sure you want to drop schema "{name}"? This will permanently delete the schema and all its objects.', createSchemaSuccess: 'Schema "{name}" created', dropSchemaSuccess: 'Schema "{name}" dropped', + dropDamengSchemaRequiresDifferentDba: "Dameng cannot safely drop this schema from the current connection. Connect as a different DBA user and try again.", createSchemaNamePlaceholder: "Schema name", editSchemaComment: "Edit Comment", editSchemaCommentTitle: 'Edit Comment: "{name}"', diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index fb9291511f..6b7244a9ce 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -2191,6 +2191,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: '¿Estás seguro de que deseas eliminar el esquema "{name}"? Esto borrará permanentemente el esquema y todos sus objetos.', createSchemaSuccess: 'Esquema "{name}" creado', dropSchemaSuccess: 'Esquema "{name}" eliminado', + dropDamengSchemaRequiresDifferentDba: "La conexión actual no puede eliminar este esquema de forma segura. Conéctate con otro usuario DBA e inténtalo de nuevo.", createSchemaNamePlaceholder: "Nombre del esquema", editSchemaComment: "Editar comentario", editSchemaCommentTitle: 'Editar comentario: "{name}"', diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index 7aec9e8730..e172969abd 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -2189,6 +2189,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: 'Sei sicuro di voler eliminare lo schema "{name}"? Questa operazione eliminerà permanentemente lo schema e tutti i suoi oggetti.', createSchemaSuccess: 'Schema "{name}" creato', dropSchemaSuccess: 'Schema "{name}" eliminato', + dropDamengSchemaRequiresDifferentDba: "La connessione corrente non può eliminare questo schema in modo sicuro. Connettiti con un altro utente DBA e riprova.", createSchemaNamePlaceholder: "Nome schema", editSchemaComment: "Modifica commento", editSchemaCommentTitle: 'Modifica commento: "{name}"', diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index ac5c982f21..cb1ddfcb37 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -2212,6 +2212,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: "本当にスキーマ「{name}」を削除しますか?スキーマとすべてのオブジェクトが永久に削除されます。", createSchemaSuccess: "スキーマ「{name}」を作成しました", dropSchemaSuccess: "スキーマ「{name}」を削除しました", + dropDamengSchemaRequiresDifferentDba: "現在の接続ではこのスキーマを安全に削除できません。別の DBA ユーザーで接続して再試行してください。", createSchemaNamePlaceholder: "スキーマ名", editSchemaComment: "コメントを編集", editSchemaCommentTitle: "コメントを編集: 「{name}」", diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts index ac10f9eb38..85f433bebb 100644 --- a/apps/desktop/src/i18n/locales/ko.ts +++ b/apps/desktop/src/i18n/locales/ko.ts @@ -2213,6 +2213,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: '스키마 "{name}"을(를) 삭제하시겠습니까? 스키마와 모든 객체가 영구적으로 삭제됩니다.', createSchemaSuccess: '스키마 "{name}" 생성됨', dropSchemaSuccess: '스키마 "{name}" 삭제됨', + dropDamengSchemaRequiresDifferentDba: "현재 연결에서는 이 스키마를 안전하게 삭제할 수 없습니다. 다른 DBA 사용자로 연결한 후 다시 시도하세요.", createSchemaNamePlaceholder: "스키마 이름", editSchemaComment: "주석 편집", editSchemaCommentTitle: '주석 편집: "{name}"', diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index 301cf3401d..aac1bc3984 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -2191,6 +2191,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: 'Tem certeza de que deseja remover o schema "{name}"? Isso excluirá permanentemente o schema e todos os seus objetos.', createSchemaSuccess: 'Schema "{name}" criado', dropSchemaSuccess: 'Schema "{name}" removido', + dropDamengSchemaRequiresDifferentDba: "A conexão atual não pode remover este schema com segurança. Conecte-se com outro usuário DBA e tente novamente.", createSchemaNamePlaceholder: "Nome do schema", editSchemaComment: "Editar comentário", editSchemaCommentTitle: 'Editar comentário: "{name}"', diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index 94fafae5e0..62e4422073 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -2258,6 +2258,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: "确定要删除 Schema「{name}」吗?这将永久删除该 Schema 及其所有对象。", createSchemaSuccess: "Schema「{name}」已创建", dropSchemaSuccess: "Schema「{name}」已删除", + dropDamengSchemaRequiresDifferentDba: "当前连接无法安全删除此 Schema。请改用其他 DBA 用户连接后重试。", createSchemaNamePlaceholder: "Schema 名称", editSchemaComment: "编辑注释", editSchemaCommentTitle: "编辑注释:「{name}」", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index e7c74658da..9ffcc75a27 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -2190,6 +2190,7 @@ export default withEnglishFallback({ confirmDropSchemaMessage: "確定要刪除 Schema「{name}」嗎?這將永久刪除該 Schema 及其所有物件。", createSchemaSuccess: "Schema「{name}」已建立", dropSchemaSuccess: "Schema「{name}」已刪除", + dropDamengSchemaRequiresDifferentDba: "目前連線無法安全刪除此 Schema。請改用其他 DBA 使用者連線後再試。", createSchemaNamePlaceholder: "Schema 名稱", editSchemaComment: "編輯註解", editSchemaCommentTitle: "編輯註解:「{name}」", diff --git a/apps/desktop/src/lib/__tests__/database/dbAdminSql.spec.ts b/apps/desktop/src/lib/__tests__/database/dbAdminSql.spec.ts index dd31779dd5..451df574d1 100644 --- a/apps/desktop/src/lib/__tests__/database/dbAdminSql.spec.ts +++ b/apps/desktop/src/lib/__tests__/database/dbAdminSql.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { collectDuplicateTableColumnComments, duplicateTableStructureRequiresScript } from "@/lib/database/dbAdminSql"; +import { collectDuplicateTableColumnComments, damengDropSchemaExecutionSchema, duplicateTableStructureRequiresScript } from "@/lib/database/dbAdminSql"; describe("collectDuplicateTableColumnComments", () => { it("preserves meaningful whitespace and excludes whitespace-only comments", () => { @@ -30,3 +30,17 @@ describe("duplicateTableStructureRequiresScript", () => { expect(duplicateTableStructureRequiresScript('CREATE TABLE "copy" (LIKE "source" INCLUDING ALL);')).toBe(false); }); }); + +describe("damengDropSchemaExecutionSchema", () => { + it("uses the login schema when dropping a different schema", () => { + expect(damengDropSchemaExecutionSchema("APP", "TARGET")).toBe("APP"); + }); + + it("fails closed when dropping the login schema", () => { + expect(damengDropSchemaExecutionSchema("APP", "APP")).toBeNull(); + }); + + it("fails closed when the username is missing", () => { + expect(damengDropSchemaExecutionSchema(undefined, "TARGET")).toBeNull(); + }); +}); diff --git a/apps/desktop/src/lib/database/dbAdminSql.ts b/apps/desktop/src/lib/database/dbAdminSql.ts index 521707860f..cff13afa6d 100644 --- a/apps/desktop/src/lib/database/dbAdminSql.ts +++ b/apps/desktop/src/lib/database/dbAdminSql.ts @@ -119,6 +119,13 @@ export function buildDropSchemaSql(options: SchemaNameSqlOptions): Promise Result String { let schema = quote_table_identifier(options.database_type, &options.name); - if matches!(options.database_type, Some(DatabaseType::Postgres | DatabaseType::Gaussdb | DatabaseType::Kwdb)) { + if matches!( + options.database_type, + Some(DatabaseType::Postgres | DatabaseType::Gaussdb | DatabaseType::Kwdb | DatabaseType::Dameng) + ) { format!("DROP SCHEMA {schema} CASCADE;") } else { format!("DROP SCHEMA {schema};") @@ -1427,6 +1430,13 @@ mod tests { }), "DROP SCHEMA \"analytics\" CASCADE;" ); + assert_eq!( + build_drop_schema_sql(SchemaNameSqlOptions { + database_type: Some(DatabaseType::Dameng), + name: "analytics".to_string(), + }), + "DROP SCHEMA \"analytics\" CASCADE;" + ); } #[test]