• Apache Calcite - 自定义标量函数


    前言

    上一篇文章中我们介绍了calcite中内置函数的使用。实际需求中会遇到一些场景标准内置函数无法满足需求,这时候就需要用到自定义函数。在 Apache Calcite 中添加自定义函数,以便在 SQL 查询中使用自定义的逻辑。这对于执行特定的数据处理或分析任务非常有用。

    相关依赖

    通过前面的学习,我们知道表、函数等信息维护在schema中,因此我们要做的事情就是在schema中新增自定义的函数。

    以下演示基于1.36版包实现。

        <dependency>
          <groupId>org.apache.calcitegroupId>
          <artifactId>calcite-coreartifactId>
          <version>1.36.0version>
        dependency>
    

    为了新增函数我们需要重写AbstractSchema中的 getFunctionMultimap方法,方法定义如下:

      protected Multimap<String, Function> getFunctionMultimap() {
        return ImmutableMultimap.of();
      }
    

    Function有多种实现,由于我们要扩展的是标量函数,所以关注ScalarFunction即可。
    在这里插入图片描述
    这里我们用到ScalarFunctionImpl.create方法来创建标量函数,方法中的参数1是所建函数所在的类,第二个是对应的方法名。

      /**
       * Creates {@link org.apache.calcite.schema.ScalarFunction} from given class.
       *
       * 

    If a method of the given name is not found, or it does not suit, * returns {@code null}. * * @param clazz class that is used to implement the function * @param methodName Method name (typically "eval") * @return created {@link ScalarFunction} or null */ public static @Nullable ScalarFunction create(Class<?> clazz, String methodName) { final Method method = findMethod(clazz, methodName); if (method == null) { return null; } return create(method); }

    实现自定义标量函数

    为了方便演示,我们实现一个无用的简单方法,对整数减1

    public class CustomFunctions {
        public static Integer minus1(int num1) {
            return num1 - 1;
        }
    }
    

    接着扩展前文中用到的schema,实现getFunctionMultimap方法,并增加添加函数的方法

    public class ListSchema extends AbstractSchema {
        Map<String, Table> tableMap = new HashMap<>();
    
        Multimap<String, Function> functionMap = LinkedListMultimap.create();
    
        public void addTable(String name, Table table) {
            tableMap.put(name, table);
        }
    
        public void addFunction(String name,Function function) { functionMap.put(name, function);}
        public ListSchema() {
        }
    
        @Override
        protected Map<String, Table> getTableMap() {
            return tableMap;
        }
    
        @Override
        protected Multimap<String, Function> getFunctionMultimap() {
            return functionMap;
        }
    }
    

    最后我们在schema中注册函数

    ListSchema listSchema = new ListSchema();
    listSchema.addFunction("minus1", ScalarFunctionImpl.create(CustomFunctions.class,"minus1"));
    

    完成上述工作后,在sql中使用自定义的函数

    ResultSet countResult = statement.executeQuery("select age,listSchema.minus1(age) from listSchema.MyTable");
    

    打印结果,可以看到自定义方法的计算结果

    95 94 
    21 20 
    47 46 
    

    异常处理

    在完成上述工作时也遇到了几个异常,分别如下:

    No match found for function signature minus1(< NUMERIC>)

    • 详细的异常提示为:java.sql.SQLException: Error while executing SQL “select age,minus1(age) from listSchema.MyTable”: From line 1, column 12 to line 1, column 22: No match found for function signature minus1()
    • 异常原因
      1.注册的方法名与使用方法名不一致。最开始注册时,将方法名首字母写成了大写。但实际使用时却使用的小写名 Minus1 - > minus1 listSchema.addFunction(“Minus1”, ScalarFunctionImpl.create(CustomFunctions.class,“minus1”));
      2.另外使用方法名时没指定schema名,导致了错误
      上述两个问题修改完毕程序正常运行

    总结

    实现自定义标量函数,注册到schema最后使用,schema是核心,维护了各类元信息,并提供了扩展接口来实现自定义的能力

  • 相关阅读:
    C++:多态
    流量管理技术
    ros2_control【B站WMGIII教学学习记录】1
    2022眼康品牌加盟展,北京视力保健展,中国眼科医学技术峰会
    Java 实现uniapp本机手机号一键登录
    【使用malloc函数动态模拟开辟二维数组的三种方法】
    腾讯云镜像TencentOS Server操作系统介绍、性能稳定性测评
    23种设计模式之享元模式
    Linux中select poll和epoll的区别
    CPU利用率百分之百(TiWorker.exe实锤病毒篇)
  • 原文地址:https://blog.csdn.net/Revivedsun/article/details/139391525