You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Calcite Druid Adapter:含时间运算的FLOOR无法识别有效原点

问题描述

我尝试使用Apache Calcite对Druid数据源执行以下查询:

SELECT
  FLOOR(
      ("__time" + INTERVAL '5' HOUR + INTERVAL '30' MINUTE)
      TO DAY
  ) AS "createtime.day",
  COUNT(*) AS "count"
FROM "druid"."myevent_activated";

目标是将__time列调整为UTC+5:30时区后按天取整,但通过Calcite Druid适配器运行时出现错误:当在FLOOR函数内执行时间运算(如添加5.5小时)时,适配器无法确定取整操作的有效“原点”(起始时间)。

经排查:

  • 正确行为:适配器应传入null作为原点,让Druid使用默认纪元时间
  • 错误行为:适配器传入空字符串''作为原点,导致执行失败

核心问题

  1. 有无办法在Apache Calcite与Druid中执行时间运算和FLOOR操作而不触发该错误?
  2. 有无替代方法(函数或原生查询)可实现相同的时区调整和按天取整效果?
  3. 这是否是Calcite Druid适配器的已知Bug,近期版本是否有修复?

注:已知原生Druid查询中的TIME_FLOOR可正常处理此场景,但需通过Calcite SQL实现。

解决方案与解答

1. 避免错误的临时修复方案

可以通过调整SQL结构,将时间偏移运算移到FLOOR函数外部,避免嵌套运算触发适配器的原点判断逻辑:

SELECT
  FLOOR("adjusted_time" TO DAY) AS "createtime.day",
  COUNT(*) AS "count"
FROM (
  SELECT
    "__time" + INTERVAL '5' HOUR + INTERVAL '30' MINUTE AS "adjusted_time"
  FROM "druid"."myevent_activated"
) t;

这种方式下,FLOOR函数的参数是子查询中已计算完成的时间列,适配器会正确识别并传入null作为原点。

如果有权限修改适配器代码,可直接调整DruidSqlConverter中处理FLOOR时间取整的逻辑,将默认原点从空字符串改为null。

2. 替代实现方法

  • 使用时区转换函数:如果Calcite版本支持AT TIME ZONE语法,可直接通过时区转换替代手动加减间隔,更简洁且不易出错:
SELECT
  FLOOR("__time" AT TIME ZONE 'UTC' AT TIME ZONE 'Asia/Kolkata' TO DAY) AS "createtime.day",
  COUNT(*) AS "count"
FROM "druid"."myevent_activated";

Asia/Kolkata对应UTC+5:30时区,直接完成时区转换后再按天取整。

  • 调用Druid原生TIME_FLOOR函数:通过Calcite映射Druid原生函数,直接传入时区参数:
SELECT
  TIME_FLOOR("__time", 'P1D', NULL, '+05:30') AS "createtime.day",
  COUNT(*) AS "count"
FROM "druid"."myevent_activated";

需确保Calcite Druid适配器已配置支持原生函数调用,部分版本可能需要在配置文件中添加函数映射规则。

3. Bug状态与版本修复情况

这是Calcite Druid适配器的已知Bug,在Apache Calcite官方Issue跟踪系统中已有记录。Calcite 1.32.0及以后的版本已修复该问题,修复逻辑为:当无法自动推导FLOOR取整的原点时,默认传递null而非空字符串,适配Druid的默认行为。建议升级到最新稳定版Calcite来彻底解决此问题。

内容的提问来源于stack exchange,提问作者Sachithra Dilshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 22:46:01