为什么这个 Hive QL 表达式失败了?

Why is this Hive QL expression failing?

此查询因神秘评估错误而失败:

select printf("%08x", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

(此处例外)

Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: Error evaluating printf('%08x', reflect('java.lang.Integer','reverseBytes',1))

我想要完成的是一致地重现 murmur3 哈希十六进制值的 Java 实现,它使用哈希 getBytes 方法,returns 它们在一个大的endian 格式(十进制数字以 little endian 书写),因此整数中的字节交换。

单独执行查询的每个部分都非常有效,它混合了 printf 和 reflect 失败的地方......而且只有当格式是数字类型时,这样才有效:

select printf("%s", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

但这也失败了

select printf("%d", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

并且我确保结果是数字类型而不是字符串,因为我可以对其进行算术运算,例如:

select printf("%s", 10 * reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

到目前为止,我不需要添加任何自定义 UDF,因此如果有解决方法,我想保持这种方式。

Hive 基本上是一个 Java 程序,它将 SQL 类数据类型和表达式转换为 Java 数据类型和 Java/Hadoop expressions/jobs。
在大多数情况下已经足够复杂了。但是,如果您在组合中加入自定义 Java 表达式——这就是 reflect() 的全部意义所在——那么您很可能会陷入极端情况。

在您的特定问题中,静态 java.lang.Integer.reverseBytes(int) 应该 return 原始类型 int 值。但我不确定 Hive 如何在内部处理通用整数值——可能使用 long?也许使用自定义对象类型??
无论如何,看起来 return 值不能作为数字类型 直接 馈入 Hive printf() 函数。也许 int 默认情况下被转换为 String ...也许它可以使用 long 而不是...

我看到了两种可能的解决方法:

  1. 在子查询中包装对 reflect() 的调用,以便 Hive 隐式转换为 Hive 支持的类型(子查询在编译时合并,不需要额外的 MR 步骤)--存在 Hive 类型仍为 String
    select printf("%d", WTF) from (select reflect(.....) as WTF from ...) DUH
  2. 的风险
  3. 需要显式转换为您选择的 Hive 数字类型
    select printf("%d", cast(reflect(.......) as int)) from ...