fix(sidebar): honor schema filter for single-db picker key

OceanBase Oracle (and other single-database) connections persist their
schema checkbox filter under the empty database key, but the editor
toolbar schema picker addresses the bucket with the "_" single-db
sentinel, so the strict filter never applied and unchecked schemas
still appeared (#8145). Normalize the sentinel before the lookup.

Also keep the login schema visible for user@tenant usernames: the
OceanBase login embeds the tenant in the username, so the bare-name
comparison hid SYS from sys@tenant sessions even though the user's own
schema should always stay selectable.

Closes #8145
This commit is contained in:
t8y2 committed 2026-09-05 19:21:21 +08:00
1 parent 0b9ddff19c
commit 8598416998
2 files changed
+44 -3

No files matched your search

@@ -55,6 +55,35 @@ describe("visibleDatabases schema filtering", () => {
).toEqual(["sys_catalog"]);
});
it("applies the schema filter stored under the empty key to the single-db sentinel", () => {
const connection = {
db_type: "oceanbase-oracle" as const,
username: "sys@obtest",
visible_schemas: { "": ["APP", "SYS"] },
};
expect(filterSchemaNamesForConnection(["APP", "SYS", "MDSYS", "REPORT"], connection, "_")).toEqual(["APP", "SYS"]);
});
it("hides schemas unchecked in the filter when addressed via the sentinel key", () => {
const connection = {
db_type: "oceanbase-oracle" as const,
username: "sys@obtest",
visible_schemas: { "": ["APP"] },
};
expect(filterSchemaNamesForConnection(["APP", "SYS", "REPORT"], connection, "_")).toEqual(["APP"]);
});
it("keeps the login schema visible for user@tenant usernames", () => {
expect(
filterSchemaNamesForVisiblePicker(["APP", "MDSYS", "SYS", "SYSTEM"], {
db_type: "oceanbase-oracle",
username: "sys@obtest",
}),
).toEqual(["APP", "SYS"]);
});
it("matches prefix-based system schema rules", () => {
expect(isSystemSchemaName("kingbase", "xlog_record_read")).toBe(true);
expect(isSystemSchemaName("opengauss", "dbe_pldeveloper")).toBe(true);
@@ -247,8 +247,15 @@ export function filterDatabaseNamesForVisiblePicker(databaseNames: string[], con
export function filterSchemaNamesForVisiblePicker(schemaNames: string[], connection: VisibleDatabaseConnection | undefined, options?: SchemaFilterOptions): string[] {
if (schemaFilterShowSystemSchemas(connection, options)) return schemaNames;
const currentSchema = connection?.username?.trim().toLowerCase();
// OceanBase Oracle logins embed the tenant in the username ("user@tenant");
// the schema equals the user part, so keep the login schema visible in both
// forms instead of hiding it behind a system-schema name (#8145).
const currentUserPart = currentSchema?.split("@")[0];
const databaseType = effectiveDatabaseTypeForConnection(connection);
return schemaNames.filter((name) => name.toLowerCase() === currentSchema || !isSystemSchemaName(databaseType, name));
return schemaNames.filter((name) => {
const normalized = name.toLowerCase();
return normalized === currentSchema || normalized === currentUserPart || !isSystemSchemaName(databaseType, name);
});
}
export function connectionUsesVisibleSchemaFilter(connection: VisibleDatabaseConnection | undefined): boolean {
@@ -261,7 +268,12 @@ export function visibleSchemaFilterIsEnabled(visibleSchemas: Record<string, stri
export function filterSchemaNamesForConnection(schemaNames: string[], connection: VisibleDatabaseConnection | undefined, database: string, options?: SchemaFilterOptions): string[] {
const visibleSchemas = connection?.visible_schemas;
if (!visibleSchemaFilterIsEnabled(visibleSchemas, database)) {
// Single-database connections persist their schema filter under the empty
// database key while the editor toolbar addresses the same bucket with its
// "_" single-db sentinel; normalize so the strict checkbox filter still
// applies to the schema picker (#8145).
const filterDatabase = database === "_" ? "" : database;
if (!visibleSchemaFilterIsEnabled(visibleSchemas, filterDatabase)) {
const visibleDatabases = connection?.visible_databases;
const visibleDatabasePatterns = connection?.visible_database_patterns;
if (connectionUsesVisibleSchemaFilter(connection) && (visibleDatabaseFilterIsEnabled(visibleDatabases) || visibleDatabasePatternsAreEnabled(visibleDatabasePatterns))) {
@@ -269,7 +281,7 @@ export function filterSchemaNamesForConnection(schemaNames: string[], connection
}
return filterSchemaNamesForVisiblePicker(schemaNames, connection, options);
}
const visible = new Set(visibleSchemas![database]);
const visible = new Set(visibleSchemas![filterDatabase]);
return schemaNames.filter((name) => visible.has(name));
}