mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-02 02:34:42 +08:00
feat(milvus): add database and collection deletion
This commit is contained in:
@@ -448,7 +448,9 @@ const {
|
||||
|
||||
const {
|
||||
canDropMongoDatabase,
|
||||
canDropMilvusDatabase,
|
||||
canDropMongoCollection,
|
||||
canDropMilvusCollection,
|
||||
canRenameMongoCollection,
|
||||
canCloneMongoCollection,
|
||||
prepareRenameMongoCollectionDialog,
|
||||
@@ -497,6 +499,7 @@ const {
|
||||
openEditNacosNamespaceDialog,
|
||||
confirmEditNacosNamespace,
|
||||
dropMongoCollection,
|
||||
dropMilvusCollection,
|
||||
dropMongoIndex,
|
||||
dropAllMongoIndexes,
|
||||
flushRedisDb,
|
||||
@@ -509,6 +512,8 @@ const {
|
||||
confirmFlushRedisDb,
|
||||
confirmDropMongoDatabase,
|
||||
confirmDropMongoCollection,
|
||||
confirmDropMilvusDatabase,
|
||||
confirmDropMilvusCollection,
|
||||
confirmDropMongoIndex,
|
||||
confirmDropAllMongoIndexes,
|
||||
} = useSidebarDatabaseSpecificMutationRuntime({ activeNode, connectionStore });
|
||||
@@ -1285,10 +1290,18 @@ function requestDeleteSelectedNode(): boolean {
|
||||
dropDatabase();
|
||||
return true;
|
||||
}
|
||||
if (canDropMilvusDatabase.value) {
|
||||
dropDatabase();
|
||||
return true;
|
||||
}
|
||||
if (canDropMongoCollection.value) {
|
||||
dropMongoCollection();
|
||||
return true;
|
||||
}
|
||||
if (canDropMilvusCollection.value) {
|
||||
dropMilvusCollection();
|
||||
return true;
|
||||
}
|
||||
if (canDropSchema.value) {
|
||||
dropSchema();
|
||||
return true;
|
||||
@@ -2945,6 +2958,10 @@ async function refreshDropDatabasePreviewSql() {
|
||||
dropDatabasePreviewSql.value = `db.getSiblingDB(${JSON.stringify(node.label)}).dropDatabase();`;
|
||||
return;
|
||||
}
|
||||
if (node.type === "vector-database") {
|
||||
dropDatabasePreviewSql.value = `POST /v2/vectordb/databases/drop\n{"dbName":${JSON.stringify(node.database || node.label)}}`;
|
||||
return;
|
||||
}
|
||||
dropDatabasePreviewSql.value = "";
|
||||
dropDatabasePreviewSql.value = await buildDropDatabaseSql({
|
||||
databaseType: currentDatabaseType(),
|
||||
@@ -3513,6 +3530,10 @@ async function confirmDropDatabase() {
|
||||
await confirmDropMongoDatabase();
|
||||
return;
|
||||
}
|
||||
if (node.type === "vector-database") {
|
||||
await confirmDropMilvusDatabase();
|
||||
return;
|
||||
}
|
||||
|
||||
const connectionId = node.connectionId;
|
||||
if (!connectionId || dropDatabaseLoading.value) return;
|
||||
@@ -4250,7 +4271,7 @@ routeDangerDialog(showDropMongoCollectionConfirm, () =>
|
||||
return dropMongoCollectionLoading.value;
|
||||
},
|
||||
closeOnConfirm: false,
|
||||
confirm: confirmDropMongoCollection,
|
||||
confirm: () => (activeNode.value.type === "vector-collection" ? confirmDropMilvusCollection() : confirmDropMongoCollection()),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -5040,7 +5061,7 @@ function buildSpecialSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.type === "redis-db" || node.type === "mongo-db") {
|
||||
if (node.type === "redis-db" || node.type === "mongo-db" || node.type === "vector-database") {
|
||||
items.push({ label: t("contextMenu.newQuery"), action: newQuery, icon: TerminalSquare });
|
||||
if (!isNodeDefaultDatabase.value) {
|
||||
items.push({ label: t("contextMenu.setDefaultDatabase"), action: setNodeAsDefaultDatabase, icon: Database });
|
||||
@@ -5056,7 +5077,7 @@ function buildSpecialSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
||||
items.push({ label: t("redis.setDatabaseAlias"), action: openRedisDatabaseAliasDialog, icon: Pencil });
|
||||
items.push({ label: t("redis.flushDb"), action: flushRedisDb, icon: Eraser, variant: "destructive" as const });
|
||||
}
|
||||
if (canDropMongoDatabase.value) {
|
||||
if (canDropMongoDatabase.value || canDropMilvusDatabase.value) {
|
||||
items.push({ label: "", separator: true });
|
||||
items.push({
|
||||
label: t("contextMenu.dropDatabase"),
|
||||
@@ -5125,6 +5146,10 @@ function buildSpecialSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
||||
items.push({ label: "", separator: true });
|
||||
items.push({ label: t("contextMenu.viewData"), action: toggle, icon: TableProperties });
|
||||
items.push({ label: t("contextMenu.newQuery"), action: newQuery, icon: TerminalSquare });
|
||||
if (canDropMilvusCollection.value) {
|
||||
items.push({ label: "", separator: true });
|
||||
items.push({ label: t("contextMenu.dropCollection"), action: dropMilvusCollection, icon: Trash2, shortcut: shortcutDelete, variant: "destructive" as const });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+29
@@ -40,6 +40,18 @@ function connectionGroupNode(groupId: string): TreeNode {
|
||||
};
|
||||
}
|
||||
|
||||
function vectorDatabaseNode(database: string): TreeNode {
|
||||
return {
|
||||
id: `conn-1:${database}`,
|
||||
label: database,
|
||||
type: "vector-database",
|
||||
connectionId: "conn-1",
|
||||
database,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
function connectionStore(selectedTreeNodeIds: string[]) {
|
||||
const lastSelectedTreeNodeId = selectedTreeNodeIds[selectedTreeNodeIds.length - 1] ?? null;
|
||||
return {
|
||||
@@ -57,6 +69,7 @@ function connectionStore(selectedTreeNodeIds: string[]) {
|
||||
disconnect: vi.fn().mockResolvedValue(undefined),
|
||||
isTreeNodeChildrenLoaded: vi.fn(() => false),
|
||||
getConfig: vi.fn(() => undefined),
|
||||
isDefaultDatabase: vi.fn(() => false),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,6 +86,22 @@ function runtime(activeNode: TreeNode, store: ReturnType<typeof connectionStore>
|
||||
});
|
||||
}
|
||||
|
||||
describe("sidebar default database state", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
sidebarFormTarget.value = null;
|
||||
});
|
||||
|
||||
it("recognizes the configured Milvus vector database as default", () => {
|
||||
const store = connectionStore([]);
|
||||
store.isDefaultDatabase.mockReturnValue(true);
|
||||
const { isNodeDefaultDatabase } = runtime(vectorDatabaseNode("analytics"), store);
|
||||
|
||||
expect(isNodeDefaultDatabase.value).toBe(true);
|
||||
expect(store.isDefaultDatabase).toHaveBeenCalledWith("conn-1", "analytics");
|
||||
});
|
||||
});
|
||||
|
||||
describe("sidebar connection move selection", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
Vendored
+48
@@ -89,6 +89,31 @@ function mongoConfig(driverProfile?: string, production = false) {
|
||||
};
|
||||
}
|
||||
|
||||
function milvusConfig(database?: string) {
|
||||
return {
|
||||
id: "conn-1",
|
||||
name: "Milvus",
|
||||
db_type: "milvus" as const,
|
||||
host: "localhost",
|
||||
port: 19530,
|
||||
username: "",
|
||||
password: "",
|
||||
database,
|
||||
};
|
||||
}
|
||||
|
||||
function milvusDatabaseNode(database: string): TreeNode {
|
||||
return {
|
||||
id: `conn-1:${database}`,
|
||||
label: database,
|
||||
type: "vector-database",
|
||||
connectionId: "conn-1",
|
||||
database,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
function mongoDatabaseNode(): TreeNode {
|
||||
return {
|
||||
id: "conn-1:app",
|
||||
@@ -209,6 +234,29 @@ describe("MongoDB sidebar mutation runtime", () => {
|
||||
cloneMongoCollectionLoading.value = false;
|
||||
});
|
||||
|
||||
it("protects the built-in and configured Milvus databases from deletion", () => {
|
||||
mocks.getConfig.mockReturnValue(milvusConfig("analytics"));
|
||||
const activeNode = shallowRef(milvusDatabaseNode("default"));
|
||||
const feature = useSidebarDatabaseSpecificMutationRuntime({
|
||||
activeNode,
|
||||
connectionStore: {
|
||||
getConfig: mocks.getConfig,
|
||||
} as any,
|
||||
});
|
||||
|
||||
expect(feature.canDropMilvusDatabase.value).toBe(false);
|
||||
|
||||
activeNode.value = milvusDatabaseNode("analytics");
|
||||
expect(feature.canDropMilvusDatabase.value).toBe(false);
|
||||
|
||||
activeNode.value = milvusDatabaseNode("archive");
|
||||
expect(feature.canDropMilvusDatabase.value).toBe(true);
|
||||
|
||||
mocks.getConfig.mockReturnValue(mongoConfig());
|
||||
activeNode.value = milvusDatabaseNode("archive-2");
|
||||
expect(feature.canDropMilvusDatabase.value).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps Legacy MongoDB mutations available while limiting index actions to the Indexes group", () => {
|
||||
mocks.getConfig.mockReturnValue(mongoConfig("mongodb-legacy"));
|
||||
const activeNode = shallowRef(mongoDatabaseNode());
|
||||
|
||||
@@ -290,7 +290,11 @@ export function useSidebarConnectionMutationRuntime(options: SidebarConnectionMu
|
||||
|
||||
const isPinned = computed(() => activeNode.value.pinned || connectionStore.isTreeNodePinned(activeNode.value));
|
||||
const isNodeDefaultDatabase = computed(
|
||||
() => (activeNode.value.type === "database" || activeNode.value.type === "redis-db" || activeNode.value.type === "mongo-db") && !!activeNode.value.connectionId && !!activeNode.value.database && connectionStore.isDefaultDatabase(activeNode.value.connectionId, activeNode.value.database),
|
||||
() =>
|
||||
(activeNode.value.type === "database" || activeNode.value.type === "redis-db" || activeNode.value.type === "mongo-db" || activeNode.value.type === "vector-database") &&
|
||||
!!activeNode.value.connectionId &&
|
||||
!!activeNode.value.database &&
|
||||
connectionStore.isDefaultDatabase(activeNode.value.connectionId, activeNode.value.database),
|
||||
);
|
||||
const isNodeDefaultSchema = computed(() => activeNode.value.type === "schema" && !!activeNode.value.connectionId && !!activeNode.value.schema && connectionStore.isDefaultSchema(activeNode.value.connectionId, activeNode.value.schema));
|
||||
const isConnected = computed(() => activeNode.value.type === "connection" && !!activeNode.value.connectionId && connectionStore.connectedIds.has(activeNode.value.connectionId));
|
||||
|
||||
@@ -117,6 +117,15 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
}
|
||||
|
||||
const canDropMongoDatabase = computed(() => activeNode.value.type === "mongo-db" && !!activeNode.value.database && usesAnyMongoDriver(activeNode.value));
|
||||
function canDropMilvusDatabaseNode(node: TreeNode): boolean {
|
||||
const connectionId = node.connectionId;
|
||||
const database = node.database;
|
||||
if (node.type !== "vector-database" || !connectionId || !database || database === "default") return false;
|
||||
const config = connectionStore.getConfig(connectionId);
|
||||
return config?.db_type === "milvus" && config.database !== database;
|
||||
}
|
||||
|
||||
const canDropMilvusDatabase = computed(() => canDropMilvusDatabaseNode(activeNode.value));
|
||||
|
||||
function canMutateMongoCollectionNode(node: TreeNode): boolean {
|
||||
if (node.type !== "mongo-collection" || !node.connectionId || !node.database) return false;
|
||||
@@ -132,6 +141,7 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
}
|
||||
|
||||
const canDropMongoCollection = computed(() => canMutateMongoCollectionNode(activeNode.value));
|
||||
const canDropMilvusCollection = computed(() => activeNode.value.type === "vector-collection" && !!activeNode.value.connectionId && !!activeNode.value.database && connectionStore.getConfig(activeNode.value.connectionId)?.db_type === "milvus");
|
||||
const canRenameMongoCollection = computed(() => canRenameMongoCollectionNode(activeNode.value));
|
||||
const canCloneMongoCollection = computed(() => canCloneMongoCollectionNode(activeNode.value));
|
||||
|
||||
@@ -732,6 +742,10 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
showDropMongoCollectionConfirm.value = true;
|
||||
}
|
||||
|
||||
function dropMilvusCollection() {
|
||||
dropMongoCollection();
|
||||
}
|
||||
|
||||
function dropMongoIndex() {
|
||||
dropMongoIndexLoading.value = false;
|
||||
showDropMongoIndexConfirm.value = true;
|
||||
@@ -836,8 +850,6 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
toast(t("contextMenu.dropCollectionSuccess", { name: collectionName }), 3000);
|
||||
showDropMongoCollectionConfirm.value = false;
|
||||
await refreshMongoTreeAfterDrop(node, async () => {
|
||||
// The final collection can remove its database; if the database
|
||||
// remains, refresh its preserved expanded children as well.
|
||||
await connectionStore.loadMongoDatabases(connectionId);
|
||||
await connectionStore.loadMongoCollections(connectionId, database);
|
||||
});
|
||||
@@ -846,6 +858,54 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
});
|
||||
}
|
||||
|
||||
async function confirmDropMilvusDatabase() {
|
||||
const node = sidebarDangerTarget.value ?? activeNode.value;
|
||||
const connectionId = node.connectionId;
|
||||
const database = node.database;
|
||||
if (!connectionId || !database || !canDropMilvusDatabaseNode(node)) return;
|
||||
await runMongoSidebarMutation({
|
||||
connection: connectionStore.getConfig(connectionId),
|
||||
database,
|
||||
reviewText: `POST /v2/vectordb/databases/drop\n{"dbName":${JSON.stringify(database)}}`,
|
||||
source: t("production.sourceSidebar"),
|
||||
loading: dropDatabaseLoading,
|
||||
beforeExecute: () => connectionStore.ensureConnected(connectionId),
|
||||
execute: () => api.vectorDropDatabase(connectionId, database),
|
||||
onSuccess: async () => {
|
||||
toast(t("contextMenu.dropDatabaseSuccess", { name: node.label }), 3000);
|
||||
showDropDatabaseConfirm.value = false;
|
||||
await refreshMongoTreeAfterDrop(node, () => connectionStore.loadMilvusDatabases(connectionId));
|
||||
},
|
||||
onError: toastMutationError,
|
||||
});
|
||||
}
|
||||
|
||||
async function confirmDropMilvusCollection() {
|
||||
const node = sidebarDangerTarget.value ?? activeNode.value;
|
||||
const connectionId = node.connectionId;
|
||||
const database = node.database;
|
||||
if (node.type !== "vector-collection" || !connectionId || !database || connectionStore.getConfig(connectionId)?.db_type !== "milvus") return;
|
||||
const collectionName = node.label;
|
||||
await runMongoSidebarMutation({
|
||||
connection: connectionStore.getConfig(connectionId),
|
||||
database,
|
||||
reviewText: `POST /v2/vectordb/collections/drop\n{"dbName":${JSON.stringify(database)},"collectionName":${JSON.stringify(collectionName)}}`,
|
||||
source: t("production.sourceSidebar"),
|
||||
loading: dropMongoCollectionLoading,
|
||||
beforeExecute: () => connectionStore.ensureConnected(connectionId),
|
||||
execute: () => api.vectorDropCollection(connectionId, database, collectionName),
|
||||
onSuccess: async () => {
|
||||
toast(t("contextMenu.dropCollectionSuccess", { name: collectionName }), 3000);
|
||||
showDropMongoCollectionConfirm.value = false;
|
||||
await refreshMongoTreeAfterDrop(node, async () => {
|
||||
await connectionStore.loadMilvusDatabases(connectionId);
|
||||
await connectionStore.loadVectorCollections(connectionId, database);
|
||||
});
|
||||
},
|
||||
onError: toastMutationError,
|
||||
});
|
||||
}
|
||||
|
||||
async function refreshMongoTreeAfterDrop(node: TreeNode, refresh: () => Promise<void>) {
|
||||
try {
|
||||
await refresh();
|
||||
@@ -937,7 +997,9 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
|
||||
return {
|
||||
canDropMongoDatabase,
|
||||
canDropMilvusDatabase,
|
||||
canDropMongoCollection,
|
||||
canDropMilvusCollection,
|
||||
canRenameMongoCollection,
|
||||
canCloneMongoCollection,
|
||||
prepareRenameMongoCollectionDialog,
|
||||
@@ -998,6 +1060,9 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
||||
confirmFlushRedisDb,
|
||||
confirmDropMongoDatabase,
|
||||
confirmDropMongoCollection,
|
||||
confirmDropMilvusDatabase,
|
||||
confirmDropMilvusCollection,
|
||||
dropMilvusCollection,
|
||||
confirmDropMongoIndex,
|
||||
confirmDropAllMongoIndexes,
|
||||
};
|
||||
|
||||
@@ -700,6 +700,8 @@ export const documentDownloadGridFsFile = forward("documentDownloadGridFsFile");
|
||||
export const documentUploadGridFsFile = forward("documentUploadGridFsFile");
|
||||
export const documentDeleteGridFsFile = forward("documentDeleteGridFsFile");
|
||||
export const vectorGetCollectionDetail = forward("vectorGetCollectionDetail");
|
||||
export const vectorDropDatabase = forward("vectorDropDatabase");
|
||||
export const vectorDropCollection = forward("vectorDropCollection");
|
||||
export const mongoCreateDatabase = forward("mongoCreateDatabase");
|
||||
export const mongoDropDatabase = forward("mongoDropDatabase");
|
||||
export const mongoDropCollection = forward("mongoDropCollection");
|
||||
|
||||
@@ -3589,6 +3589,14 @@ export async function vectorGetCollectionDetail(connectionId: string, database:
|
||||
});
|
||||
}
|
||||
|
||||
export async function vectorDropDatabase(connectionId: string, database: string): Promise<void> {
|
||||
await post("/api/vector/drop-database", { connectionId, database });
|
||||
}
|
||||
|
||||
export async function vectorDropCollection(connectionId: string, database: string, collection: string): Promise<void> {
|
||||
await post("/api/vector/drop-collection", { connectionId, database, collection });
|
||||
}
|
||||
|
||||
export async function mongoFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, projection?: string, sort?: string, collation?: string, executionId?: string): Promise<MongoDocumentResult> {
|
||||
return documentFindDocuments(connectionId, database, collection, skip, limit, filter, projection, sort, collation, executionId);
|
||||
}
|
||||
|
||||
@@ -3504,6 +3504,14 @@ export async function mongoCloneCollection(connectionId: string, database: strin
|
||||
});
|
||||
}
|
||||
|
||||
export async function vectorDropDatabase(connectionId: string, database: string): Promise<void> {
|
||||
return invoke("vector_drop_database", { connectionId, database });
|
||||
}
|
||||
|
||||
export async function vectorDropCollection(connectionId: string, database: string, collection: string): Promise<void> {
|
||||
return invoke("vector_drop_collection", { connectionId, database, collection });
|
||||
}
|
||||
|
||||
export async function elasticsearchListIndices(connectionId: string): Promise<string[]> {
|
||||
const collections = await documentListCollections(connectionId, "default");
|
||||
return collections.map((c) => c.name);
|
||||
|
||||
@@ -239,6 +239,31 @@ pub async fn list_databases(client: &VectorClient) -> Result<Vec<String>, String
|
||||
}
|
||||
}
|
||||
|
||||
/// Drop a Milvus database through the v2 REST API.
|
||||
pub async fn drop_database(client: &VectorClient, database: &str) -> Result<(), String> {
|
||||
if client.kind != VectorDbKind::Milvus {
|
||||
return Err("Database deletion is only supported for Milvus connections".to_string());
|
||||
}
|
||||
send_json(client.post("/v2/vectordb/databases/drop").json(&serde_json::json!({ "dbName": database })), client.kind)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// Drop a Milvus collection through the v2 REST API.
|
||||
pub async fn drop_collection(client: &VectorClient, database: &str, collection: &str) -> Result<(), String> {
|
||||
if client.kind != VectorDbKind::Milvus {
|
||||
return Err("Collection deletion is only supported for Milvus connections".to_string());
|
||||
}
|
||||
send_json(
|
||||
client
|
||||
.post("/v2/vectordb/collections/drop")
|
||||
.json(&serde_json::json!({ "dbName": database, "collectionName": collection })),
|
||||
client.kind,
|
||||
)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
async fn list_milvus_databases(client: &VectorClient) -> Result<Vec<String>, String> {
|
||||
// Older Milvus versions (pre-2.2) do not expose the databases endpoint; fall back to the
|
||||
// configured database (or "default") so the connection stays browsable instead of failing the whole tree load.
|
||||
@@ -254,11 +279,15 @@ async fn list_milvus_databases(client: &VectorClient) -> Result<Vec<String>, Str
|
||||
}
|
||||
|
||||
fn milvus_database_names(body: &Value, configured_database: &str) -> Vec<String> {
|
||||
let has_database_list = body.get("data").is_some_and(Value::is_array);
|
||||
let mut names: Vec<String> = match body.get("data") {
|
||||
Some(Value::Array(items)) => items.iter().filter_map(milvus_database_name_from_item).collect(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
if !names.iter().any(|name| name == configured_database) {
|
||||
// Only use the configured database as a compatibility fallback when the
|
||||
// server does not return a database list. This lets a successfully dropped
|
||||
// database disappear from the sidebar instead of being re-added locally.
|
||||
if !has_database_list && !names.iter().any(|name| name == configured_database) {
|
||||
names.push(configured_database.to_string());
|
||||
}
|
||||
names.sort();
|
||||
@@ -1061,11 +1090,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn milvus_database_list_keeps_the_configured_database() {
|
||||
assert_eq!(
|
||||
milvus_database_names(&json!({ "data": ["default"] }), "resume_test"),
|
||||
vec!["default".to_string(), "resume_test".to_string()]
|
||||
);
|
||||
fn milvus_database_list_does_not_readd_deleted_configured_database() {
|
||||
assert_eq!(milvus_database_names(&json!({ "data": ["default"] }), "resume_test"), vec!["default".to_string()]);
|
||||
assert_eq!(
|
||||
milvus_database_names(&json!({ "data": ["resume_test"] }), "resume_test"),
|
||||
vec!["resume_test".to_string()]
|
||||
|
||||
@@ -1089,6 +1089,35 @@ pub async fn get_vector_collection_detail_core(
|
||||
db::vector_driver::get_collection_detail(&client, database, collection).await
|
||||
}
|
||||
|
||||
pub async fn drop_vector_database_core(state: &AppState, connection_id: &str, database: &str) -> Result<(), String> {
|
||||
let pool_key = state.get_or_create_metadata_pool_for_session(connection_id, Some(database), None).await?;
|
||||
let client = {
|
||||
let connections = state.connections.read().await;
|
||||
match connections.get(&pool_key) {
|
||||
Some(PoolKind::VectorDb(client)) => client.clone(),
|
||||
_ => return Err("Not a vector database connection".to_string()),
|
||||
}
|
||||
};
|
||||
db::vector_driver::drop_database(&client, database).await
|
||||
}
|
||||
|
||||
pub async fn drop_vector_collection_core(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
database: &str,
|
||||
collection: &str,
|
||||
) -> Result<(), String> {
|
||||
let pool_key = state.get_or_create_metadata_pool_for_session(connection_id, Some(database), None).await?;
|
||||
let client = {
|
||||
let connections = state.connections.read().await;
|
||||
match connections.get(&pool_key) {
|
||||
Some(PoolKind::VectorDb(client)) => client.clone(),
|
||||
_ => return Err("Not a vector database connection".to_string()),
|
||||
}
|
||||
};
|
||||
db::vector_driver::drop_collection(&client, database, collection).await
|
||||
}
|
||||
|
||||
pub async fn get_table_comment_core(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
|
||||
@@ -776,6 +776,8 @@ async fn main() {
|
||||
.route("/mongo/list-databases", post(routes::mongo::list_databases))
|
||||
.route("/mongo/list-collections", post(routes::mongo::list_collections))
|
||||
.route("/mongo/vector-collection-detail", post(routes::mongo::vector_collection_detail))
|
||||
.route("/vector/drop-database", post(routes::mongo::vector_drop_database))
|
||||
.route("/vector/drop-collection", post(routes::mongo::vector_drop_collection))
|
||||
.route("/mongo/create-database", post(routes::mongo::create_database))
|
||||
.route("/mongo/drop-database", post(routes::mongo::drop_database))
|
||||
.route("/mongo/drop-collection", post(routes::mongo::drop_collection))
|
||||
|
||||
@@ -367,6 +367,34 @@ pub async fn vector_collection_detail(
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
pub async fn vector_drop_database(
|
||||
State(state): State<Arc<WebState>>,
|
||||
headers: HeaderMap,
|
||||
Json(req): Json<MongoCollectionRequest>,
|
||||
) -> Result<Json<serde_json::Value>, AppError> {
|
||||
super::mcp_policy::ensure_dangerous_write(&state, &headers, &req.connection_id, &req.database, "Drop database")
|
||||
.await?;
|
||||
ensure_writable(&state.app, &req.connection_id, "Drop database").await?;
|
||||
dbx_core::schema::drop_vector_database_core(&state.app, &req.connection_id, &req.database)
|
||||
.await
|
||||
.map_err(AppError::from)?;
|
||||
Ok(Json(serde_json::json!({ "ok": true })))
|
||||
}
|
||||
|
||||
pub async fn vector_drop_collection(
|
||||
State(state): State<Arc<WebState>>,
|
||||
headers: HeaderMap,
|
||||
Json(req): Json<MongoCollectionNameRequest>,
|
||||
) -> Result<Json<serde_json::Value>, AppError> {
|
||||
super::mcp_policy::ensure_dangerous_write(&state, &headers, &req.connection_id, &req.database, "Drop collection")
|
||||
.await?;
|
||||
ensure_writable(&state.app, &req.connection_id, "Drop collection").await?;
|
||||
dbx_core::schema::drop_vector_collection_core(&state.app, &req.connection_id, &req.database, &req.collection)
|
||||
.await
|
||||
.map_err(AppError::from)?;
|
||||
Ok(Json(serde_json::json!({ "ok": true })))
|
||||
}
|
||||
|
||||
pub async fn create_database(
|
||||
State(state): State<Arc<WebState>>,
|
||||
Json(req): Json<MongoCollectionRequest>,
|
||||
|
||||
@@ -86,6 +86,27 @@ pub async fn mongo_drop_collection(
|
||||
dbx_core::mongo_ops::mongo_drop_collection_core(&state, &connection_id, &database, &collection).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vector_drop_database(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
database: String,
|
||||
) -> Result<(), String> {
|
||||
ensure_connection_writable(&state, &connection_id, "Drop database").await?;
|
||||
dbx_core::schema::drop_vector_database_core(&state, &connection_id, &database).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vector_drop_collection(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
database: String,
|
||||
collection: String,
|
||||
) -> Result<(), String> {
|
||||
ensure_connection_writable(&state, &connection_id, "Drop collection").await?;
|
||||
dbx_core::schema::drop_vector_collection_core(&state, &connection_id, &database, &collection).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn mongo_rename_collection(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
|
||||
@@ -2006,6 +2006,8 @@ pub fn run() {
|
||||
commands::mongo_cmd::mongo_create_database,
|
||||
commands::mongo_cmd::mongo_drop_database,
|
||||
commands::mongo_cmd::mongo_drop_collection,
|
||||
commands::mongo_cmd::vector_drop_database,
|
||||
commands::mongo_cmd::vector_drop_collection,
|
||||
commands::mongo_cmd::mongo_rename_collection,
|
||||
commands::mongo_cmd::mongo_clone_collection,
|
||||
commands::docs::docs_collect_snapshot,
|
||||
|
||||
Reference in New Issue
Block a user