feat(vector): add qdrant and milvus support
This commit is contained in:
1 parent
fffdcb9db1
commit
e27d34a34a
45 files changed
+1116
-29
No files matched your search
@@ -338,6 +338,7 @@ export const mongoDeleteDocuments = forward("mongoDeleteDocuments");
|
||||
|
||||
// Elasticsearch
|
||||
export const elasticsearchListIndices = forward("elasticsearchListIndices");
|
||||
export const vectorListCollections = forward("vectorListCollections");
|
||||
|
||||
// History
|
||||
export const saveHistory = forward("saveHistory");
|
||||
|
||||
@@ -127,6 +127,8 @@ export function connectionUrlPlaceholder(dbType: DatabaseType): string {
|
||||
return "oracle://user:password@host:port/service_name";
|
||||
|
||||
case "elasticsearch":
|
||||
case "qdrant":
|
||||
case "milvus":
|
||||
return "http://user:password@host:port";
|
||||
|
||||
case "dameng":
|
||||
|
||||
@@ -39,6 +39,8 @@ const SCHEME_PROFILES: Record<string, ConnectionProfile> = {
|
||||
mssql: { type: "sqlserver", profile: "sqlserver", label: "SQL Server", defaultPort: 1433 },
|
||||
oracle: { type: "oracle", profile: "oracle", label: "Oracle", defaultPort: 1521 },
|
||||
elasticsearch: { type: "elasticsearch", profile: "elasticsearch", label: "Elasticsearch", defaultPort: 9200 },
|
||||
qdrant: { type: "qdrant", profile: "qdrant", label: "Qdrant", defaultPort: 6333 },
|
||||
milvus: { type: "milvus", profile: "milvus", label: "Milvus", defaultPort: 19530 },
|
||||
dm: { type: "dameng", profile: "dm", label: "DM (Dameng)", defaultPort: 5236 },
|
||||
dameng: { type: "dameng", profile: "dm", label: "DM (Dameng)", defaultPort: 5236 },
|
||||
gaussdb: { type: "gaussdb", profile: "gaussdb", label: "GaussDB", defaultPort: 5432 },
|
||||
@@ -59,6 +61,8 @@ const SCHEME_PROFILES: Record<string, ConnectionProfile> = {
|
||||
const HTTP_SELECTED_PROFILES: Record<string, ConnectionProfile> = {
|
||||
clickhouse: SCHEME_PROFILES.clickhouse,
|
||||
elasticsearch: SCHEME_PROFILES.elasticsearch,
|
||||
qdrant: SCHEME_PROFILES.qdrant,
|
||||
milvus: SCHEME_PROFILES.milvus,
|
||||
};
|
||||
|
||||
function decodeUrlPart(value: string): string {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { filterDatabaseNamesForConnection, normalizeVisibleDatabaseSelection } f
|
||||
|
||||
const DRAFT_VISIBLE_DATABASES_PREFIX = "__visible_draft_";
|
||||
|
||||
const UNSUPPORTED_VISIBLE_DATABASE_TYPES = new Set<DatabaseType>(["elasticsearch", "etcd"]);
|
||||
const UNSUPPORTED_VISIBLE_DATABASE_TYPES = new Set<DatabaseType>(["elasticsearch", "qdrant", "milvus", "etcd"]);
|
||||
|
||||
type VisibleDatabaseConnectionFields = Pick<
|
||||
ConnectionConfig,
|
||||
|
||||
@@ -1460,6 +1460,10 @@ export async function elasticsearchListIndices(connectionId: string): Promise<st
|
||||
return mongoListCollections(connectionId, "default");
|
||||
}
|
||||
|
||||
export async function vectorListCollections(connectionId: string): Promise<string[]> {
|
||||
return mongoListCollections(connectionId, "default");
|
||||
}
|
||||
|
||||
export async function mongoFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise<MongoDocumentResult> {
|
||||
return post("/api/mongo/find-documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ export type ActiveTabSidebarTarget =
|
||||
database: string;
|
||||
collectionName: string;
|
||||
}
|
||||
| {
|
||||
type: "vector-collection";
|
||||
connectionId: string;
|
||||
collectionName: string;
|
||||
}
|
||||
| {
|
||||
type: "etcd-root";
|
||||
connectionId: string;
|
||||
@@ -61,6 +66,16 @@ export function activeTabSidebarTarget(tab: QueryTab | undefined | null): Active
|
||||
};
|
||||
}
|
||||
|
||||
if (tab.mode === "vector") {
|
||||
const collectionName = tab.sql || tab.title;
|
||||
if (!collectionName) return null;
|
||||
return {
|
||||
type: "vector-collection",
|
||||
connectionId: tab.connectionId,
|
||||
collectionName,
|
||||
};
|
||||
}
|
||||
|
||||
if (tab.mode === "etcd") {
|
||||
return { type: "etcd-root", connectionId: tab.connectionId };
|
||||
}
|
||||
@@ -99,6 +114,10 @@ export function matchesTarget(node: TreeNode, target: ActiveTabSidebarTarget): b
|
||||
return node.type === "mongo-collection" && node.connectionId === target.connectionId && node.database === target.database && node.label === target.collectionName;
|
||||
}
|
||||
|
||||
if (target.type === "vector-collection") {
|
||||
return node.type === "vector-collection" && node.connectionId === target.connectionId && node.label === target.collectionName;
|
||||
}
|
||||
|
||||
if (target.type === "query-context") {
|
||||
if (target.schema) {
|
||||
return node.type === "schema" && node.connectionId === target.connectionId && node.database === target.database && node.label === target.schema;
|
||||
|
||||
@@ -30,7 +30,7 @@ export function sortSidebarTreeChildrenForParent(parent: Pick<TreeNode, "type">,
|
||||
const regularChildren = normalized.filter((child) => child.type !== "user-admin" && child.type !== "saved-sql-root");
|
||||
const withConnectionUtilityOrder = (children: TreeNode[]) => [...savedSqlNodes, ...children, ...userAdminNodes];
|
||||
|
||||
if (databaseType === "mongodb" || databaseType === "elasticsearch") {
|
||||
if (databaseType === "mongodb" || databaseType === "elasticsearch" || databaseType === "qdrant" || databaseType === "milvus") {
|
||||
return withConnectionUtilityOrder(sortByLabel(regularChildren));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { TreeNodeType } from "@/types/database";
|
||||
|
||||
const leafTypes: Set<TreeNodeType> = new Set(["column", "index", "fkey", "trigger", "procedure", "function", "package", "package-body", "object-browser", "redis-db", "mq-tenant", "mongo-collection", "elasticsearch-index", "user-admin", "saved-sql-file", "load-more"]);
|
||||
const leafTypes: Set<TreeNodeType> = new Set(["column", "index", "fkey", "trigger", "procedure", "function", "package", "package-body", "object-browser", "redis-db", "mq-tenant", "mongo-collection", "vector-collection", "elasticsearch-index", "user-admin", "saved-sql-file", "load-more"]);
|
||||
|
||||
const fullWidthLabelTypes: Set<TreeNodeType> = new Set(["table", "view", "materialized_view", "mongo-collection", "elasticsearch-index"]);
|
||||
const fullWidthLabelTypes: Set<TreeNodeType> = new Set(["table", "view", "materialized_view", "mongo-collection", "vector-collection", "elasticsearch-index"]);
|
||||
|
||||
const emptyContainerTypes: Set<TreeNodeType> = new Set(["saved-sql-root", "saved-sql-folder"]);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ export function areSqlSemanticDiagnosticsEqual(left: readonly SqlSemanticDiagnos
|
||||
}
|
||||
|
||||
export function shouldRunSqlSemanticDiagnostics(sql: string, cursor: number, options: { databaseType?: DatabaseType } = {}): boolean {
|
||||
if (options.databaseType === "mongodb" || options.databaseType === "elasticsearch" || options.databaseType === "redis") return false;
|
||||
if (options.databaseType === "mongodb" || options.databaseType === "elasticsearch" || options.databaseType === "qdrant" || options.databaseType === "milvus" || options.databaseType === "redis") return false;
|
||||
const context = getSqlCompletionContext(sql, cursor);
|
||||
if (context.suggestTables || context.exclusiveTableSuggestions || context.exclusiveColumnSuggestions) return false;
|
||||
if (context.qualifier) return false;
|
||||
|
||||
@@ -70,6 +70,10 @@ export function tabDisplayTitle(tab: QueryTab, t: Translate): string {
|
||||
if (compact) return tab.sql;
|
||||
return `${tab.sql}@${database}`;
|
||||
}
|
||||
if (tab.mode === "vector" && tab.sql) {
|
||||
if (compact) return tab.sql;
|
||||
return `${tab.sql}@${database}`;
|
||||
}
|
||||
if (tab.mode === "redis") {
|
||||
if (compact) return connectionDisplayName(tab.connectionId);
|
||||
return `${connectionDisplayName(tab.connectionId)}@${database}`;
|
||||
@@ -106,6 +110,9 @@ export function tabTooltipLines(tab: QueryTab, t: Translate): { label: string; v
|
||||
if (tab.mode === "mongo" && tab.sql) {
|
||||
lines.push({ label: t("tabs.tooltipCollection"), value: tab.sql });
|
||||
}
|
||||
if (tab.mode === "vector" && tab.sql) {
|
||||
lines.push({ label: t("tabs.tooltipCollection"), value: tab.sql });
|
||||
}
|
||||
if (tab.mode === "objects" && tab.objectBrowser?.schema) {
|
||||
lines.push({ label: t("tabs.tooltipSchema"), value: tab.objectBrowser.schema });
|
||||
}
|
||||
@@ -171,6 +178,7 @@ export function tabModeLabel(tab: QueryTab, t: Translate): string {
|
||||
if (tab.mode === "data") return t("tabs.table");
|
||||
if (tab.mode === "query") return t("tabs.sql");
|
||||
if (tab.mode === "mongo") return t("tabs.mongo");
|
||||
if (tab.mode === "vector") return t("tabs.vector");
|
||||
if (tab.mode === "redis") return t("tabs.redis");
|
||||
if (tab.mode === "etcd") return t("tabs.etcd");
|
||||
if (tab.mode === "objects") return t("tabs.objects");
|
||||
|
||||
@@ -31,6 +31,18 @@ const capabilityByType: Partial<Record<DatabaseType, Partial<TableMetadataCapabi
|
||||
triggers: false,
|
||||
ddl: false,
|
||||
},
|
||||
qdrant: {
|
||||
indexes: false,
|
||||
foreignKeys: false,
|
||||
triggers: false,
|
||||
ddl: false,
|
||||
},
|
||||
milvus: {
|
||||
indexes: false,
|
||||
foreignKeys: false,
|
||||
triggers: false,
|
||||
ddl: false,
|
||||
},
|
||||
influxdb: {
|
||||
indexes: false,
|
||||
foreignKeys: false,
|
||||
|
||||
@@ -1300,6 +1300,10 @@ export async function elasticsearchListIndices(connectionId: string): Promise<st
|
||||
return mongoListCollections(connectionId, "default");
|
||||
}
|
||||
|
||||
export async function vectorListCollections(connectionId: string): Promise<string[]> {
|
||||
return mongoListCollections(connectionId, "default");
|
||||
}
|
||||
|
||||
export async function mongoFindDocuments(connectionId: string, database: string, collection: string, skip: number, limit: number, filter?: string, sort?: string, executionId?: string): Promise<MongoDocumentResult> {
|
||||
return invoke("mongo_find_documents", { connectionId, database, collection, skip, limit, filter, sort, executionId });
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export type SidebarSelectionCopyAction = "copy-name" | "none";
|
||||
export type SidebarActivation = "single" | "double";
|
||||
|
||||
const dataNodeTypes = new Set<TreeNodeType>(["table", "view", "materialized_view"]);
|
||||
const toggleLeafNodeTypes = new Set<TreeNodeType>(["redis-db", "mq-tenant", "mongo-collection", "elasticsearch-index", "user-admin"]);
|
||||
const toggleLeafNodeTypes = new Set<TreeNodeType>(["redis-db", "mq-tenant", "mongo-collection", "vector-collection", "elasticsearch-index", "user-admin"]);
|
||||
const objectBrowserNodeTypes = new Set<TreeNodeType>(["database", "schema", "object-browser"]);
|
||||
const sourceNodeTypes = new Set<TreeNodeType>(["materialized_view", "procedure", "function", "sequence", "package", "package-body"]);
|
||||
const savedSqlNodeTypes = new Set<TreeNodeType>(["saved-sql-file"]);
|
||||
|
||||
Reference in new issue
Block a user