diff --git a/agents/drivers/dameng/src/main/java/com/dbx/agent/dameng/DamengAgent.java b/agents/drivers/dameng/src/main/java/com/dbx/agent/dameng/DamengAgent.java index 4e4d2538a8..ed16f956ba 100644 --- a/agents/drivers/dameng/src/main/java/com/dbx/agent/dameng/DamengAgent.java +++ b/agents/drivers/dameng/src/main/java/com/dbx/agent/dameng/DamengAgent.java @@ -744,6 +744,9 @@ public final class DamengAgent extends AbstractJdbcAgent { if (errorCode == -3325 || errorCode == -2207) { return true; } + if (isDamengPermissionError(candidate)) { + return true; + } String message = candidate.getMessage(); if (message == null) { continue; @@ -786,6 +789,27 @@ public final class DamengAgent extends AbstractJdbcAgent { return false; } + /** + * 达梦中文环境在无权限时只返回「权限不足」(vendorCode -5669),消息里不带对象名, + * 无法通过 {@link #isDamengMetadataUnavailableError} 的对象名匹配识别。 + * 这类错误同样应按「元数据不可用」处理:走字典视图降级,而不是让查看对象直接报错。 + */ + private static boolean isDamengPermissionError(SQLException error) { + if (error.getErrorCode() == -5669) { + return true; + } + String message = error.getMessage(); + if (message == null) { + return false; + } + String normalized = message.toLowerCase(Locale.ROOT); + return normalized.contains("权限") + || normalized.contains("privilege") + || normalized.contains("permission") + || normalized.contains("access denied") + || normalized.contains("not authorized"); + } + /** 连接类错误(断连/超时等)不属于元数据不可用,必须继续上抛。 */ private static boolean isDamengConnectionError(Throwable error) { for (Throwable current = error; current != null; current = current.getCause()) { diff --git a/agents/drivers/dameng/src/test/java/com/dbx/agent/dameng/DamengAgentMetadataTest.java b/agents/drivers/dameng/src/test/java/com/dbx/agent/dameng/DamengAgentMetadataTest.java index f46aaad394..50b4ed6b24 100644 --- a/agents/drivers/dameng/src/test/java/com/dbx/agent/dameng/DamengAgentMetadataTest.java +++ b/agents/drivers/dameng/src/test/java/com/dbx/agent/dameng/DamengAgentMetadataTest.java @@ -1159,6 +1159,37 @@ class DamengAgentMetadataTest { Assertions.assertTrue(source.getSource().contains("系统字典视图"), source.getSource()); } + @Test + void fallsBackToTriggerCatalogWhenDbmsMetadataPermissionDenied() { + DamengAgent agent = new DamengAgent(); + List sqls = new ArrayList<>(); + TestSupport.setPrivateConnection(agent, proxy(Connection.class, (method, args) -> { + if ("prepareStatement".equals(method.getName())) { + String sql = (String) args[0]; + sqls.add(sql); + if (sql.contains("DBMS_METADATA.GET_DDL")) { + return failingMetadataStatement(new SQLException("权限不足", "28000", -5669)); + } + if (sql.contains("ALL_TRIGGERS")) { + return metadataStatement(List.of(List.of("BEGIN NULL; END;"))); + } + } + if ("close".equals(method.getName())) { + return null; + } + if ("isClosed".equals(method.getName())) { + return false; + } + return defaultValue(method.getReturnType()); + })); + + ObjectSource source = agent.getObjectSource("APP", "TRG_AUDIT", "TRIGGER"); + + Assertions.assertTrue(source.getSource().contains("BEGIN NULL; END;"), source.getSource()); + Assertions.assertTrue(source.getSource().contains("系统字典视图"), source.getSource()); + Assertions.assertTrue(sqls.stream().anyMatch(sql -> sql.contains("ALL_TRIGGERS")), String.join("\n", sqls)); + } + @Test void tableDdlFallsBackToViewAndMaterializedViewCatalogDefinitions() { DamengAgent agent = new DamengAgent();