public Snapshot scan(String run, Target target, List entries) {
String targetSchema = schema(target);
try (Connection targetConnection = factory.open(targetSchema, target.alias())) {
List<ObjectInfo> objects = new ArrayList<>();
// Bulk query 1: errors for all invalid objects.
Map<String, List<String>> errorsByObject = new HashMap<>();
try (PreparedStatement s = targetConnection.prepareStatement(
"SELECT e.NAME, e.TYPE, e.LINE, e.POSITION, e.TEXT " +
"FROM USER_ERRORS e JOIN USER_OBJECTS o " +
"ON o.OBJECT_NAME = e.NAME AND o.OBJECT_TYPE = e.TYPE " +
"WHERE o.STATUS = 'INVALID' " +
"ORDER BY e.NAME, e.TYPE, e.SEQUENCE")) {
s.setQueryTimeout(20);
try (ResultSet r = s.executeQuery()) {
while (r.next()) {
String key = r.getString(1) + "\u0000" + r.getString(2);
errorsByObject
.computeIfAbsent(key, ignored -> new ArrayList<>())
.add("Line " + r.getInt(3) + ":" +
r.getInt(4) + " " + r.getString(5));
}
}
}
// Bulk query 2: dependencies for all invalid objects.
Map<String, List<String>> dependenciesByObject = new HashMap<>();
try (PreparedStatement s = targetConnection.prepareStatement(
"SELECT d.NAME, d.TYPE, d.REFERENCED_NAME " +
"FROM USER_DEPENDENCIES d JOIN USER_OBJECTS o " +
"ON o.OBJECT_NAME = d.NAME AND o.OBJECT_TYPE = d.TYPE " +
"WHERE o.STATUS = 'INVALID' " +
"AND d.REFERENCED_OWNER = USER " +
"ORDER BY d.NAME, d.TYPE, d.REFERENCED_NAME")) {
s.setQueryTimeout(20);
try (ResultSet r = s.executeQuery()) {
while (r.next()) {
String key = r.getString(1) + "\u0000" + r.getString(2);
dependenciesByObject
.computeIfAbsent(key, ignored -> new ArrayList<>())
.add(r.getString(3));
}
}
}
// Bulk query 3: all invalid object names and types.
try (PreparedStatement s = targetConnection.prepareStatement(
"SELECT OBJECT_NAME, OBJECT_TYPE FROM USER_OBJECTS " +
"WHERE STATUS = 'INVALID' " +
"ORDER BY OBJECT_TYPE, OBJECT_NAME")) {
s.setQueryTimeout(20);
try (ResultSet r = s.executeQuery()) {
while (r.next()) {
String name = r.getString(1);
String type = r.getString(2);
String key = name + "\u0000" + type;
objects.add(new ObjectInfo(
name,
type,
"INVALID",
errorsByObject.getOrDefault(key, List.of()),
dependenciesByObject.getOrDefault(key, List.of())
));
}
}
}
// Reuse one Oracle connection per execution schema.
Map<String, Connection> connections = new HashMap<>();
connections.put(targetSchema, targetConnection);
Set<String> satisfied = new HashSet<>();
try {
for (LibraryEntry entry : entries) {
String segment = entry.executionSegment().equals("CURRENT")
? target.segment()
: entry.executionSegment();
String executionSchema = names.build(
SchemaInputParser.parse(target.input()).base(),
segment
);
Connection checkConnection = connections.get(executionSchema);
if (checkConnection == null) {
checkConnection = factory.open(executionSchema, target.alias());
connections.put(executionSchema, checkConnection);
}
if (check(checkConnection, entry, target)) {
satisfied.add(entry.id());
}
}
} finally {
for (Connection connection : connections.values()) {
if (connection != targetConnection) {
try {
connection.close();
} catch (SQLException ignored) {
}
}
}
}
return new Snapshot(objects, satisfied);
} catch (SQLException e) {
throw databaseError(e);
}
}
Top comments (0)