fix(jdbc): include routines in object metadata
This commit is contained in:
parent
5d5f7feb4a
commit
fda65621e2
|
|
@ -73,15 +73,24 @@ public abstract class ConfiguredJdbcAgent extends AbstractJdbcAgent {
|
|||
|
||||
@Override
|
||||
public List<ObjectInfo> listObjects(String schema) {
|
||||
return StandardJdbcMetadata.INSTANCE.listObjects(listTables(schema), schema);
|
||||
return StandardJdbcMetadata.INSTANCE.listObjects(
|
||||
requireConnection(),
|
||||
profile,
|
||||
configuredDatabase,
|
||||
schema,
|
||||
MetadataListConstraints.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ObjectInfo> listObjects(String schema, MetadataListConstraints constraints) {
|
||||
MetadataListConstraints normalized = MetadataListConstraints.orNone(constraints);
|
||||
MetadataListConstraints tableConstraints =
|
||||
new MetadataListConstraints(normalized.getFilter(), null, null, normalized.getObjectTypes());
|
||||
return StandardJdbcMetadata.INSTANCE.listObjects(listTables(schema, tableConstraints), schema, normalized);
|
||||
return StandardJdbcMetadata.INSTANCE.listObjects(
|
||||
requireConnection(),
|
||||
profile,
|
||||
configuredDatabase,
|
||||
schema,
|
||||
constraints
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -108,6 +108,33 @@ public final class StandardJdbcMetadata {
|
|||
return MetadataListConstraints.orNone(constraints).filterObjects(result);
|
||||
}
|
||||
|
||||
public List<ObjectInfo> listObjects(
|
||||
Connection conn,
|
||||
JdbcAgentProfile profile,
|
||||
String configuredDatabase,
|
||||
String schema,
|
||||
MetadataListConstraints constraints
|
||||
) {
|
||||
return unchecked(() -> {
|
||||
MetadataListConstraints normalized = MetadataListConstraints.orNone(constraints);
|
||||
MetadataListConstraints tableConstraints =
|
||||
new MetadataListConstraints(normalized.getFilter(), null, null, normalized.getObjectTypes());
|
||||
List<ObjectInfo> result = new ArrayList<>(
|
||||
listObjects(listTables(conn, profile, configuredDatabase, schema, tableConstraints), schema)
|
||||
);
|
||||
DatabaseMetaData meta = conn.getMetaData();
|
||||
appendRoutines(result, meta, null, blankToNull(schema), schema);
|
||||
if (!containsRoutine(result)
|
||||
&& profile.getCatalogFallbackEnabled()
|
||||
&& configuredDatabase != null
|
||||
&& !configuredDatabase.trim().isEmpty()) {
|
||||
appendRoutines(result, meta, configuredDatabase, blankToNull(schema), schema);
|
||||
}
|
||||
result.sort(Comparator.comparing(ObjectInfo::getName));
|
||||
return normalized.filterObjects(result);
|
||||
});
|
||||
}
|
||||
|
||||
public List<String> listDataTypes(Connection conn) {
|
||||
return unchecked(() -> {
|
||||
Set<String> seen = new LinkedHashSet<>();
|
||||
|
|
@ -587,6 +614,47 @@ public final class StandardJdbcMetadata {
|
|||
return type;
|
||||
}
|
||||
|
||||
private static void appendRoutines(
|
||||
List<ObjectInfo> result,
|
||||
DatabaseMetaData meta,
|
||||
String catalog,
|
||||
String schemaPattern,
|
||||
String 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")));
|
||||
}
|
||||
}
|
||||
} catch (Exception | AbstractMethodError ignored) {
|
||||
// Some JDBC drivers don't implement routine metadata.
|
||||
}
|
||||
try (ResultSet rs = meta.getFunctions(catalog, schemaPattern, "%")) {
|
||||
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")));
|
||||
}
|
||||
}
|
||||
} catch (Exception | AbstractMethodError ignored) {
|
||||
// Some JDBC drivers don't implement function metadata separately.
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean containsRoutine(List<ObjectInfo> objects) {
|
||||
for (ObjectInfo object : objects) {
|
||||
if ("PROCEDURE".equalsIgnoreCase(object.getObject_type())
|
||||
|| "FUNCTION".equalsIgnoreCase(object.getObject_type())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Integer intOrNull(ResultSet rs, String column) throws Exception {
|
||||
Object value = rs.getObject(column);
|
||||
return value instanceof Number ? ((Number) value).intValue() : null;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,30 @@ class StandardJdbcMetadataTest {
|
|||
assertEquals("TABLE", tables.get(1).getTable_type());
|
||||
}
|
||||
|
||||
@Test
|
||||
void listsProceduresAndFunctionsFromJdbcRoutineMetadata() {
|
||||
Connection conn = routineConnection(
|
||||
rows(
|
||||
row("PROCEDURE_NAME", "PROCESS_ORDER", "REMARKS", "processes an order"),
|
||||
row("PROCEDURE_NAME", "SHARED_ROUTINE", "REMARKS", null)
|
||||
),
|
||||
rows(
|
||||
row("FUNCTION_NAME", "CALCULATE_TOTAL", "REMARKS", "calculates a total"),
|
||||
row("FUNCTION_NAME", "SHARED_ROUTINE", "REMARKS", null)
|
||||
)
|
||||
);
|
||||
MetadataListConstraints constraints =
|
||||
new MetadataListConstraints(null, null, null, Collections.singletonList("PROCEDURE"));
|
||||
|
||||
List<ObjectInfo> objects = StandardJdbcMetadata.INSTANCE.listObjects(conn, profile, "", "APP", constraints);
|
||||
|
||||
assertEquals(2, objects.size());
|
||||
assertEquals("PROCESS_ORDER", objects.get(0).getName());
|
||||
assertEquals("PROCEDURE", objects.get(0).getObject_type());
|
||||
assertEquals("SHARED_ROUTINE", objects.get(1).getName());
|
||||
assertEquals("PROCEDURE", objects.get(1).getObject_type());
|
||||
}
|
||||
|
||||
@Test
|
||||
void listsDataTypesFromJdbcTypeInfo() {
|
||||
Connection conn = connection(
|
||||
|
|
@ -581,6 +605,34 @@ class StandardJdbcMetadataTest {
|
|||
});
|
||||
}
|
||||
|
||||
private static Connection routineConnection(ResultSet procedures, ResultSet functions) {
|
||||
DatabaseMetaData meta = proxy(DatabaseMetaData.class, new MethodHandler() {
|
||||
@Override
|
||||
public Object handle(Method method, Object[] args) {
|
||||
String name = method.getName();
|
||||
if ("getTables".equals(name) || "getTableTypes".equals(name)) {
|
||||
return rows();
|
||||
}
|
||||
if ("getProcedures".equals(name)) {
|
||||
return procedures;
|
||||
}
|
||||
if ("getFunctions".equals(name)) {
|
||||
return functions;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
}
|
||||
});
|
||||
return proxy(Connection.class, new MethodHandler() {
|
||||
@Override
|
||||
public Object handle(Method method, Object[] args) {
|
||||
if ("getMetaData".equals(method.getName())) {
|
||||
return meta;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ResultSet orderColumns() {
|
||||
return rows(row(
|
||||
"COLUMN_NAME", "ID",
|
||||
|
|
|
|||
Loading…
Reference in New Issue