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)));
+        }
+    }
 }

Reply via email to