feat(database): support Doris and StarRocks catalogs

This commit is contained in:
如梦技术 authored and GitHub committed 2026-07-30 16:03:32 +08:00
1 parent b39a0f18a4
commit adb6d86b53
44 files changed
+1330 -242

No files matched your search

@@ -0,0 +1,38 @@
import { describe, expect, it } from "vitest";
import { isSameTransferDatabase, normalizeTransferCatalog, type TransferDatabaseSelection } from "@/lib/database/dataTransferSelection";
import type { CatalogInfo } from "@/types/database";
function catalog(name: string, catalog_type: string): CatalogInfo {
return { name, catalog_type, is_current: false };
}
function selection(overrides: Partial<TransferDatabaseSelection> = {}): TransferDatabaseSelection {
return {
connectionId: "connection-1",
catalog: "",
catalogs: [],
database: "sales",
...overrides,
};
}
describe("data transfer database selection", () => {
it("normalizes empty, Doris internal, and StarRocks default catalogs", () => {
expect(normalizeTransferCatalog("", [])).toBe("");
expect(normalizeTransferCatalog("internal", [])).toBe("");
expect(normalizeTransferCatalog("default_catalog", [catalog("default_catalog", "Internal")])).toBe("");
});
it("treats internal catalog aliases as the same transfer database", () => {
expect(isSameTransferDatabase(selection(), selection({ catalog: "internal", catalogs: [catalog("internal", "internal")] }))).toBe(true);
expect(isSameTransferDatabase(selection(), selection({ catalog: "default_catalog", catalogs: [catalog("default_catalog", "Internal")] }))).toBe(true);
});
it("keeps different external catalogs distinct", () => {
expect(isSameTransferDatabase(selection({ catalog: "iceberg", catalogs: [catalog("iceberg", "Iceberg")] }), selection({ catalog: "hive", catalogs: [catalog("hive", "Hive")] }))).toBe(false);
});
it("compares connection and database fields without concatenation collisions", () => {
expect(isSameTransferDatabase(selection({ connectionId: "ab", database: "c" }), selection({ connectionId: "a", database: "bc" }))).toBe(false);
});
});
+2
View File
@@ -3170,9 +3170,11 @@ export interface TransferRequest {
sourceConnectionId: string;
sourceDatabase: string;
sourceSchema: string;
sourceCatalog?: string;
targetConnectionId: string;
targetDatabase: string;
targetSchema: string;
targetCatalog?: string;
tables: string[];
createTable: boolean;
mode: TransferMode;
@@ -0,0 +1,20 @@
import { isInternalDorisCatalog } from "@/lib/database/databaseFeatureSupport";
import type { CatalogInfo } from "@/types/database";
export interface TransferDatabaseSelection {
connectionId: string;
catalog: string;
catalogs: readonly CatalogInfo[];
database: string;
}
export function normalizeTransferCatalog(catalog: string, catalogs: readonly CatalogInfo[]): string {
const normalizedCatalog = catalog.trim();
if (!normalizedCatalog) return "";
const catalogInfo = catalogs.find((item) => item.name.trim() === normalizedCatalog);
return isInternalDorisCatalog(catalogInfo?.catalog_type, normalizedCatalog) ? "" : normalizedCatalog;
}
export function isSameTransferDatabase(source: TransferDatabaseSelection, target: TransferDatabaseSelection): boolean {
return source.connectionId === target.connectionId && source.database === target.database && normalizeTransferCatalog(source.catalog, source.catalogs) === normalizeTransferCatalog(target.catalog, target.catalogs);
}
@@ -1,12 +1,13 @@
import type { TreeNode } from "@/types/database";
export function findDatabaseTreeNode(nodes: TreeNode[], connectionId: string, database: string): TreeNode | null {
export function findDatabaseTreeNode(nodes: TreeNode[], connectionId: string, database: string, catalog?: string): TreeNode | null {
for (const node of nodes) {
if (node.type === "database" && node.connectionId === connectionId && node.database === database) {
const catalogMatches = catalog ? node.catalog === catalog : !node.catalog;
if (node.type === "database" && node.connectionId === connectionId && node.database === database && catalogMatches) {
return node;
}
if (node.children) {
const found = findDatabaseTreeNode(node.children, connectionId, database);
const found = findDatabaseTreeNode(node.children, connectionId, database, catalog);
if (found) return found;
}
}