共计 5020 个字符,预计需要花费 13 分钟才能阅读完成。
这篇文章主要为大家展示了“Presto 自定义函数 @SqlNullable 怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让丸趣 TV 小编带领大家一起研究并学习一下“Presto 自定义函数 @SqlNullable 怎么用”这篇文章吧。
看到标题我们会想到是由于 @SqlNullable 注解引发的问题,我们先看一段代码,正是这段有意思的代码,让我纠结了 2 个多小时,引发了 Presto 的问题。
@Description(user_id)
@ScalarFunction(user_id)
@SqlType(StandardTypes.VARCHAR)
public static Slice userId(@SqlType(StandardTypes.VARCHAR) Slice value) { String _value = value.toStringUtf8();
if (StringUtils.containsWhitespace(_value)) {
_value = StringUtils.replace(_value, , +
}
return Slices.utf8Slice(makeErrorMsgBase64(_value));
}
这段代码很简单,就是我们将传递进来的 base64 的字符串解码成实际的字符串,单单从代码上看是不会有什么问题的。当我们实际运行这个函数的时候问题就出现了,以下是一个使用示例:
select user_id(str) from temp.users limit 100;
看执行的 SQL 似乎也没有什么异常,但就是这么简简单单的一个函数引发了 Presto 的问题,那就是 java.lang.NullPointerException: undefined 错误,这个错误的具体内容如下
java.lang.NullPointerException: undefined
at io.prestosql.type.VarcharOperators.equal(VarcharOperators.java:53)
at io.prestosql.$gen.CursorProcessor_20200927_063218_2398.filter(Unknown Source)
at io.prestosql.$gen.CursorProcessor_20200927_063218_2398.process(Unknown Source)
at io.prestosql.operator.ScanFilterAndProjectOperator$RecordCursorToPages.process(ScanFilterAndProjectOperator.java:323)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils.getNextState(WorkProcessorUtils.java:221)
at io.prestosql.operator.WorkProcessorUtils$YieldingProcess.process(WorkProcessorUtils.java:181)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils.getNextState(WorkProcessorUtils.java:221)
at io.prestosql.operator.WorkProcessorUtils.lambda$processStateMonitor$2(WorkProcessorUtils.java:200)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils.lambda$flatten$6(WorkProcessorUtils.java:277)
at io.prestosql.operator.WorkProcessorUtils$3.process(WorkProcessorUtils.java:319)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils$3.process(WorkProcessorUtils.java:306)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils.getNextState(WorkProcessorUtils.java:221)
at io.prestosql.operator.WorkProcessorUtils.lambda$processStateMonitor$2(WorkProcessorUtils.java:200)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorUtils.getNextState(WorkProcessorUtils.java:221)
at io.prestosql.operator.WorkProcessorUtils.lambda$finishWhen$3(WorkProcessorUtils.java:215)
at io.prestosql.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:372)
at io.prestosql.operator.WorkProcessorSourceOperatorAdapter.getOutput(WorkProcessorSourceOperatorAdapter.java:149)
at io.prestosql.operator.Driver.processInternal(Driver.java:379)
at io.prestosql.operator.Driver.lambda$processFor$8(Driver.java:283)
at io.prestosql.operator.Driver.tryWithLock(Driver.java:675)
at io.prestosql.operator.Driver.processFor(Driver.java:276)
at io.prestosql.execution.SqlTaskExecution$DriverSplitRunner.processFor(SqlTaskExecution.java:1076)
at io.prestosql.execution.executor.PrioritizedSplitRunner.process(PrioritizedSplitRunner.java:shichengoooo@163.com)
at io.prestosql.execution.executor.TaskExecutor$TaskRunner.run(TaskExecutor.java:484)
at io.prestosql.$gen.Presto_341____20200925_110330_2.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
通过上面错误我们推算出应该是由于数据导致空指针异常,那么问题出在哪里呢?问题就出在查询 str 这个字段中,这个字段我们经过实际的查询发现是有 的数据,在做转换的时候出现了空指针问题,于是我们修改 UDF 的源码为
@Description(user_id)
@ScalarFunction(user_id)
@SqlType(StandardTypes.VARCHAR)
@SqlNullable
public static Slice userId(@SqlNullable @SqlType(StandardTypes.VARCHAR) Slice value) { String _value = value.toStringUtf8();
if (StringUtils.containsWhitespace(_value)) {
_value = StringUtils.replace(_value, , +
}
return Slices.utf8Slice(makeErrorMsgBase64(_value));
}
我们在方法和参数上添加了 @SqlNullable 注解用于标记此函数可以接收空的数据,这似乎看着也没有问题,我们将该函数重新发布,再次执行 SQL 发现还存在相同的问题,于是又将代码修改为以下内容
@Description(user_id)
@ScalarFunction(user_id)
@SqlType(StandardTypes.VARCHAR)
public static Slice userId(@SqlNullable @SqlType(StandardTypes.VARCHAR) Slice value) { String _value = value.toStringUtf8();
if (StringUtils.containsWhitespace(_value)) {
_value = StringUtils.replace(_value, , +
}
return Slices.utf8Slice(makeErrorMsgBase64(_value));
}
删除了方法上的 @SqlNullable 注解,再次运行发现不会再出现这个错误,但是 Presto 服务中不断的报出空指针错误,只是不在反馈给查询客户端,原本以为此问题已经解决,然而更有意思的事情发生了,我们使用了 343 版本测试成功后,线上版本是 341,升级线上后发现此问题再次复现,如果再次在方法上加上 @SqlNullable 注解在 341 版本上又会修复这个问题,目前已将这个问题反馈给官方,推荐大家使用 343 版本!
以上是“Presto 自定义函数 @SqlNullable 怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道!