Skip to content

Commit 74dbdb6

Browse files
authored
Enhance doc and error message handling for bins on time-related fields (#4713) (#4937)
(cherry picked from commit ef4c51e) Signed-off-by: Kai Huang <ahkcs@amazon.com>
1 parent f62e932 commit 74dbdb6

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

core/src/main/java/org/opensearch/sql/calcite/utils/CalciteToolsHelper.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,17 @@ public RelNode visit(TableScan scan) {
360360
final RelRunner runner = connection.unwrap(RelRunner.class);
361361
return runner.prepareStatement(rel);
362362
} catch (SQLException e) {
363+
// Detect if error is due to window functions in unsupported context (bins on time fields)
364+
String errorMsg = e.getMessage();
365+
if (errorMsg != null
366+
&& errorMsg.contains("Error while preparing plan")
367+
&& errorMsg.contains("WIDTH_BUCKET")) {
368+
throw new UnsupportedOperationException(
369+
"The 'bins' parameter on timestamp fields requires: (1) pushdown to be enabled"
370+
+ " (controlled by plugins.calcite.pushdown.enabled, enabled by default), and"
371+
+ " (2) the timestamp field to be used as an aggregation bucket (e.g., 'stats"
372+
+ " count() by @timestamp').");
373+
}
363374
throw Util.throwAsRuntime(e);
364375
}
365376
}

core/src/main/java/org/opensearch/sql/calcite/utils/binning/handlers/CountBinHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ public RexNode createExpression(
2828
CountBin countBin = (CountBin) node;
2929

3030
// Create validated binnable field (validates that field is numeric or time-based)
31-
// Note: bins parameter works with both numeric and time-based fields
31+
// Note: bins parameter on time-based fields requires:
32+
// 1. Pushdown to be enabled (controlled by plugins.calcite.pushdown.enabled, enabled by
33+
// default)
34+
// 2. The time-based field to be used as an aggregation bucket
35+
// (e.g., stats count() by @timestamp)
3236
String fieldName = BinFieldValidator.extractFieldName(node);
3337
BinnableField field = new BinnableField(fieldExpr, fieldExpr.getType(), fieldName);
3438

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteBinCommandIT.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.opensearch.sql.calcite.remote;
77

8+
import static org.junit.Assert.assertThrows;
89
import static org.junit.Assert.assertTrue;
910
import static org.junit.jupiter.api.Assertions.assertThrows;
1011
import static org.opensearch.sql.legacy.TestsConstants.*;
@@ -988,6 +989,33 @@ public void testStatsWithBinsOnTimeAndTermField_Avg() throws IOException {
988989
rows(40.25, "us-west", "2024-07-01 00:01:00"));
989990
}
990991

992+
@Test
993+
public void testBinsOnTimeFieldWithPushdownDisabled_ShouldFail() throws IOException {
994+
// Verify that bins parameter on timestamp fields fails with clear error when pushdown disabled
995+
enabledOnlyWhenPushdownIsDisabled();
996+
997+
ResponseException exception =
998+
assertThrows(
999+
ResponseException.class,
1000+
() ->
1001+
executeQuery(
1002+
"source=events_null | bin @timestamp bins=3 | stats count() by @timestamp"));
1003+
1004+
// Verify the error message clearly explains the limitation and suggests solutions
1005+
// Note: bins parameter on timestamp fields requires BOTH:
1006+
// 1. Pushdown to be enabled (plugins.calcite.pushdown.enabled=true, enabled by default)
1007+
// 2. The timestamp field to be used as an aggregation bucket (e.g., stats count() by
1008+
// @timestamp)
1009+
String errorMessage = exception.getMessage();
1010+
assertTrue(
1011+
"Expected clear error message about bins parameter requirements on timestamp fields, but"
1012+
+ " got: "
1013+
+ errorMessage,
1014+
errorMessage.contains("bins' parameter on timestamp fields requires")
1015+
&& errorMessage.contains("pushdown to be enabled")
1016+
&& errorMessage.contains("aggregation bucket"));
1017+
}
1018+
9911019
@Test
9921020
public void testBinWithNestedFieldWithoutExplicitProjection() throws IOException {
9931021
// Test bin command on nested field without explicit fields projection

integ-test/src/test/java/org/opensearch/sql/ppl/PPLIntegTestCase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ protected void enabledOnlyWhenPushdownIsEnabled() throws IOException {
333333
Assume.assumeTrue("This test is only for when push down is enabled", !isPushdownDisabled());
334334
}
335335

336+
protected void enabledOnlyWhenPushdownIsDisabled() throws IOException {
337+
Assume.assumeTrue("This test is only for when push down is disabled", isPushdownDisabled());
338+
}
339+
336340
public void updatePushdownSettings() throws IOException {
337341
String pushdownEnabled = String.valueOf(GlobalPushdownConfig.enabled);
338342
assert !pushdownEnabled.isBlank() : "Pushdown enabled setting cannot be empty";

0 commit comments

Comments
 (0)