Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-3394

Can not register implementation of a UDF with RexImpTable and use the same with RelBuilder

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Not A Problem
    • 1.21.0
    • 1.22.0
    • core
    • None

    Description

      I am trying to register a simple UDF that returns the length of input string. I can do this with prepareStatement approach -

      public static class MyUdf1 {
         public Integer eval(String a) {
            return a.length();
         }
      }
      
      public void testUDF() {
      final String strLenSql = "select STRLEN('SampleString') from emp";
      ScalarFunction strLenFunction = ScalarFunctionImpl.create(MyUdf1.class, "eval");
      calciteConnection.getRootSchema().add("STRLEN", strLenFunction);
      
      ResultSet resultSet = calciteConnection.prepareStatement(strLenSql).executeQuery();
      resultSet.next();
      System.out.println(resultSet.getString(1));
      }
      
      

       

      When I try the similar steps with RelBuilder, I can successfully register the SqlOperator; but am unable to refer to the implementation of this operator. The builder refers to RexImpTable's maps for the function table implementation and there is no public/protected api exposed for these maps. 

      SqlFunction length = new SqlFunction("STRLEN",
            SqlKind.OTHER_FUNCTION,
            ReturnTypes.INTEGER,
            null,
            OperandTypes.STRING,
            SqlFunctionCategory.USER_DEFINED_FUNCTION);
      
      SqlStdOperatorTable sqlStdOperatorTable = SqlStdOperatorTable.instance();
      sqlStdOperatorTable.register(length);
      
      FrameworkConfig frameworkConfig = Frameworks.newConfigBuilder()
            .parserConfig(SqlParser.Config.DEFAULT)
            .defaultSchema(connection.getRootSchema().getSubSchema("SYSTEM"))
            .programs(Programs.sequence(Programs.ofRules(Programs.RULE_SET), Programs.CALC_PROGRAM))
            .operatorTable(sqlStdOperatorTable)
            .build();
      
      final RelBuilder builder = RelBuilder.create(frameworkConfig);
      RelNode udfRelNode = builder
            .scan("EMP")
            .project(builder.call(length,builder.literal("SampleString")))
            .build();
      
      ResultSet resultSet = RelRunners.run(udfRelNode).executeQuery();
      

       

      This code throws exception - 

      Caused by: java.lang.RuntimeException: cannot translate call STRLEN($t3)Caused by: java.lang.RuntimeException: cannot translate call STRLEN($t3) at org.apache.calcite.adapter.enumerable.RexToLixTranslator.translateCall(RexToLixTranslator.java:756) at org.apache.calcite.adapter.enumerable.RexToLixTranslator.translate0(RexToLixTranslator.java:730) at org.apache.calcite.adapter.enumerable.RexToLixTranslator.translate(RexToLixTranslator.java:199) at org.apache.calcite.adapter.enumerable.RexToLixTranslator.translate0(RexToLixTranslator.java:684)
      

      There are no junits that show this working with RelBuilder. Is it possible currently to register and use the udfs with RelBuilder?

      Attachments

        Activity

          People

            Unassigned Unassigned
            vaishnavee Vaishnavee Kulkarni
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: