fix(dameng): fall back for restricted schema objects

This commit is contained in:
t8y2 2026-08-01 12:34:52 +08:00
parent 313b1c4b2a
commit 6c41bb4da1
No known key found for this signature in database
2 changed files with 153 additions and 22 deletions

View File

@ -576,33 +576,66 @@ public final class DamengAgent extends AbstractJdbcAgent {
if (!includesSupportedObjectTypes(constraints)) {
return List.of();
}
RuntimeException permissionError;
try {
return executeConstrainedObjects(schema, buildConstrainedObjectsQuery(schema, constraints), constraints);
} catch (RuntimeException e) {
if (needsMaterializedViewClassification(constraints)) {
try {
return executeConstrainedObjects(
schema,
buildAccessibleConstrainedObjectsQuery(schema, constraints),
constraints
);
} catch (RuntimeException ignored) {
// Fall through to owner-local and raw catalog fallbacks.
}
if (!isDamengMetadataPermissionError(e)) {
throw e;
}
if (needsMaterializedViewClassification(constraints) && schemaMatchesConnectedUser(schema)) {
try {
return executeConstrainedObjects(
schema,
buildConstrainedObjectsQuery(schema, constraints, DAMENG_USER_MATERIALIZED_VIEW_JOIN_SQL),
constraints
);
} catch (RuntimeException ignored) {
// Fall through to the raw catalog path below.
}
}
return executeRawConstrainedObjects(schema, constraints);
permissionError = e;
}
if (needsMaterializedViewClassification(constraints)) {
try {
return executeConstrainedObjects(
schema,
buildAccessibleConstrainedObjectsQuery(schema, constraints),
constraints
);
} catch (RuntimeException e) {
if (!isDamengMetadataPermissionError(e)) {
throw e;
}
permissionError.addSuppressed(e);
}
}
if (needsMaterializedViewClassification(constraints) && schemaMatchesConnectedUser(schema)) {
try {
return executeConstrainedObjects(
schema,
buildConstrainedObjectsQuery(schema, constraints, DAMENG_USER_MATERIALIZED_VIEW_JOIN_SQL),
constraints
);
} catch (RuntimeException e) {
if (!isDamengMetadataPermissionError(e)) {
throw e;
}
permissionError.addSuppressed(e);
}
}
try {
return executeRawConstrainedObjects(schema, constraints);
} catch (RuntimeException e) {
if (!isDamengMetadataPermissionError(e)) {
throw e;
}
permissionError.addSuppressed(e);
}
try {
return executeJdbcMetadataObjects(schema, constraints);
} catch (RuntimeException e) {
e.addSuppressed(permissionError);
throw e;
}
}
private List<ObjectInfo> executeJdbcMetadataObjects(String schema, MetadataListConstraints constraints) {
if (!constraints.includesTableLikeTypes()) {
return List.of();
}
return executeJdbcMetadataTables(schema, constraints).stream()
.map(table -> new ObjectInfo(table.getName(), table.getTable_type(), schema, table.getComment()))
.toList();
}
private List<ObjectInfo> executeConstrainedObjects(

View File

@ -196,6 +196,104 @@ class DamengAgentMetadataTest {
Assertions.assertEquals("用户示例表", objects.get(0).getComment());
}
@Test
void fallsBackToJdbcMetadataForRestrictedSchemaObjects() {
DamengAgent agent = new DamengAgent();
List<String> sqls = new ArrayList<>();
List<String> jdbcMetadataCalls = new ArrayList<>();
TestSupport.setPrivateConnection(agent, restrictedTableConnection(
sqls,
jdbcMetadataCalls,
List.of(
List.of("VIEW_B", "VIEW", "view comment"),
List.of("TABLE_A", "TABLE", "table comment"),
List.of("MV_C", "MATERIALIZED VIEW", "mv comment"),
List.of("APP_PROC", "PROCEDURE", "procedure comment"),
List.of("MTAB$_INTERNAL", "TABLE", "internal table")
),
null,
"没有[SYS.ALL_OBJECTS]对象的查询权限"
));
setConnectedUsername(agent, "APP_DATA%2026");
List<ObjectInfo> objects = agent.listObjects("APP_DATA%2026");
Assertions.assertEquals(List.of("MV_C", "TABLE_A", "VIEW_B"), objects.stream().map(ObjectInfo::getName).toList());
Assertions.assertEquals(List.of("MATERIALIZED_VIEW", "TABLE", "VIEW"), objects.stream().map(ObjectInfo::getObject_type).toList());
Assertions.assertEquals(List.of("APP_DATA%2026", "APP_DATA%2026", "APP_DATA%2026"), objects.stream().map(ObjectInfo::getSchema).toList());
Assertions.assertEquals(List.of("mv comment", "table comment", "view comment"), objects.stream().map(ObjectInfo::getComment).toList());
Assertions.assertEquals(4, sqls.size(), String.join("\n", sqls));
Assertions.assertTrue(sqls.stream().allMatch(sql -> sql.contains("ALL_OBJECTS")), String.join("\n", sqls));
Assertions.assertEquals(List.of("catalog=null,schema=APP\\_DATA\\%2026,table=%,types=null"), jdbcMetadataCalls);
}
@Test
void appliesConstraintsToRestrictedSchemaObjectFallback() {
DamengAgent agent = new DamengAgent();
TestSupport.setPrivateConnection(agent, restrictedTableConnection(
new ArrayList<>(),
new ArrayList<>(),
List.of(
List.of("VIEW_B", "VIEW", "keep view"),
List.of("TABLE_A", "TABLE", "keep table"),
List.of("TABLE_Z", "TABLE", "other"),
List.of("MV_C", "MATERIALIZED VIEW", "keep materialized view")
),
null,
"no SYS.ALL_OBJECTS privilege"
));
MetadataListConstraints constraints = new MetadataListConstraints(
"keep",
1,
1,
List.of("TABLE", "VIEW")
);
List<ObjectInfo> objects = agent.listObjects("APP", constraints);
Assertions.assertEquals(1, objects.size());
Assertions.assertEquals("VIEW_B", objects.get(0).getName());
Assertions.assertEquals("VIEW", objects.get(0).getObject_type());
Assertions.assertEquals("keep view", objects.get(0).getComment());
}
@Test
void doesNotFallbackForNonPermissionObjectMetadataErrors() {
DamengAgent agent = new DamengAgent();
List<String> sqls = new ArrayList<>();
List<String> jdbcMetadataCalls = new ArrayList<>();
TestSupport.setPrivateConnection(agent, restrictedTableConnection(
sqls,
jdbcMetadataCalls,
List.of(),
null,
"ALL_OBJECTS metadata query timed out"
));
RuntimeException error = Assertions.assertThrows(RuntimeException.class, () -> agent.listObjects("APP"));
Assertions.assertEquals("ALL_OBJECTS metadata query timed out", error.getCause().getMessage());
Assertions.assertEquals(1, sqls.size(), String.join("\n", sqls));
Assertions.assertTrue(jdbcMetadataCalls.isEmpty(), jdbcMetadataCalls.toString());
}
@Test
void propagatesJdbcMetadataObjectFallbackErrors() {
DamengAgent agent = new DamengAgent();
TestSupport.setPrivateConnection(agent, restrictedTableConnection(
new ArrayList<>(),
new ArrayList<>(),
List.of(),
new SQLException("JDBC metadata getTables failed"),
"没有[SYS.ALL_OBJECTS]对象的查询权限"
));
RuntimeException error = Assertions.assertThrows(RuntimeException.class, () -> agent.listObjects("APP"));
Assertions.assertEquals("JDBC metadata getTables failed", error.getCause().getMessage());
Assertions.assertEquals(1, error.getSuppressed().length);
}
@Test
void listSchemasIncludesSchemaObjectsWithoutChildren() {
DamengAgent agent = new DamengAgent();