fix(hana): show tables under schemas

This commit is contained in:
gggaiitx authored and GitHub committed 2026-07-24 10:02:27 +08:00
1 parent 562edef4dc
commit b121240b2f
3 files changed
+140 -9

No files matched your search

@@ -123,12 +123,12 @@ public final class StandardJdbcMetadata {
listObjects(listTables(conn, profile, configuredDatabase, schema, tableConstraints), schema)
);
DatabaseMetaData meta = conn.getMetaData();
appendRoutines(result, meta, null, blankToNull(schema), schema);
appendRoutines(result, meta, null, schema, schema);
if (!containsRoutine(result)
&& profile.getCatalogFallbackEnabled()
&& configuredDatabase != null
&& !configuredDatabase.trim().isEmpty()) {
appendRoutines(result, meta, configuredDatabase, blankToNull(schema), schema);
appendRoutines(result, meta, configuredDatabase, schema, schema);
}
result.sort(Comparator.comparing(ObjectInfo::getName));
return normalized.filterObjects(result);
@@ -332,7 +332,9 @@ public final class StandardJdbcMetadata {
return;
}
// JDBC has no portable metadata limit/offset. Use table types for safe pushdown and filter/page locally.
try (ResultSet rs = meta.getTables(catalog, blankToNull(schema), "%", tableTypes)) {
// schema 是 DatabaseMetaData.getTables() 的 schemaPattern,_ 和 % 具有通配符语义;
// HANA 存在 _SYS_RT 等含下划线的 schema,需按 getSearchStringEscape() 转义,避免混入其他 schema 的对象。
try (ResultSet rs = meta.getTables(catalog, escapeSchemaPattern(meta, schema), "%", tableTypes)) {
while (rs.next()) {
result.add(new TableInfo(
rs.getString("TABLE_NAME"),
@@ -618,16 +620,18 @@ public final class StandardJdbcMetadata {
List<ObjectInfo> result,
DatabaseMetaData meta,
String catalog,
String schemaPattern,
String schema
String schema,
String schemaLabel
) {
// schema 作为 getProcedures/getFunctions 的 schemaPattern,同样需要转义 _ 和 % 通配符。
String schemaPattern = escapeSchemaPattern(meta, schema);
Set<String> procedureNames = new LinkedHashSet<>();
try (ResultSet rs = meta.getProcedures(catalog, schemaPattern, "%")) {
while (rs.next()) {
String name = rs.getString("PROCEDURE_NAME");
if (name != null && !name.trim().isEmpty()) {
procedureNames.add(name);
result.add(new ObjectInfo(name, "PROCEDURE", schema, rs.getString("REMARKS")));
result.add(new ObjectInfo(name, "PROCEDURE", schemaLabel, rs.getString("REMARKS")));
}
}
} catch (Exception | AbstractMethodError ignored) {
@@ -637,7 +641,7 @@ public final class StandardJdbcMetadata {
while (rs.next()) {
String name = rs.getString("FUNCTION_NAME");
if (name != null && !name.trim().isEmpty() && !procedureNames.contains(name)) {
result.add(new ObjectInfo(name, "FUNCTION", schema, rs.getString("REMARKS")));
result.add(new ObjectInfo(name, "FUNCTION", schemaLabel, rs.getString("REMARKS")));
}
}
} catch (Exception | AbstractMethodError ignored) {
@@ -676,6 +680,38 @@ public final class StandardJdbcMetadata {
return value == null || value.trim().isEmpty() ? null : value;
}
/**
* 将 schema 名转义为可安全用作 {@link DatabaseMetaData#getTables(String, String, String, String[])}
* 等 schemaPattern 参数的形式。
*
* <p>JDBC 的 schemaPattern 把 {@code _}(匹配任意单字符)和 {@code %}(匹配任意字符序列)当作通配符。
* 当 schema 名本身含有这些字符时(例如 HANA 的 {@code _SYS_RT}、{@code _SYS_BIC},或被引号引用的含
* {@code %} 的 schema),直接作为 schemaPattern 传入会误匹配到其他 schema 的对象。参考 DBeaver 的
* {@code JDBCUtils.escapeWildCards()},按 {@link DatabaseMetaData#getSearchStringEscape()} 对通配符做转义。
*
* <p>当 schema 为空白(将映射为 {@code null},表示不做 schema 过滤)或驱动未提供转义字符时,原样返回。
*/
private static String escapeSchemaPattern(DatabaseMetaData meta, String schema) {
String normalized = blankToNull(schema);
if (normalized == null) {
return null;
}
String escape;
try {
escape = meta.getSearchStringEscape();
} catch (Exception ignored) {
escape = null;
}
if (escape == null || escape.isEmpty()) {
return normalized;
}
// 先转义 escape 自身,再转义 % 和 _,顺序与 PreparedStatement.setEscapeProcessing / DBeaver 一致。
String escapedEscape = normalized.replace(escape, escape + escape);
String escapedPercent = escapedEscape.replace("%", escape + "%");
String escapedUnderscore = escapedPercent.replace("_", escape + "_");
return escapedUnderscore;
}
private static void addNonBlank(Set<String> values, String value) {
if (value != null && !value.trim().isEmpty()) {
values.add(value);