in java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnection.java [149:301]
public ArrowReader getStatistics(
String catalogPattern, String dbSchemaPattern, String tableNamePattern, boolean approximate)
throws AdbcException {
if (tableNamePattern == null) {
throw AdbcException.notImplemented(
JdbcDriverUtil.prefixExceptionMessage("getStatistics: must supply table name"));
}
try (final VectorSchemaRoot root =
VectorSchemaRoot.create(StandardSchemas.GET_STATISTICS_SCHEMA, allocator);
ResultSet rs =
connection
.getMetaData()
.getIndexInfo(
catalogPattern,
dbSchemaPattern,
tableNamePattern, /*unique*/
false,
approximate)) {
// Build up the statistics in-memory and then return a constant reader.
// We have to read and sort the data first because the ordering is not by the catalog/etc.
// {catalog: {schema: {index_name: statistic}}}
Map<String, Map<String, Map<String, Statistic>>> allStatistics = new HashMap<>();
while (rs.next()) {
@Nullable String catalog = rs.getString(1);
String schema = rs.getString(2);
String table = rs.getString(3);
String index = rs.getString(6);
short statisticType = rs.getShort(7);
String column = rs.getString(9);
long cardinality = rs.getLong(11);
if (table == null || column == null) {
throw new AdbcException(
JdbcDriverUtil.prefixExceptionMessage("JDBC driver returned null table/column name"),
null,
AdbcStatusCode.INTERNAL,
null,
0);
}
if (!allStatistics.containsKey(catalog)) {
allStatistics.put(catalog, new HashMap<>());
}
Map<String, Map<String, Statistic>> catalogStats = allStatistics.get(catalog);
if (!catalogStats.containsKey(schema)) {
catalogStats.put(schema, new HashMap<>());
}
Map<String, Statistic> schemaStats = catalogStats.get(schema);
Statistic statistic = schemaStats.getOrDefault(index, new Statistic(table, column));
assert statistic != null; // for checker-framework
if (schemaStats.containsKey(index)) {
// Multi-column index, ignore it
statistic.multiColumn = true;
continue;
}
statistic.column = column;
statistic.table = table;
statistic.key =
statisticType == DatabaseMetaData.tableIndexStatistic
? StandardStatistics.ROW_COUNT.getKey()
: StandardStatistics.DISTINCT_COUNT.getKey();
statistic.value = cardinality;
schemaStats.put(index, statistic);
}
VarCharVector catalogNames = (VarCharVector) root.getVector(0);
ListVector catalogDbSchemas = (ListVector) root.getVector(1);
StructVector dbSchemas = (StructVector) catalogDbSchemas.getDataVector();
VarCharVector dbSchemaNames = (VarCharVector) dbSchemas.getVectorById(0);
ListVector dbSchemaStatistics = (ListVector) dbSchemas.getVectorById(1);
StructVector statistics = (StructVector) dbSchemaStatistics.getDataVector();
VarCharVector tableNames = (VarCharVector) statistics.getVectorById(0);
VarCharVector columnNames = (VarCharVector) statistics.getVectorById(1);
SmallIntVector statisticKeys = (SmallIntVector) statistics.getVectorById(2);
DenseUnionVector statisticValues = (DenseUnionVector) statistics.getVectorById(3);
BitVector statisticIsApproximate = (BitVector) statistics.getVectorById(4);
// Build up the Arrow result
Text text = new Text();
NullableBigIntHolder holder = new NullableBigIntHolder();
int catalogIndex = 0;
int schemaIndex = 0;
int statisticIndex = 0;
for (String catalog : allStatistics.keySet()) {
Map<String, Map<String, Statistic>> schemas = allStatistics.get(catalog);
if (catalog == null) {
catalogNames.setNull(catalogIndex);
} else {
text.set(catalog);
catalogNames.setSafe(catalogIndex, text);
}
catalogDbSchemas.startNewValue(catalogIndex);
int schemaCount = 0;
for (String schema : schemas.keySet()) {
if (schema == null) {
dbSchemaNames.setNull(schemaIndex);
} else {
text.set(schema);
dbSchemaNames.setSafe(schemaIndex, text);
}
dbSchemaStatistics.startNewValue(schemaIndex);
Map<String, Statistic> indices = schemas.get(schema);
int statisticCount = 0;
for (Statistic statistic : indices.values()) {
if (statistic.multiColumn) {
continue;
}
text.set(statistic.table);
tableNames.setSafe(statisticIndex, text);
if (statistic.column == null) {
columnNames.setNull(statisticIndex);
} else {
text.set(statistic.column);
columnNames.setSafe(statisticIndex, text);
}
statisticKeys.setSafe(statisticIndex, statistic.key);
statisticValues.setTypeId(statisticIndex, (byte) 0);
holder.isSet = 1;
holder.value = statistic.value;
statisticValues.setSafe(statisticIndex, holder);
statisticIsApproximate.setSafe(statisticIndex, approximate ? 1 : 0);
statistics.setIndexDefined(statisticIndex++);
statisticCount++;
}
dbSchemaStatistics.endValue(schemaIndex, statisticCount);
dbSchemas.setIndexDefined(schemaIndex++);
schemaCount++;
}
catalogDbSchemas.endValue(catalogIndex, schemaCount);
catalogIndex++;
}
root.setRowCount(catalogIndex);
return RootArrowReader.fromRoot(allocator, root);
} catch (SQLException e) {
throw JdbcDriverUtil.fromSqlException(e);
}
}