mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
fix(oceanbase): restore Oracle-mode system schema visibility
Closes #6508
This commit is contained in:
+1
-9
@@ -31,7 +31,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class OceanBaseOracleAgent extends ConfiguredJdbcAgent {
|
||||
private static final long MICROS_PER_SECOND = 1_000_000L;
|
||||
@@ -721,23 +720,16 @@ public final class OceanBaseOracleAgent extends ConfiguredJdbcAgent {
|
||||
}
|
||||
|
||||
private List<String> querySchemaNames() throws SQLException {
|
||||
String placeholders = SYSTEM_SCHEMAS.stream()
|
||||
.map(schema -> "'" + schema + "'")
|
||||
.collect(Collectors.joining(","));
|
||||
String sql = """
|
||||
SELECT username
|
||||
FROM ALL_USERS
|
||||
WHERE username IS NOT NULL
|
||||
AND username NOT IN (%s)
|
||||
AND username NOT LIKE 'APEX_%%'
|
||||
AND username NOT LIKE 'FLOWS_%%'
|
||||
AND username NOT LIKE '%%$%%'
|
||||
ORDER BY CASE
|
||||
WHEN username = SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') THEN 0
|
||||
WHEN username = SYS_CONTEXT('USERENV', 'SESSION_USER') THEN 1
|
||||
ELSE 2
|
||||
END, username
|
||||
""".formatted(placeholders).stripIndent().trim();
|
||||
""".stripIndent().trim();
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
try (var stmt = requireConnection().createStatement();
|
||||
|
||||
+53
@@ -27,6 +27,7 @@ import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
class OceanBaseOracleAgentTest {
|
||||
@Test
|
||||
@@ -70,6 +71,36 @@ class OceanBaseOracleAgentTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void schemaListingReturnsEveryNonBlankUserWithoutHardSystemExclusions() {
|
||||
List<String> sql = new ArrayList<>();
|
||||
OceanBaseOracleAgent agent = new OceanBaseOracleAgent();
|
||||
TestSupport.setPrivateConnection(agent, schemaConnection(sql, resultSet(
|
||||
new String[]{"USERNAME"},
|
||||
new Object[][]{
|
||||
{"SYS"},
|
||||
{null},
|
||||
{" "},
|
||||
{"APEX_240100"},
|
||||
{"APP$USER"},
|
||||
{"REPORTING"}
|
||||
}
|
||||
)));
|
||||
|
||||
Assertions.assertEquals(
|
||||
List.of("SYS", "APEX_240100", "APP$USER", "REPORTING"),
|
||||
agent.listSchemas()
|
||||
);
|
||||
String schemaSql = sql.get(0).toUpperCase(Locale.ROOT);
|
||||
Assertions.assertTrue(schemaSql.contains("FROM ALL_USERS"), schemaSql);
|
||||
Assertions.assertTrue(schemaSql.contains("USERNAME IS NOT NULL"), schemaSql);
|
||||
Assertions.assertFalse(schemaSql.contains("NOT IN"), schemaSql);
|
||||
Assertions.assertFalse(schemaSql.contains("USERNAME NOT LIKE"), schemaSql);
|
||||
Assertions.assertTrue(schemaSql.contains("CURRENT_SCHEMA') THEN 0"), schemaSql);
|
||||
Assertions.assertTrue(schemaSql.contains("SESSION_USER') THEN 1"), schemaSql);
|
||||
Assertions.assertTrue(schemaSql.endsWith("ELSE 2\nEND, USERNAME"), schemaSql);
|
||||
}
|
||||
|
||||
@Test
|
||||
void appendsCompatibleOjdbcVersionToCustomJdbcUrl() {
|
||||
ConnectParams params = new ConnectParams();
|
||||
@@ -443,6 +474,28 @@ class OceanBaseOracleAgentTest {
|
||||
});
|
||||
}
|
||||
|
||||
private static Connection schemaConnection(List<String> sql, ResultSet resultSet) {
|
||||
Statement statement = proxy(Statement.class, (method, args) -> {
|
||||
if ("executeQuery".equals(method.getName())) {
|
||||
sql.add(String.valueOf(args[0]));
|
||||
return resultSet;
|
||||
}
|
||||
if ("close".equals(method.getName())) {
|
||||
return null;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
});
|
||||
return proxy(Connection.class, (method, args) -> {
|
||||
if ("createStatement".equals(method.getName())) {
|
||||
return statement;
|
||||
}
|
||||
if ("isClosed".equals(method.getName())) {
|
||||
return false;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
});
|
||||
}
|
||||
|
||||
private static Connection objectSourceConnection(List<String> sql, List<String> params, ResultSet resultSet) {
|
||||
PreparedStatement statement = objectSourceStatement(params, resultSet, false);
|
||||
return proxy(Connection.class, (method, args) -> {
|
||||
|
||||
@@ -6,6 +6,7 @@ type VisibleDatabaseConnection = Partial<ConnectionConfig>;
|
||||
type SystemNameRules = {
|
||||
exact?: ReadonlySet<string>;
|
||||
prefixes?: readonly string[];
|
||||
contains?: readonly string[];
|
||||
};
|
||||
|
||||
type SchemaFilterOptions = {
|
||||
@@ -80,39 +81,48 @@ const POSTGRES_LIKE_SYSTEM_SCHEMA_RULES: SystemNameRules = {
|
||||
prefixes: ["pg_temp_", "pg_toast_temp_"],
|
||||
};
|
||||
|
||||
const ORACLE_SYSTEM_SCHEMA_NAMES = 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",
|
||||
]);
|
||||
|
||||
const OCEANBASE_ORACLE_SYSTEM_SCHEMA_NAMES = new Set([...ORACLE_SYSTEM_SCHEMA_NAMES, "apex_public_user", "dbsfwuser", "dgpdb_int", "dip", "ggsys", "gsmcatuser", "gsmrootuser", "gsmuser", "lbacsys", "ojvmsys", "ops$oracle", "oracle_ocm", "pdbadmin", "sysbackup", "sysman", "sysrac"]);
|
||||
|
||||
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",
|
||||
]),
|
||||
exact: ORACLE_SYSTEM_SCHEMA_NAMES,
|
||||
},
|
||||
"oceanbase-oracle": {
|
||||
exact: OCEANBASE_ORACLE_SYSTEM_SCHEMA_NAMES,
|
||||
prefixes: ["apex_", "flows_"],
|
||||
contains: ["$"],
|
||||
},
|
||||
dameng: {
|
||||
exact: new Set(["_sys_statistics", "ctisys", "dba", "sys", "sys_dba", "sys_phm", "sysauditor", "sysdba", "sysdbo", "syssso", "system"]),
|
||||
@@ -171,7 +181,8 @@ export function isSystemSchemaName(databaseType: DatabaseType | undefined, schem
|
||||
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;
|
||||
if (rules.prefixes?.some((prefix) => normalized.startsWith(prefix))) return true;
|
||||
return rules.contains?.some((part) => normalized.includes(part)) ?? false;
|
||||
}
|
||||
|
||||
export function filterDatabaseNamesForConnection(databaseNames: string[], connection: VisibleDatabaseConnection | undefined): string[] {
|
||||
|
||||
@@ -100,6 +100,15 @@ test("OceanBase Oracle uses schema filtering for visible object selection", () =
|
||||
assert.equal(connectionUsesVisibleSchemaFilter(config({ db_type: "mysql", driver_profile: "oceanbase" })), false);
|
||||
});
|
||||
|
||||
test("OceanBase Oracle applies Oracle system schema visibility rules", () => {
|
||||
const schemas = ["APP", "SYS", "SYSTEM", "APEX_240100", "FLOWS_240100", "APP$USER"];
|
||||
|
||||
assert.deepEqual(filterSchemaNamesForVisiblePicker(schemas, config({ db_type: "oceanbase-oracle", username: "APP" })), ["APP"]);
|
||||
assert.deepEqual(filterSchemaNamesForVisiblePicker(schemas, config({ db_type: "oceanbase-oracle", username: "SYS" })), ["APP", "SYS"]);
|
||||
assert.deepEqual(filterSchemaNamesForConnection(schemas, config({ db_type: "oceanbase-oracle", show_system_schemas: true }), ""), schemas);
|
||||
assert.deepEqual(filterSchemaNamesForConnection(schemas, config({ db_type: "oceanbase-oracle", visible_schemas: { "": ["SYS", "APEX_240100", "FLOWS_240100", "APP$USER"] } }), ""), ["SYS", "APEX_240100", "FLOWS_240100", "APP$USER"]);
|
||||
});
|
||||
|
||||
test("Oracle JDBC uses schema filtering for visible object selection", () => {
|
||||
const connection = config({
|
||||
db_type: "jdbc",
|
||||
|
||||
Reference in New Issue
Block a user