From d1940b98e529577f412b817fa1273b8e2ec07337 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 13 Mar 2026 18:33:14 +0100 Subject: [PATCH] Fix timeseries query: use epoch-based bucketing for DateTime64 compatibility Replace toStartOfInterval with intDiv on epoch seconds, and cast avg/quantile results to Int64 to avoid Float64 JDBC mapping issues. Co-Authored-By: Claude Opus 4.6 --- .../server/app/search/ClickHouseSearchEngine.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/search/ClickHouseSearchEngine.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/search/ClickHouseSearchEngine.java index 81f77d2f..67744177 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/search/ClickHouseSearchEngine.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/search/ClickHouseSearchEngine.java @@ -106,12 +106,13 @@ public class ClickHouseSearchEngine implements SearchEngine { long intervalSeconds = Duration.between(from, to).getSeconds() / bucketCount; if (intervalSeconds < 1) intervalSeconds = 1; + // Use epoch-based bucketing for DateTime64 compatibility String sql = "SELECT " + - "toStartOfInterval(start_time, INTERVAL " + intervalSeconds + " SECOND) AS bucket, " + + "toDateTime(intDiv(toUInt32(toDateTime(start_time)), " + intervalSeconds + ") * " + intervalSeconds + ") AS bucket, " + "count() AS total_count, " + "countIf(status = 'FAILED') AS failed_count, " + - "avg(duration_ms) AS avg_duration_ms, " + - "quantile(0.99)(duration_ms) AS p99_duration_ms, " + + "toInt64(avg(duration_ms)) AS avg_duration_ms, " + + "toInt64(quantile(0.99)(duration_ms)) AS p99_duration_ms, " + "countIf(status = 'RUNNING') AS active_count " + "FROM route_executions " + "WHERE start_time >= ? AND start_time <= ? " +