Apache Drill UDF:未找到函数签名的匹配项

Posted

技术标签:

【中文标题】Apache Drill UDF:未找到函数签名的匹配项【英文标题】:Apache Drill UDF: No match found for function signature 【发布时间】:2021-03-24 00:43:56 【问题描述】:

您好,我正在开发钻头用户定义的函数。我已经写了这个 UDF。

package somepackage.udfs;

import io.netty.buffer.DrillBuf;
import org.apache.drill.exec.expr.DrillSimpleFunc;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;

import javax.inject.Inject;

@FunctionTemplate(
        name = "split_sample",
        scope = FunctionTemplate.FunctionScope.SIMPLE,
        nulls = FunctionTemplate.NullHandling.NULL_IF_NULL
)
public class SplitTrainTestSample implements DrillSimpleFunc 
    @Param
    NullableVarCharHolder targetIn;

    @Param(constant = true)
    Float8Holder train_test_rate;

    @Output
    VarCharHolder label;

    @Inject
    DrillBuf buffer;

    public SplitTrainTestSample() 
    

    @Override
    public void setup() 
    

    @Override
    public void eval() 
        double r = Math.random();
        String l;
        assert 0 < train_test_rate.value && train_test_rate.value < 1;
        if (r < train_test_rate.value) 
            l = "train";
        
        else 
            l = "test";
        
        byte[] bytes = l.getBytes();

        label.buffer = buffer;
        label.start = 0;
        label.end = bytes.length;
        label.buffer.setBytes(0, bytes);
    

但是当我运行这个查询时

Apache Drill> select split_sample(cast(full_name as char), 0.5) from cp.`employee.json`;

Drill 返回错误消息。

Error: VALIDATION ERROR: From line 1, column 8 to line 1, column 49: No match found for function signature split_sample(<CHARACTER>, <NUMERIC>)

请帮我找出问题所在。我在同一个包下编写了另一个 UDF,它工作得很好。所以不太可能是 UDF 注册表错误。

有没有办法探测 UDF 的函数签名?

【问题讨论】:

【参考方案1】:

Drill UDF 真的很难调试。

我怀疑这种情况下的问题是:

double r = Math.random();

尝试将其替换为:

double r = java.lang.Math.random();

如果这不起作用,您可能想尝试使用简单的if 语句而不是assert。另外,我从未在 UDF 参数中看到过(constant = true)

一般来说,除了 Drill 内部类之外,几乎所有的外部类都必须用它们的完整路径写出来。除了 Drill 内部,您不能将任何内容导入 UDF。 UDF 实际上使用 Java 的一个子集,结果是要知道哪些支持哪些不支持可能有点棘手。

让这很烦人的是,Drill 没有给你任何有用的调试信息。它只是说它找不到 UDF。

当这种情况发生在我身上时,我要做的是注释掉整个 UDF 正文,在取消注释每一行后运行该函数以查看是哪一行导致了问题。

一种简单的解决方法是创建一个带有静态函数的帮助类。

public class functionHelpers 
 public String getLabel(<params>) 
   // Your code here... 
 


// Then in your UDF exec() method
...

String label = com.my_package.functionHelpers.getLabel(<params>);
...

如果您有复杂的 UDF,这会让生活变得更轻松。您还可以更轻松地调试代码,因为您可以轻松地为帮助类编写单元测试,然后使用固定代码将输出映射到 Drill 向量。

【讨论】:

以上是关于Apache Drill UDF:未找到函数签名的匹配项的主要内容,如果未能解决你的问题,请参考以下文章

雪花 SQL udf 的输入列表

使用 Apache Drill

Apache Drill - 以嵌入式模式连接到 Drill [java]

sdk-3.1.1.js:1 未捕获类型错误:无法在“URL”上执行“createObjectURL”:未找到与提供的签名匹配的函数

存储插件配置持久性不适用于 Apache Drill

Apache Drill 查询 HBase 表