This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 95d92e85c08 IGNITE-24350 SQL Calcite: Forbid to register user defined
function with duplicated signature - Fixes #11837.
95d92e85c08 is described below
commit 95d92e85c08bb2b39bc422d64c46fc1535e2bf2b
Author: Vladimir Steshin <[email protected]>
AuthorDate: Fri Feb 14 21:45:36 2025 +0300
IGNITE-24350 SQL Calcite: Forbid to register user defined function with
duplicated signature - Fixes #11837.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../query/calcite/schema/IgniteSchema.java | 23 +++++++++++
.../UserDefinedFunctionsIntegrationTest.java | 44 ++++++++++++++++++++++
2 files changed, 67 insertions(+)
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 2e032f66067..6d22ac2d51d 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
@@ -18,16 +18,20 @@
package org.apache.ignite.internal.processors.query.calcite.schema;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
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.schema.Function;
+import org.apache.calcite.schema.FunctionParameter;
import org.apache.calcite.schema.SchemaPlus;
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.util.Commons;
/**
* Ignite schema.
@@ -90,6 +94,25 @@ 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);
+
+ if
(!p.getType(Commons.typeFactory()).equalsSansFieldNames(existingP.getType(Commons.typeFactory())))
+ break;
+ }
+
+ 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);
}
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 f46b0bb2f96..ac2e9acecc3 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
@@ -64,6 +64,35 @@ public class UserDefinedFunctionsIntegrationTest extends
AbstractBasicIntegratio
return cfg;
}
+ /** */
+ @Test
+ public void testSameSignatureNotRegistered() throws Exception {
+ LogListener logChecker = LogListener.matches("Unable to register
function 'SAMESIGN'. Other function " +
+ "with the same name and parameters is already registered").build();
+
+ listeningLog.registerListener(logChecker);
+
+ // Actually, we might use QuerySqlFunction#alias instead of declaring
additional method holding class (OtherFunctionsLibrary2).
+ // But Class#getDeclaredMethods() seems to give methods with a
different order. If we define methods with one class,
+ // we can get one 'sameSign' registered before another. And the test
would become flaky.
+ client.getOrCreateCache(new CacheConfiguration<Integer, Object>("emp")
+ .setSqlFunctionClasses(OtherFunctionsLibrary.class,
OtherFunctionsLibrary2.class));
+
+ // Ensure that 1::INTEGER isn't returned by
OtherFunctionsLibrary2#sameSign(int).
+ assertQuery("SELECT \"emp\".sameSign(1)").returns("echo_1").check();
+
+ // Ensure that OtherFunctionsLibrary#sameSign2(int) isn't registered.
+ assertThrows("SELECT \"emp\".sameSign2(1)",
SqlValidatorException.class,
+ "No match found for function signature SAMESIGN2");
+
+ assertTrue(logChecker.check(getTestTimeout()));
+
+ SchemaPlus schema =
queryProcessor(client).schemaHolder().schema("emp");
+
+ assertEquals(1, schema.getFunctions("SAMESIGN").size());
+ }
+
+
/** */
@Test
public void testSystemFunctionOverriding() throws Exception {
@@ -618,6 +647,21 @@ public class UserDefinedFunctionsIntegrationTest extends
AbstractBasicIntegratio
public static String echo(String s) {
return s;
}
+
+ /** The signature interferes with aliased {@link
OtherFunctionsLibrary2#sameSign2(int)}. */
+ @QuerySqlFunction
+ public static String sameSign(int v) {
+ return "echo_" + v;
+ }
+ }
+
+ /** */
+ public static class OtherFunctionsLibrary2 {
+ /** The aliased signature interferes with {@link
OtherFunctionsLibrary#sameSign(int)}. */
+ @QuerySqlFunction(alias = "sameSign")
+ public static int sameSign2(int v) {
+ return v;
+ }
}
/** */