This is an automated email from the ASF dual-hosted git repository. tkalkirill pushed a commit to branch ignite-29033 in repository https://gitbox.apache.org/repos/asf/ignite.git
commit 620a05013d14f8d4baa227067e41cb4584b0f990 Author: Kirill Tkalenko <[email protected]> AuthorDate: Wed Sep 2 15:30:04 2026 +0300 IGNITE-29033 Wip --- .../query/calcite/schema/IgniteSchema.java | 42 ++++++++----- .../UserDefinedFunctionsIntegrationTest.java | 72 ++++++++++++++++++++++ 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteSchema.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteSchema.java index 6d22ac2d51d..73faebcd9fb 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteSchema.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteSchema.java @@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; +import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.schema.Function; import org.apache.calcite.schema.FunctionParameter; import org.apache.calcite.schema.SchemaPlus; @@ -31,6 +32,7 @@ import org.apache.calcite.schema.Table; import org.apache.calcite.schema.impl.AbstractSchema; import org.apache.calcite.tools.FrameworkConfig; import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; import org.apache.ignite.internal.processors.query.calcite.util.Commons; /** @@ -94,23 +96,13 @@ public class IgniteSchema extends AbstractSchema { * @param func SQL function. */ public void addFunction(String name, Function func) { - for (Function existingFun : getFunctions(name)) { - List<FunctionParameter> params = func.getParameters(); - List<FunctionParameter> existingParams = existingFun.getParameters(); - - if (params.size() != existingParams.size()) - continue; - - for (int i = 0; i < params.size(); ++i) { - FunctionParameter p = params.get(i); - FunctionParameter existingP = existingParams.get(i); + IgniteTypeFactory typeFactory = Commons.typeFactory(); - if (!p.getType(Commons.typeFactory()).equalsSansFieldNames(existingP.getType(Commons.typeFactory()))) - break; + for (Function existingFun : getFunctions(name)) { + if (sameParameters(func.getParameters(), existingFun.getParameters(), typeFactory)) { + throw new IgniteException("Unable to register function '" + name + "'. Other function with the same " + + "name and parameters is already registered in schema '" + schemaName + "'."); } - - throw new IgniteException("Unable to register function '" + name + "'. Other function with the same " + - "name and parameters is already registered in schema '" + schemaName + "'."); } funcMap.put(name, func); @@ -145,4 +137,24 @@ public class IgniteSchema extends AbstractSchema { return newSchema; } + + /** */ + private static boolean sameParameters( + List<FunctionParameter> params, + List<FunctionParameter> existingParams, + IgniteTypeFactory typeFactory + ) { + if (params.size() != existingParams.size()) + return false; + + for (int i = 0; i < params.size(); ++i) { + RelDataType paramType = typeFactory.toSql(params.get(i).getType(typeFactory)); + RelDataType existingParamType = typeFactory.toSql(existingParams.get(i).getType(typeFactory)); + + if (!paramType.equalsSansFieldNamesAndNullability(existingParamType)) + return false; + } + + return true; + } } diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java index 569420c7401..dc1ca87526a 100644 --- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java +++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java @@ -94,6 +94,27 @@ public class UserDefinedFunctionsIntegrationTest extends AbstractBasicIntegratio assertEquals(1, schema.getFunctions("SAMESIGN").size()); } + /** */ + @Test + public void testOverloadedFunctions() { + client.getOrCreateCache(new CacheConfiguration<Integer, Object>("overloaded-functions") + .setSqlSchema("UDF") + .setSqlFunctionClasses(OverloadedFunctionsLibrary.class)); + + SchemaPlus schema = queryProcessor(client).schemaHolder().schema("UDF"); + + assertEquals(2, schema.getFunctions("OVERLOADED").size()); + assertEquals(2, schema.getFunctions("OVERLOADED_TABLE").size()); + assertEquals(1, schema.getFunctions("SQL_EQUIVALENT").size()); + assertEquals(1, schema.getFunctions("SQL_EQUIVALENT_TABLE").size()); + + assertQuery("SELECT UDF.OVERLOADED(1, 'a')").returns("1a").check(); + assertQuery("SELECT UDF.OVERLOADED('a', 1)").returns("a1").check(); + + assertQuery("SELECT * FROM TABLE(UDF.OVERLOADED_TABLE(1, 'a'))").returns("1a").check(); + assertQuery("SELECT * FROM TABLE(UDF.OVERLOADED_TABLE('a', 1))").returns("a1").check(); + } + /** */ @Test public void testSystemFunctionOverriding() throws Exception { @@ -829,4 +850,55 @@ public class UserDefinedFunctionsIntegrationTest extends AbstractBasicIntegratio return "CustomClass.toString"; } } + + /** */ + public static class OverloadedFunctionsLibrary { + /** */ + @QuerySqlFunction + public static String overloaded(int i, String s) { + return i + s; + } + + /** */ + @QuerySqlFunction + public static String overloaded(String s, int i) { + return s + i; + } + + /** */ + @QuerySqlFunction(alias = "SQL_EQUIVALENT") + public static String sqlEquivalent(int i) { + return String.valueOf(i); + } + + /** */ + @QuerySqlFunction(alias = "SQL_EQUIVALENT") + public static String sqlEquivalent(Integer i) { + return String.valueOf(i); + } + + /** */ + @QuerySqlTableFunction(alias = "OVERLOADED_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"}) + public static Iterable<Collection<?>> overloadedTable(int i, String s) { + return List.of(List.of(i + s)); + } + + /** */ + @QuerySqlTableFunction(alias = "OVERLOADED_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"}) + public static Iterable<Collection<?>> overloadedTable(String s, int i) { + return List.of(List.of(s + i)); + } + + /** */ + @QuerySqlTableFunction(alias = "SQL_EQUIVALENT_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"}) + public static Iterable<Collection<?>> sqlEquivalentTable(int i) { + return List.of(List.of(String.valueOf(i))); + } + + /** */ + @QuerySqlTableFunction(alias = "SQL_EQUIVALENT_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"}) + public static Iterable<Collection<?>> sqlEquivalentTable(Integer i) { + return List.of(List.of(String.valueOf(i))); + } + } }
