in src/main/java/software/aws/neptune/gremlin/GremlinQueryExecutor.java [394:439]
protected <T> T runQuery(final String query) throws SQLException {
final Client client = getClient(gremlinConnectionProperties);
synchronized (completableFutureLock) {
completableFuture = client.submitAsync(query);
}
final List<Result> results = completableFuture.get().all().get();
final List<Map<String, Object>> rows = new ArrayList<>();
final Map<String, Class<?>> columns = new HashMap<>();
for (final Object result : results.stream().map(Result::getObject).collect(Collectors.toList())) {
if (!(result instanceof LinkedHashMap)) {
// Best way to handle it seems to be to issue a warning.
LOGGER.warn(String.format("Result of type '%s' is not convertible to a Map and will be skipped.",
result.getClass().getCanonicalName()));
continue;
}
// We don't know key or value types, so pull it out raw.
final Map<?, ?> uncastedRow = (LinkedHashMap<?, ?>) result;
// Convert generic key types to string and insert in new map with corresponding value.
final Map<String, Object> row = new HashMap<>();
uncastedRow.forEach((key, value) -> row.put(key.toString(), value));
// Add row to List of rows.
rows.add(row);
// Get columns from row and put in columns List if they aren't already in there.
for (final String key : row.keySet()) {
if (!columns.containsKey(key)) {
final Object value = row.get(key);
if (GremlinTypeMapping.checkContains(value.getClass())) {
columns.put(key, value.getClass());
} else {
columns.put(key, String.class);
}
} else if (columns.get(key) != row.get(key)) {
columns.put(key, String.class);
}
}
}
final List<String> listColumns = new ArrayList<>(columns.keySet());
return (T) new GremlinResultSet.ResultSetInfoWithRows(rows, columns, listColumns);
}