1 回答

TA貢獻1842條經驗 獲得超13個贊
這是因為 SqlStdOperatorTable.instance() 為注冊的函數做了一些初始化工作。因此,在 #register 之后調用它不會按預期工作。正確的方法是使用 ListSqlOperatorTable 并將其與帶有 ChainedSqlOperatorTable 的 StdSqlOperatorTable 鏈接起來,預置代碼可能如下所示:
ListSqlOperatorTable listOpTable = new ListSqlOperatorTable();
listOpTable.add(my_udf);
ChainedSqlOperatorTable chainedOpTable = ChainedSqlOperatorTable.of(listOpTable, SqlStdOperatorTable.instance());
// then use this chainedOpTable
// If you want to use a special dialect operators, you can code like this
SqlOperatorTable optable = SqlLibraryOperatorTableFactory.INSTANCE
? .getOperatorTable(SqlLibrary.STANDARD, SqlLibrary.POSTGRESQL);
我用以下方法解決了我的問題 -
// methods containing the udf logic?
public static class MyUdf1 {
? ? ? ? public Integer eval(String a) {
? ? ? ? ? ? return a.length();
? ? ? ? }
? ? }
@Test
? ? public void test1() throws SQLException, ClassNotFoundException {
? ? ? ? CalciteConnection connection = MyTests.getCalciteConnection();
? ? ? ? final String functionName = "STR_LEN";
? ? ? ? final ScalarFunction udfLengthFunction = ScalarFunctionImpl.create(Types.lookupMethod(MyUdf1.class, "eval", String.class));
? ? ? ? connection.getRootSchema().getSubSchema("SYSTEM").add(functionName, udfLengthFunction);
? ? ? ? FrameworkConfig frameworkConfig = Frameworks.newConfigBuilder()
? ? ? ? ? ? ? ? .parserConfig(SqlParser.Config.DEFAULT)
? ? ? ? ? ? ? ? .defaultSchema(connection.getRootSchema().getSubSchema("SYSTEM"))
? ? ? ? ? ? ? ? .programs(Programs.sequence(Programs.ofRules(Programs.RULE_SET), Programs.CALC_PROGRAM))
? ? ? ? ? ? ? ? .build();
? ? ? ? SqlIdentifier udfLengthIdentifier = new SqlIdentifier(Collections.singletonList(functionName), null, SqlParserPos.ZERO, null);
? ? ? ? final SqlOperator strLenOperator = new SqlUserDefinedFunction(udfLengthIdentifier, ReturnTypes.INTEGER, null, OperandTypes.STRING, null, udfLengthFunction);
? ? ? ? final RelBuilder builder = RelBuilder.create(frameworkConfig);
? ? ? ? RelNode udfRelNode = builder
? ? ? ? ? ? ? ? .scan("EMP")
? ? ? ? ? ? ? ? .project(builder.call(strLenOperator, builder.literal("SampleString")))
? ? ? ? ? ? ? ? .build();
? ? ? ? ResultSet set = RelRunners.run(udfRelNode).executeQuery();
? ? ? ? set.next();
? ? ? ? System.out.println(set.getString(1));
? ? }
添加回答
舉報