feat(metadata): honor system schema visibility
This commit is contained in:
1 parent
a07def6042
commit
820b8cd26f
44 files changed
+422
-47
No files matched your search
@@ -0,0 +1,52 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { filterSchemaNamesForConnection, filterSchemaNamesForVisiblePicker, isSystemSchemaName } from "@/lib/database/visibleDatabases";
|
||||
|
||||
describe("visibleDatabases schema filtering", () => {
|
||||
it("hides common Kingbase system schemas by default", () => {
|
||||
expect(filterSchemaNamesForVisiblePicker(["anon", "dbms_job", "information_schema", "pg_catalog", "public", "sys", "sys_catalog", "wmsys", "xlog_record_read"], { db_type: "kingbase", username: "test" })).toEqual(["public"]);
|
||||
});
|
||||
|
||||
it("keeps the current schema visible even when it matches a system schema name", () => {
|
||||
expect(
|
||||
filterSchemaNamesForVisiblePicker(["public", "sys", "sys_catalog"], {
|
||||
db_type: "kingbase",
|
||||
username: "sys",
|
||||
}),
|
||||
).toEqual(["public", "sys"]);
|
||||
});
|
||||
|
||||
it("keeps Oracle DIP visible while hiding default system schemas", () => {
|
||||
expect(filterSchemaNamesForConnection(["DBX_TEST", "DIP", "SYSTEM"], { db_type: "oracle", database: "XE" }, "XE")).toEqual(["DBX_TEST", "DIP"]);
|
||||
});
|
||||
|
||||
it("keeps the Dameng login schema visible while hiding default system schemas", () => {
|
||||
expect(filterSchemaNamesForConnection(["APP", "SYS", "SYSDBA", "SYSDBO", "SYSAUDITOR"], { db_type: "dameng", username: "SYSDBA" }, "")).toEqual(["APP", "SYSDBA"]);
|
||||
});
|
||||
|
||||
it("hides openGauss system schemas and prefixes while keeping user schemas", () => {
|
||||
expect(filterSchemaNamesForVisiblePicker(["blockchain", "cstore", "db4ai", "dbe_perf", "dbe_pldeveloper", "dbe_sql_util", "information_schema", "pg_catalog", "public", "snapshot", "sqladvisor", "xmltype"], { db_type: "opengauss", username: "app_user" })).toEqual(["public"]);
|
||||
});
|
||||
|
||||
it("keeps all schemas visible when show-system-schemas is enabled", () => {
|
||||
expect(filterSchemaNamesForConnection(["blockchain", "db4ai", "public", "test2", "xmltype"], { db_type: "opengauss", show_system_schemas: true }, "postgres")).toEqual(["blockchain", "db4ai", "public", "test2", "xmltype"]);
|
||||
});
|
||||
|
||||
it("respects explicit visible schema configuration after default filtering", () => {
|
||||
expect(
|
||||
filterSchemaNamesForConnection(
|
||||
["public", "sys_catalog", "reporting"],
|
||||
{
|
||||
db_type: "kingbase",
|
||||
visible_schemas: { test: ["sys_catalog"] },
|
||||
},
|
||||
"test",
|
||||
),
|
||||
).toEqual(["sys_catalog"]);
|
||||
});
|
||||
|
||||
it("matches prefix-based system schema rules", () => {
|
||||
expect(isSystemSchemaName("kingbase", "xlog_record_read")).toBe(true);
|
||||
expect(isSystemSchemaName("opengauss", "dbe_pldeveloper")).toBe(true);
|
||||
expect(isSystemSchemaName("kingbase", "public")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,18 @@
|
||||
import type { ConnectionConfig, DatabaseType } from "@/types/database";
|
||||
|
||||
type SystemNameRules = {
|
||||
exact?: ReadonlySet<string>;
|
||||
prefixes?: readonly string[];
|
||||
};
|
||||
|
||||
type SchemaFilterOptions = {
|
||||
showSystemSchemas?: boolean;
|
||||
};
|
||||
|
||||
function schemaFilterShowSystemSchemas(connection: Partial<Pick<ConnectionConfig, "show_system_schemas">> | undefined, options?: SchemaFilterOptions): boolean {
|
||||
return options?.showSystemSchemas ?? connection?.show_system_schemas === true;
|
||||
}
|
||||
|
||||
const SYSTEM_DATABASE_RULES: Partial<Record<DatabaseType, ReadonlySet<string>>> = {
|
||||
mysql: new Set(["information_schema", "mysql", "performance_schema", "sys"]),
|
||||
doris: new Set(["information_schema", "mysql", "performance_schema", "sys"]),
|
||||
@@ -59,6 +72,67 @@ const SYSTEM_DATABASE_RULES: Partial<Record<DatabaseType, ReadonlySet<string>>>
|
||||
snowflake: new Set(["snowflake", "snowflake_sample_data"]),
|
||||
};
|
||||
|
||||
const POSTGRES_LIKE_SYSTEM_SCHEMA_RULES: SystemNameRules = {
|
||||
exact: new Set(["information_schema", "pg_catalog", "pg_toast"]),
|
||||
prefixes: ["pg_temp_", "pg_toast_temp_"],
|
||||
};
|
||||
|
||||
const SYSTEM_SCHEMA_RULES: Partial<Record<DatabaseType, SystemNameRules>> = {
|
||||
oracle: {
|
||||
exact: new Set([
|
||||
"anonymous",
|
||||
"appqossys",
|
||||
"audsys",
|
||||
"ctxsys",
|
||||
"dbsnmp",
|
||||
"dvf",
|
||||
"dvsys",
|
||||
"exfsys",
|
||||
"flows_files",
|
||||
"gsmadmin_internal",
|
||||
"mddata",
|
||||
"mdsys",
|
||||
"mgmt_view",
|
||||
"olapsys",
|
||||
"orddata",
|
||||
"ordplugins",
|
||||
"ordsys",
|
||||
"outln",
|
||||
"owbsys",
|
||||
"remote_scheduler_agent",
|
||||
"si_informtn_schema",
|
||||
"sys",
|
||||
"sysback",
|
||||
"sysdg",
|
||||
"syskm",
|
||||
"system",
|
||||
"wmsys",
|
||||
"xdb",
|
||||
"xs$null",
|
||||
]),
|
||||
},
|
||||
dameng: {
|
||||
exact: new Set(["_sys_statistics", "ctisys", "dba", "sys", "sys_dba", "sys_phm", "sysauditor", "sysdba", "sysdbo", "syssso", "system"]),
|
||||
},
|
||||
postgres: POSTGRES_LIKE_SYSTEM_SCHEMA_RULES,
|
||||
gaussdb: {
|
||||
exact: new Set(["blockchain", "coverage", "cstore", "db4ai", "dbe_perf", "dbe_pldebugger", "dbe_pldeveloper", "dbe_sql_util", "information_schema", "pg_catalog", "pg_toast", "pkg_service", "snapshot", "sqladvisor", "xmltype"]),
|
||||
prefixes: ["pg_temp_", "pg_toast_temp_", "dbe_"],
|
||||
},
|
||||
kwdb: POSTGRES_LIKE_SYSTEM_SCHEMA_RULES,
|
||||
opengauss: {
|
||||
exact: new Set(["blockchain", "coverage", "cstore", "db4ai", "dbe_perf", "dbe_pldebugger", "dbe_pldeveloper", "dbe_sql_util", "information_schema", "pg_catalog", "pg_toast", "pkg_service", "snapshot", "sqladvisor", "xmltype"]),
|
||||
prefixes: ["pg_temp_", "pg_toast_temp_", "dbe_"],
|
||||
},
|
||||
questdb: POSTGRES_LIKE_SYSTEM_SCHEMA_RULES,
|
||||
kingbase: {
|
||||
exact: new Set(["anon", "dbms_job", "dbms_scheduler", "dbms_sql", "information_schema", "kdb_schedule", "perf", "pg_bitmapindex", "pg_catalog", "pg_toast", "src_restrict", "sys", "sys_catalog", "sys_hm", "sysaudit", "sysmac", "wmsys"]),
|
||||
prefixes: ["dbms_", "pg_temp_", "pg_toast_temp_", "sys_temp_", "sys_toast_temp_", "xlog_"],
|
||||
},
|
||||
highgo: POSTGRES_LIKE_SYSTEM_SCHEMA_RULES,
|
||||
vastbase: POSTGRES_LIKE_SYSTEM_SCHEMA_RULES,
|
||||
};
|
||||
|
||||
export function visibleDatabaseFilterIsEnabled(visibleDatabases: string[] | undefined): boolean {
|
||||
return Array.isArray(visibleDatabases);
|
||||
}
|
||||
@@ -88,6 +162,15 @@ export function isSystemDatabaseName(databaseType: DatabaseType | undefined, dat
|
||||
return SYSTEM_DATABASE_RULES[databaseType]?.has(databaseName.toLowerCase()) ?? false;
|
||||
}
|
||||
|
||||
export function isSystemSchemaName(databaseType: DatabaseType | undefined, schemaName: string): boolean {
|
||||
if (!databaseType) return false;
|
||||
const normalized = schemaName.toLowerCase();
|
||||
const rules = SYSTEM_SCHEMA_RULES[databaseType];
|
||||
if (!rules) return false;
|
||||
if (rules.exact?.has(normalized)) return true;
|
||||
return rules.prefixes?.some((prefix) => normalized.startsWith(prefix)) ?? false;
|
||||
}
|
||||
|
||||
export function filterDatabaseNamesForConnection(databaseNames: string[], connection: Pick<ConnectionConfig, "db_type" | "driver_profile" | "visible_databases"> | undefined): string[] {
|
||||
const visibleDatabases = connection?.visible_databases;
|
||||
if (visibleDatabaseFilterIsEnabled(visibleDatabases)) {
|
||||
@@ -103,9 +186,10 @@ export function filterDatabaseNamesForVisiblePicker(databaseNames: string[], con
|
||||
return databaseNames.filter((name) => !isSystemDatabaseName(connection?.db_type, name));
|
||||
}
|
||||
|
||||
export function filterSchemaNamesForVisiblePicker(schemaNames: string[], connection: Partial<Pick<ConnectionConfig, "db_type" | "username">> | undefined): string[] {
|
||||
export function filterSchemaNamesForVisiblePicker(schemaNames: string[], connection: Partial<Pick<ConnectionConfig, "db_type" | "username" | "show_system_schemas">> | undefined, options?: SchemaFilterOptions): string[] {
|
||||
if (schemaFilterShowSystemSchemas(connection, options)) return schemaNames;
|
||||
const currentSchema = connection?.username?.trim().toLowerCase();
|
||||
return schemaNames.filter((name) => name.toLowerCase() === currentSchema || !isSystemDatabaseName(connection?.db_type, name));
|
||||
return schemaNames.filter((name) => name.toLowerCase() === currentSchema || !isSystemSchemaName(connection?.db_type, name));
|
||||
}
|
||||
|
||||
export function connectionUsesVisibleSchemaFilter(connection: Pick<ConnectionConfig, "db_type"> | undefined): boolean {
|
||||
@@ -116,13 +200,18 @@ export function visibleSchemaFilterIsEnabled(visibleSchemas: Record<string, stri
|
||||
return Array.isArray(visibleSchemas?.[database]);
|
||||
}
|
||||
|
||||
export function filterSchemaNamesForConnection(schemaNames: string[], connection: (Pick<ConnectionConfig, "db_type" | "visible_schemas" | "visible_databases"> & Partial<Pick<ConnectionConfig, "username">>) | undefined, database: string): string[] {
|
||||
export function filterSchemaNamesForConnection(
|
||||
schemaNames: string[],
|
||||
connection: (Pick<ConnectionConfig, "db_type" | "visible_schemas" | "visible_databases" | "show_system_schemas"> & Partial<Pick<ConnectionConfig, "username">>) | undefined,
|
||||
database: string,
|
||||
options?: SchemaFilterOptions,
|
||||
): string[] {
|
||||
const visibleSchemas = connection?.visible_schemas;
|
||||
if (!visibleSchemaFilterIsEnabled(visibleSchemas, database)) {
|
||||
if (connectionUsesVisibleSchemaFilter(connection) && visibleDatabaseFilterIsEnabled(connection?.visible_databases)) {
|
||||
return filterVisibleDatabaseNames(schemaNames, connection?.visible_databases);
|
||||
}
|
||||
return filterSchemaNamesForVisiblePicker(schemaNames, connection);
|
||||
return filterSchemaNamesForVisiblePicker(schemaNames, connection, options);
|
||||
}
|
||||
const visible = new Set(visibleSchemas![database]);
|
||||
return schemaNames.filter((name) => visible.has(name));
|
||||
|
||||
Reference in new issue
Block a user