为什么这个 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
而不是...
我看到了两种可能的解决方法:
- 在子查询中包装对
reflect()
的调用,以便 Hive 隐式转换为 Hive 支持的类型(子查询在编译时合并,不需要额外的 MR 步骤)--存在 Hive 类型仍为 String
select printf("%d", WTF) from (select reflect(.....) as WTF from ...) DUH
的风险
- 需要显式转换为您选择的 Hive 数字类型
select printf("%d", cast(reflect(.......) as int)) from ...
此查询因神秘评估错误而失败:
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
而不是...
我看到了两种可能的解决方法:
- 在子查询中包装对
reflect()
的调用,以便 Hive 隐式转换为 Hive 支持的类型(子查询在编译时合并,不需要额外的 MR 步骤)--存在 Hive 类型仍为String
select printf("%d", WTF) from (select reflect(.....) as WTF from ...) DUH
的风险
- 需要显式转换为您选择的 Hive 数字类型
select printf("%d", cast(reflect(.......) as int)) from ...