Образцы UOT-юнитов OOTB (UdfTest.java) используют фиктивную схему jdbc и не показывают использование RelBuilder API.
Я работаю над регистрацией простого UDF, который возвращает длину входной строки. Я создал SqlFunction и зарегистрировал то же самое в SqlStdOperatorTable -
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 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();
Теперь я могу использовать предопределенные функции sql, такие как substr
, определенный в классе SqlStringLengthFunction, со следующей частью-
RelNode udfRelNode = builder
.scan("EMP")
.project(builder.call(new SqlStringLengthFunction(),builder.literal("SampleString"), builder.literal(3))
.build();
PreparedStatement statement = RelRunners.run(udfRelNode);
ResultSet resultSet = statement.executeQuery();
, но когда я пытаюсь использовать вышеуказанную функцию 'length' в builder.call, он выдает исключение -
java.lang.RuntimeException: cannot translate call STRLEN($t3)
builder извлекает реализацию этих функций из приватной карты класса RexImpTable
. В этом классе нет открытых / защищенных apis для добавления значений к этой карте.
Подскажите, пожалуйста, как зарегистрировать любой UDF в Calcite и использовать его в RelBuilder?