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

时间:2016-05-04 18:00:59

标签: java hadoop hex string-formatting endianness

此查询失败并出现神秘的评估错误:

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

(这是例外)

getBytes

我想要完成的是一致地重现murmur3哈希十六进制值的Java实现,该值使用hasher select printf("%s", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0))); 方法,以大端格式返回它们(并且十进制数字写得很少) endian),因此字节交换整数。

分别完成查询的每个部分,它会混合printf并反映出失败的内容......只有当格式化为数字类型时,才有效:

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

但这也失败了

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

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

{{1}}

到目前为止,我还没有添加任何自定义UDF,所以如果有解决方法,我希望保持这种方式。

1 个答案:

答案 0 :(得分:1)

Hive基本上是一个Java程序,它将类似SQL的数据类型和表达式转换为Java数据类型和Java / Hadoop表达式/作业。
在大多数情况下,它足够复杂。但是如果你在混合中抛出一个自定义Java表达式 - 那就是reflect()的全部内容 - 那么你可能会陷入边缘情况。

在您的特定问题中,静态java.lang.Integer.reverseBytes(int)应返回原始类型int值。但我不确定Hive如何在内部处理通用整数值 - 可能是long?也许用自定义对象类型??
无论如何,看起来返回值不能直接直接作为数字类型提供给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 ...