Skip to content

Commit

Permalink
feat: Enable unique values in column statistics calls from JS (#6346)
Browse files Browse the repository at this point in the history
Fixes #5031
  • Loading branch information
niloc132 authored Nov 8, 2024
1 parent 238bc30 commit dfc8e0d
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public enum StatType {
/**
* The number of unique values in the column.
*/
UNIQUE_VALUES("UNIQUE VALUES", "long"),
UNIQUE_VALUES("UNIQUE VALUES", "int"),
/**
* The sum of all data in the column.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1344,32 +1344,6 @@ public Promise<JsColumnStatistics> getColumnStatistics(Column column) {
}, "get column statistics")
.refetch(this, workerConnection.metadata())
.then(state -> {
// TODO (deephaven-core#188) don't drop these columns once we can decode them
JsArray<String> dropCols = new JsArray<>();
if (Arrays.stream(state.getColumns()).anyMatch(c -> c.getName().equals("UNIQUE_KEYS"))) {
dropCols.push("UNIQUE_KEYS");
}
if (Arrays.stream(state.getColumns()).anyMatch(c -> c.getName().equals("UNIQUE_COUNTS"))) {
dropCols.push("UNIQUE_COUNTS");
}

if (dropCols.length > 0) {
toRelease.add(() -> workerConnection.releaseHandle(state.getHandle()));
return workerConnection.newState((c2, state2, metadata2) -> {
DropColumnsRequest drop = new DropColumnsRequest();
drop.setColumnNamesList(dropCols);
drop.setSourceId(state.getHandle().makeTableReference());
drop.setResultId(state2.getHandle().makeTicket());
workerConnection.tableServiceClient().dropColumns(drop, metadata2, c2::apply);
}, "drop unreadable stats columns")
.refetch(this, workerConnection.metadata())
.then(state2 -> {
JsTable table = new JsTable(workerConnection, state2);
toRelease.add(table::close);
table.setViewport(0, 0);
return table.getViewportData();
});
}
JsTable table = new JsTable(workerConnection, state);
toRelease.add(table::close);
table.setViewport(0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static Test suite() {
suite.addTestSuite(PartitionedTableTestGwt.class);
suite.addTestSuite(JsStorageServiceTestGwt.class);
suite.addTestSuite(InputTableTestGwt.class);
suite.addTestSuite(ColumnStatisticsTestGwt.class);

// This should be a unit test, but it requires a browser environment to run on GWT 2.9
// GWT 2.9 doesn't have proper bindings for Promises in HtmlUnit, so we need to use the IntegrationTest suite
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.web.client.api;

import elemental2.core.JsMap;
import elemental2.promise.Promise;

public class ColumnStatisticsTestGwt extends AbstractAsyncGwtTestCase {
private final TableSourceBuilder tables = new TableSourceBuilder()
.script("from deephaven import empty_table")
.script("staticTable", "empty_table(3).update([\"A = i % 2\", \"B = `` + A\"])");

public void testStatsWithUniqueCounts() {
connect(tables)
.then(table("staticTable"))
.then(table -> Promise.all(
table.getColumnStatistics(table.findColumn("A"))
.then(stats -> {
JsMap<String, Double> uniqueValues = stats.getUniqueValues();
assertEquals(0, uniqueValues.size);

return null;
}),
table.getColumnStatistics(table.findColumn("B"))
.then(stats -> {
JsMap<String, Double> uniqueValues = stats.getUniqueValues();
assertEquals(2, uniqueValues.size);
assertEquals(2.0, uniqueValues.get("0"));
assertEquals(1.0, uniqueValues.get("1"));

return null;
})))
.then(this::finish).catch_(this::report);
}

public void testStats() {
connect(tables)
.then(table("staticTable"))
.then(table -> Promise.all(
table.getColumnStatistics(table.findColumn("A"))
.then(stats -> {
JsMap<String, Object> values = stats.getStatisticsMap();
assertEquals(LongWrapper.of(3),
values.get(JsColumnStatistics.StatType.COUNT.getDisplayName()));
assertEquals(LongWrapper.of(3),
values.get(JsColumnStatistics.StatType.SIZE.getDisplayName()));
assertEquals(null,
values.get(JsColumnStatistics.StatType.UNIQUE_VALUES.getDisplayName()));
assertEquals(LongWrapper.of(1),
values.get(JsColumnStatistics.StatType.SUM.getDisplayName()));
assertEquals(LongWrapper.of(1),
values.get(JsColumnStatistics.StatType.SUM_ABS.getDisplayName()));
assertEquals(1. / 3., values.get(JsColumnStatistics.StatType.AVG.getDisplayName()));
assertEquals(1. / 3.,
values.get(JsColumnStatistics.StatType.AVG_ABS.getDisplayName()));
assertEquals(0.0, values.get(JsColumnStatistics.StatType.MIN.getDisplayName()));
assertEquals(0.0, values.get(JsColumnStatistics.StatType.MIN_ABS.getDisplayName()));
assertEquals(1.0, values.get(JsColumnStatistics.StatType.MAX.getDisplayName()));
assertEquals(1.0, values.get(JsColumnStatistics.StatType.MAX_ABS.getDisplayName()));
assertEquals(0.5774,
(Double) values.get(JsColumnStatistics.StatType.STD_DEV.getDisplayName()),
0.0001);
assertEquals(LongWrapper.of(1),
values.get(JsColumnStatistics.StatType.SUM_SQRD.getDisplayName()));

return null;
}),
table.getColumnStatistics(table.findColumn("B"))
.then(stats -> {
JsMap<String, Object> values = stats.getStatisticsMap();
assertEquals(LongWrapper.of(3),
values.get(JsColumnStatistics.StatType.COUNT.getDisplayName()));
assertEquals(LongWrapper.of(3),
values.get(JsColumnStatistics.StatType.SIZE.getDisplayName()));
assertEquals(2.0,
values.get(JsColumnStatistics.StatType.UNIQUE_VALUES.getDisplayName()));

assertEquals(null, values.get(JsColumnStatistics.StatType.SUM.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.SUM_ABS.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.AVG.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.AVG_ABS.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.MIN.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.MIN_ABS.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.MAX.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.MAX_ABS.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.STD_DEV.name()));
assertEquals(null, values.get(JsColumnStatistics.StatType.SUM_SQRD.name()));
return null;
})))
.then(this::finish).catch_(this::report);
}

@Override
public String getModuleName() {
return "io.deephaven.web.DeephavenIntegrationTest";
}

}

0 comments on commit dfc8e0d

Please sign in to comment.