From dfc8e0d5c818d8c4bf0a136838facb7cc7ea6dd5 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Fri, 8 Nov 2024 14:08:10 -0600 Subject: [PATCH] feat: Enable unique values in column statistics calls from JS (#6346) Fixes #5031 --- .../web/client/api/JsColumnStatistics.java | 2 +- .../io/deephaven/web/client/api/JsTable.java | 26 ----- .../web/ClientIntegrationTestSuite.java | 1 + .../client/api/ColumnStatisticsTestGwt.java | 99 +++++++++++++++++++ 4 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 web/client-api/src/test/java/io/deephaven/web/client/api/ColumnStatisticsTestGwt.java diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/JsColumnStatistics.java b/web/client-api/src/main/java/io/deephaven/web/client/api/JsColumnStatistics.java index d66034f67d4..05f1a4f6b15 100644 --- a/web/client-api/src/main/java/io/deephaven/web/client/api/JsColumnStatistics.java +++ b/web/client-api/src/main/java/io/deephaven/web/client/api/JsColumnStatistics.java @@ -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. */ diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java index aa0721bd546..04127edec70 100644 --- a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java +++ b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java @@ -1344,32 +1344,6 @@ public Promise 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 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); diff --git a/web/client-api/src/test/java/io/deephaven/web/ClientIntegrationTestSuite.java b/web/client-api/src/test/java/io/deephaven/web/ClientIntegrationTestSuite.java index e76783234d2..3c1887e8a5c 100644 --- a/web/client-api/src/test/java/io/deephaven/web/ClientIntegrationTestSuite.java +++ b/web/client-api/src/test/java/io/deephaven/web/ClientIntegrationTestSuite.java @@ -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 diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/ColumnStatisticsTestGwt.java b/web/client-api/src/test/java/io/deephaven/web/client/api/ColumnStatisticsTestGwt.java new file mode 100644 index 00000000000..dff62ea6f7b --- /dev/null +++ b/web/client-api/src/test/java/io/deephaven/web/client/api/ColumnStatisticsTestGwt.java @@ -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 uniqueValues = stats.getUniqueValues(); + assertEquals(0, uniqueValues.size); + + return null; + }), + table.getColumnStatistics(table.findColumn("B")) + .then(stats -> { + JsMap 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 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 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"; + } + +}