From 5ad0c75da88862e707550d10d3e32310f30ac3a8 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Sun, 15 Mar 2026 11:15:42 +0100 Subject: [PATCH] Truncate rollup params to second precision for DateTime column The JDBC driver sends java.sql.Timestamp with nanoseconds as a string (e.g. '2026-03-15 10:13:58.105931162') which DateTime('UTC') rejects. Add bucketTimestamp() helper that truncates to seconds for all rollup query parameters. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../app/search/ClickHouseSearchEngine.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 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 bbd36d1f..1ed6f047 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 @@ -100,9 +100,9 @@ public class ClickHouseSearchEngine implements SearchEngine { var conditions = new ArrayList(); var params = new ArrayList(); conditions.add("bucket >= ?"); - params.add(Timestamp.from(floorToFiveMinutes(from))); + params.add(bucketTimestamp(floorToFiveMinutes(from))); conditions.add("bucket <= ?"); - params.add(Timestamp.from(to)); + params.add(bucketTimestamp(to)); addScopeFilters(routeId, agentIds, conditions, params); String where = " WHERE " + String.join(" AND ", conditions); @@ -140,9 +140,9 @@ public class ClickHouseSearchEngine implements SearchEngine { var prevConditions = new ArrayList(); var prevParams = new ArrayList(); prevConditions.add("bucket >= ?"); - prevParams.add(Timestamp.from(floorToFiveMinutes(prevFrom))); + prevParams.add(bucketTimestamp(floorToFiveMinutes(prevFrom))); prevConditions.add("bucket <= ?"); - prevParams.add(Timestamp.from(prevTo)); + prevParams.add(bucketTimestamp(prevTo)); addScopeFilters(routeId, agentIds, prevConditions, prevParams); String prevWhere = " WHERE " + String.join(" AND ", prevConditions); @@ -166,7 +166,7 @@ public class ClickHouseSearchEngine implements SearchEngine { var todayConditions = new ArrayList(); var todayParams = new ArrayList(); todayConditions.add("bucket >= ?"); - todayParams.add(Timestamp.from(floorToFiveMinutes(todayStart))); + todayParams.add(bucketTimestamp(floorToFiveMinutes(todayStart))); addScopeFilters(routeId, agentIds, todayConditions, todayParams); String todayWhere = " WHERE " + String.join(" AND ", todayConditions); @@ -195,9 +195,9 @@ public class ClickHouseSearchEngine implements SearchEngine { var conditions = new ArrayList(); var params = new ArrayList(); conditions.add("bucket >= ?"); - params.add(Timestamp.from(floorToFiveMinutes(from))); + params.add(bucketTimestamp(floorToFiveMinutes(from))); conditions.add("bucket <= ?"); - params.add(Timestamp.from(to)); + params.add(bucketTimestamp(to)); addScopeFilters(routeId, agentIds, conditions, params); String where = " WHERE " + String.join(" AND ", conditions); @@ -334,6 +334,15 @@ public class ClickHouseSearchEngine implements SearchEngine { return Instant.ofEpochSecond(epochSecond - (epochSecond % 300)); } + /** + * Create a second-precision Timestamp for rollup bucket comparisons. + * The bucket column is DateTime('UTC') (second precision); the JDBC driver + * sends java.sql.Timestamp with nanoseconds which ClickHouse rejects. + */ + private static Timestamp bucketTimestamp(Instant instant) { + return Timestamp.from(instant.truncatedTo(java.time.temporal.ChronoUnit.SECONDS)); + } + /** * Escape special LIKE characters to prevent LIKE injection. */