refactor(frontend): centralize database feature capabilities

This commit is contained in:
t8y2 committed 2026-05-13 22:14:33 +08:00
1 parent 298f57c160
commit 5832e1b194
12 files changed
+435 -204

No files matched your search

+3 -178
View File
@@ -1,178 +1,3 @@
import type { DatabaseType } from "@/types/database";
export const SCHEMA_AWARE_TYPES = new Set<DatabaseType>([
"postgres",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"jdbc",
"h2",
"snowflake",
"trino",
"db2",
"informix",
]);
export const SQL_FILE_UNSUPPORTED_TYPES = new Set<DatabaseType>(["redis", "mongodb", "elasticsearch"]);
export const DIAGRAM_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
"h2",
"db2",
]);
export const DATABASE_SEARCH_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"duckdb",
"clickhouse",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
"h2",
"snowflake",
"trino",
"hive",
"db2",
"informix",
"neo4j",
"cassandra",
"bigquery",
"kylin",
"sundb",
]);
export const TABLE_IMPORT_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"duckdb",
"clickhouse",
"sqlserver",
"oracle",
"doris",
"starrocks",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
]);
export const TABLE_STRUCTURE_SUPPORTED_TYPES = new Set<DatabaseType>(["mysql", "postgres", "sqlite", "sqlserver"]);
export const CREATE_DATABASE_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlserver",
"clickhouse",
"oracle",
"dameng",
"gaussdb",
"doris",
"starrocks",
"redshift",
]);
export const FIELD_LINEAGE_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
]);
export const SINGLE_DATABASE_TYPES = new Set<DatabaseType>(["oracle", "dameng"]);
export const FETCH_FIRST_TYPES = new Set<DatabaseType>(["oracle", "dameng"]);
export const TREE_SCHEMA_TYPES = new Set<DatabaseType>([
"postgres",
"redshift",
"sqlserver",
"gaussdb",
"jdbc",
"trino",
"h2",
]);
export const PG_LIKE_STRUCTURE_TYPES = new Set<DatabaseType>(["postgres", "redshift", "gaussdb"]);
export const AGENT_DRIVER_TYPES = new Set<DatabaseType>([
"dameng",
"kingbase",
"vastbase",
"goldendb",
"oracle",
"h2",
"snowflake",
"trino",
"hive",
"db2",
"informix",
"neo4j",
"cassandra",
"bigquery",
"kylin",
"sundb",
"gaussdb",
]);
export const TRANSFER_SQL_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"clickhouse",
"duckdb",
"dameng",
"gaussdb",
]);
export const DIAGRAM_SQL_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
]);
export function isSchemaAware(dbType?: DatabaseType): boolean {
return !!dbType && SCHEMA_AWARE_TYPES.has(dbType);
}
export function isSingleDatabase(dbType?: DatabaseType): boolean {
return !!dbType && SINGLE_DATABASE_TYPES.has(dbType);
}
export function usesFetchFirst(dbType?: DatabaseType): boolean {
return !!dbType && FETCH_FIRST_TYPES.has(dbType);
}
export * from "./databaseCapabilitySets";
export * from "./databaseFeatureSupport";
export * from "./databaseTableDataCapabilities";
+166
View File
@@ -0,0 +1,166 @@
import type { DatabaseType } from "@/types/database";
export const SCHEMA_AWARE_TYPES = new Set<DatabaseType>([
"postgres",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"jdbc",
"h2",
"snowflake",
"trino",
"db2",
"informix",
]);
export const SQL_FILE_UNSUPPORTED_TYPES = new Set<DatabaseType>(["redis", "mongodb", "elasticsearch"]);
export const DIAGRAM_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
"h2",
"db2",
]);
export const DATABASE_SEARCH_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"duckdb",
"clickhouse",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
"h2",
"snowflake",
"trino",
"hive",
"db2",
"informix",
"neo4j",
"cassandra",
"bigquery",
"kylin",
"sundb",
]);
export const TABLE_IMPORT_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"duckdb",
"clickhouse",
"sqlserver",
"oracle",
"doris",
"starrocks",
"redshift",
"dameng",
"gaussdb",
"kingbase",
"vastbase",
"goldendb",
]);
export const TABLE_STRUCTURE_SUPPORTED_TYPES = new Set<DatabaseType>(["mysql", "postgres", "sqlite", "sqlserver"]);
export const CREATE_DATABASE_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlserver",
"clickhouse",
"oracle",
"dameng",
"gaussdb",
"doris",
"starrocks",
"redshift",
]);
export const FIELD_LINEAGE_SUPPORTED_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
]);
export const SINGLE_DATABASE_TYPES = new Set<DatabaseType>(["oracle", "dameng"]);
export const FETCH_FIRST_TYPES = new Set<DatabaseType>(["oracle", "dameng"]);
export const TREE_SCHEMA_TYPES = new Set<DatabaseType>([
"postgres",
"redshift",
"sqlserver",
"gaussdb",
"jdbc",
"trino",
"h2",
]);
export const PG_LIKE_STRUCTURE_TYPES = new Set<DatabaseType>(["postgres", "redshift", "gaussdb"]);
export const AGENT_DRIVER_TYPES = new Set<DatabaseType>([
"dameng",
"kingbase",
"vastbase",
"goldendb",
"oracle",
"h2",
"snowflake",
"trino",
"hive",
"db2",
"informix",
"neo4j",
"cassandra",
"bigquery",
"kylin",
"sundb",
"gaussdb",
]);
export const TRANSFER_SQL_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"clickhouse",
"duckdb",
"dameng",
"gaussdb",
]);
export const DIAGRAM_SQL_TYPES = new Set<DatabaseType>([
"mysql",
"postgres",
"sqlite",
"sqlserver",
"oracle",
"redshift",
"dameng",
"gaussdb",
]);
+81
View File
@@ -0,0 +1,81 @@
import type { DatabaseType } from "@/types/database";
import {
AGENT_DRIVER_TYPES,
CREATE_DATABASE_SUPPORTED_TYPES,
DATABASE_SEARCH_SUPPORTED_TYPES,
DIAGRAM_SUPPORTED_TYPES,
FETCH_FIRST_TYPES,
FIELD_LINEAGE_SUPPORTED_TYPES,
PG_LIKE_STRUCTURE_TYPES,
SCHEMA_AWARE_TYPES,
SINGLE_DATABASE_TYPES,
SQL_FILE_UNSUPPORTED_TYPES,
TABLE_IMPORT_SUPPORTED_TYPES,
TABLE_STRUCTURE_SUPPORTED_TYPES,
TRANSFER_SQL_TYPES,
TREE_SCHEMA_TYPES,
} from "./databaseCapabilitySets";
export function isSchemaAware(dbType?: DatabaseType): boolean {
return !!dbType && SCHEMA_AWARE_TYPES.has(dbType);
}
export function usesTreeSchemaMode(dbType?: DatabaseType): boolean {
return !!dbType && TREE_SCHEMA_TYPES.has(dbType);
}
export function isSingleDatabase(dbType?: DatabaseType): boolean {
return !!dbType && SINGLE_DATABASE_TYPES.has(dbType);
}
export function usesFetchFirst(dbType?: DatabaseType): boolean {
return !!dbType && FETCH_FIRST_TYPES.has(dbType);
}
export function supportsSqlFileExecution(dbType?: DatabaseType): boolean {
return !!dbType && !SQL_FILE_UNSUPPORTED_TYPES.has(dbType);
}
export function supportsSchemaDiagram(dbType?: DatabaseType): boolean {
return !!dbType && DIAGRAM_SUPPORTED_TYPES.has(dbType);
}
export function supportsDatabaseSearch(dbType?: DatabaseType): boolean {
return !!dbType && DATABASE_SEARCH_SUPPORTED_TYPES.has(dbType);
}
export function supportsTableImport(dbType?: DatabaseType): boolean {
return !!dbType && TABLE_IMPORT_SUPPORTED_TYPES.has(dbType);
}
export function supportsTableStructureEditing(dbType?: DatabaseType): boolean {
return !!dbType && TABLE_STRUCTURE_SUPPORTED_TYPES.has(dbType);
}
export function supportsDatabaseCreation(dbType?: DatabaseType): boolean {
return !!dbType && CREATE_DATABASE_SUPPORTED_TYPES.has(dbType);
}
export function supportsFieldLineage(dbType?: DatabaseType): boolean {
return !!dbType && FIELD_LINEAGE_SUPPORTED_TYPES.has(dbType);
}
export function supportsTransfer(dbType?: DatabaseType): boolean {
return !!dbType && TRANSFER_SQL_TYPES.has(dbType);
}
export function supportsDriverManagement(dbType?: DatabaseType): boolean {
return !!dbType && AGENT_DRIVER_TYPES.has(dbType);
}
export function supportsObjectBrowser(dbType?: DatabaseType): boolean {
return !!dbType && !["redis", "mongodb", "elasticsearch"].includes(dbType);
}
export function supportsTableTruncate(dbType?: DatabaseType): boolean {
return !!dbType && dbType !== "sqlite" && dbType !== "duckdb";
}
export function usesPostgresLikeStructureCopy(dbType?: DatabaseType): boolean {
return !!dbType && PG_LIKE_STRUCTURE_TYPES.has(dbType);
}
+74
View File
@@ -0,0 +1,74 @@
import type { DatabaseType } from "@/types/database";
import { isSchemaAware, usesTreeSchemaMode } from "./databaseFeatureSupport";
export type SyntheticEditKey = "oracle-rowid" | "neo4j-element-id";
export interface TableDataCapability {
insert: boolean;
updateRequiresPrimaryKey: boolean;
deleteRequiresPrimaryKey: boolean;
requiresTransactionalTableForExistingRows: boolean;
transaction: boolean;
}
export interface DatabaseCapability {
schemaAware: boolean;
treeSchemaMode: boolean;
tableData: TableDataCapability;
syntheticKey?: SyntheticEditKey;
}
const DEFAULT_TABLE_DATA_CAPABILITY: TableDataCapability = {
insert: false,
updateRequiresPrimaryKey: true,
deleteRequiresPrimaryKey: true,
requiresTransactionalTableForExistingRows: false,
transaction: true,
};
const DEFAULT_CAPABILITY: DatabaseCapability = {
schemaAware: false,
treeSchemaMode: false,
tableData: DEFAULT_TABLE_DATA_CAPABILITY,
};
const DATABASE_CAPABILITY_OVERRIDES: Partial<Record<DatabaseType, Partial<DatabaseCapability>>> = {
hive: {
tableData: {
insert: true,
updateRequiresPrimaryKey: false,
deleteRequiresPrimaryKey: false,
requiresTransactionalTableForExistingRows: true,
transaction: false,
},
},
neo4j: {
syntheticKey: "neo4j-element-id",
},
oracle: {
syntheticKey: "oracle-rowid",
},
trino: {
tableData: {
insert: true,
updateRequiresPrimaryKey: true,
deleteRequiresPrimaryKey: true,
requiresTransactionalTableForExistingRows: false,
transaction: false,
},
},
};
export function getDatabaseCapability(dbType?: DatabaseType): DatabaseCapability {
const override = dbType ? DATABASE_CAPABILITY_OVERRIDES[dbType] : undefined;
return {
...DEFAULT_CAPABILITY,
...override,
schemaAware: isSchemaAware(dbType),
treeSchemaMode: usesTreeSchemaMode(dbType),
tableData: {
...DEFAULT_TABLE_DATA_CAPABILITY,
...override?.tableData,
},
};
}
+10 -8
View File
@@ -1,32 +1,34 @@
import type { ColumnInfo, DatabaseType } from "@/types/database";
import { getDatabaseCapability } from "./databaseCapabilities";
export const DBX_ROWID_COLUMN = "__DBX_ROWID";
export const DBX_NEO4J_ELEMENT_ID_COLUMN = "__DBX_ELEMENT_ID";
export function editablePrimaryKeys(databaseType: DatabaseType | undefined, columns: ColumnInfo[]): string[] {
const primaryKeys = columns.filter((column) => column.is_primary_key).map((column) => column.name);
if (databaseType === "oracle" && primaryKeys.length === 0) return [DBX_ROWID_COLUMN];
if (databaseType === "neo4j" && primaryKeys.length === 0) return [DBX_NEO4J_ELEMENT_ID_COLUMN];
const syntheticKey = getDatabaseCapability(databaseType).syntheticKey;
if (syntheticKey === "oracle-rowid" && primaryKeys.length === 0) return [DBX_ROWID_COLUMN];
if (syntheticKey === "neo4j-element-id" && primaryKeys.length === 0) return [DBX_NEO4J_ELEMENT_ID_COLUMN];
return primaryKeys;
}
export function isTableDataEditable(databaseType: DatabaseType | undefined, primaryKeys: string[]): boolean {
if (databaseType === "hive") return true;
if (databaseType === "trino") return true;
if (getDatabaseCapability(databaseType).tableData.insert) return true;
return primaryKeys.length > 0;
}
export function supportsDataGridTransaction(databaseType: DatabaseType | undefined): boolean {
return databaseType !== "hive" && databaseType !== "trino";
return getDatabaseCapability(databaseType).tableData.transaction;
}
export function canEditExistingTableRows(
databaseType: DatabaseType | undefined,
hiveTableTransactional?: boolean,
primaryKeys: string[] = [],
primaryKeys?: string[],
): boolean {
if (databaseType === "hive") return hiveTableTransactional === true;
if (databaseType === "trino") return primaryKeys.length > 0;
const tableData = getDatabaseCapability(databaseType).tableData;
if (tableData.requiresTransactionalTableForExistingRows && hiveTableTransactional !== true) return false;
if (tableData.updateRequiresPrimaryKey && primaryKeys && primaryKeys.length === 0) return false;
return true;
}