This is an automated email from the ASF dual-hosted git repository.

jhyde pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 2447a2d1cf [CALCITE-7073] If the Java return type of a UDF is 
ByteString, Calcite should deduce that the SQL type is VARBINARY
2447a2d1cf is described below

commit 2447a2d1cff183452422a0a33edb036be5c4d918
Author: Lucas Brenner <[email protected]>
AuthorDate: Wed Jun 25 16:13:59 2025 -0300

    [CALCITE-7073] If the Java return type of a UDF is ByteString, Calcite 
should deduce that the SQL type is VARBINARY
    
    Add UDF type-mapping from ByteString to VARBINARY.
    
    Close apache/calcite#4440
---
 .../sql/type/JavaToSqlTypeConversionRules.java     |  2 ++
 .../test/java/org/apache/calcite/test/UdfTest.java | 36 +++++++++++++++++++---
 .../main/java/org/apache/calcite/util/Smalls.java  | 15 +++++++++
 3 files changed, 48 insertions(+), 5 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/sql/type/JavaToSqlTypeConversionRules.java
 
b/core/src/main/java/org/apache/calcite/sql/type/JavaToSqlTypeConversionRules.java
index f1941b29fe..7b4b8a2a87 100644
--- 
a/core/src/main/java/org/apache/calcite/sql/type/JavaToSqlTypeConversionRules.java
+++ 
b/core/src/main/java/org/apache/calcite/sql/type/JavaToSqlTypeConversionRules.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.sql.type;
 
 import org.apache.calcite.avatica.util.ArrayImpl;
+import org.apache.calcite.avatica.util.ByteString;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -62,6 +63,7 @@ public class JavaToSqlTypeConversionRules {
           .put(boolean.class, SqlTypeName.BOOLEAN)
           .put(Boolean.class, SqlTypeName.BOOLEAN)
           .put(byte[].class, SqlTypeName.VARBINARY)
+          .put(ByteString.class, SqlTypeName.VARBINARY)
           .put(String.class, SqlTypeName.VARCHAR)
           .put(char[].class, SqlTypeName.VARCHAR)
           .put(Character.class, SqlTypeName.CHAR)
diff --git a/core/src/test/java/org/apache/calcite/test/UdfTest.java 
b/core/src/test/java/org/apache/calcite/test/UdfTest.java
index 674b1e6c2a..581364fdec 100644
--- a/core/src/test/java/org/apache/calcite/test/UdfTest.java
+++ b/core/src/test/java/org/apache/calcite/test/UdfTest.java
@@ -182,6 +182,12 @@ private CalciteAssert.AssertThat withUdf() {
         + Smalls.AllTypesFunction.class.getName()
         + "',\n"
         + "           methodName: '*'\n"
+        + "         },\n"
+        + "         {\n"
+        + "           name: 'UNBASE64',\n"
+        + "           className: '"
+        + Smalls.MyUnbase64Function.class.getName()
+        + "'\n"
         + "         }\n"
         + "       ]\n"
         + "     }\n"
@@ -728,7 +734,7 @@ private CalciteAssert.AssertThat withUdf() {
 
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-1434";>[CALCITE-1434]
-   * AggregateFunctionImpl doesnt work if the class implements a generic
+   * AggregateFunctionImpl doesn't work if the class implements a generic
    * interface</a>. */
   @Test void testUserDefinedAggregateFunctionImplementsInterface() {
     final String empDept = JdbcTest.EmpDeptTableFactory.class.getName();
@@ -1037,11 +1043,9 @@ private static CalciteAssert.AssertThat 
withBadUdf(Class<?> clazz) {
         .returnsValue("0");
   }
 
-  /**
-   * Test case for
+  /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-1834";>[CALCITE-1834]
-   * User-defined function for Arrays</a>.
-   */
+   * User-defined function for Arrays</a>. */
   @Test void testArrayUserDefinedFunction() throws Exception {
     try (Connection connection = DriverManager.getConnection("jdbc:calcite:")) 
{
       CalciteConnection calciteConnection =
@@ -1075,6 +1079,28 @@ private static CalciteAssert.AssertThat 
withBadUdf(Class<?> clazz) {
     }
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7073";>[CALCITE-7073]
+   * If the UDF's Java return type is ByteString, Calcite should deduce that 
the
+   * SQL type is VARBINARY</a>.
+   *
+   * <p>Tests that the {@code UNBASE64} user-defined function correctly decodes
+   * a Base64 string and its return type ({@code VARBINARY}, mapped from
+   * {@link org.apache.calcite.avatica.util.ByteString}) is fully compatible 
for
+   * direct comparison with SQL {@code VARBINARY} literals ({@code X'...'})
+   * within queries. */
+  @Test void testUnbase64DirectComparison() {
+    final String testHex = "74657374"; // "test" in bytes
+    final String testBase64 = "dGVzdA=="; // Base64 for "test"
+
+    final String sql = "values \"adhoc\".unbase64('" + testBase64 + "')";
+    withUdf().query(sql).typeIs("[EXPR$0 VARBINARY]");
+
+    final String sql2 = "select \"adhoc\".unbase64(cast('" + testBase64
+        + "' as varchar)) = x'" + testHex + "' as C\n";
+    withUdf().query(sql2).returns("C=true\n");
+  }
+
   /**
    * Base class for functions that append arrays.
    */
diff --git a/testkit/src/main/java/org/apache/calcite/util/Smalls.java 
b/testkit/src/main/java/org/apache/calcite/util/Smalls.java
index 963b11590f..3ffd3efda9 100644
--- a/testkit/src/main/java/org/apache/calcite/util/Smalls.java
+++ b/testkit/src/main/java/org/apache/calcite/util/Smalls.java
@@ -19,6 +19,7 @@
 import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
 import org.apache.calcite.adapter.java.AbstractQueryableTable;
+import org.apache.calcite.avatica.util.ByteString;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.BaseQueryable;
@@ -1477,4 +1478,18 @@ private Object[] convertRow(Object[] full) {
           BuiltInMethod.QUERYABLE_AS_ENUMERABLE.method);
     }
   }
+
+  /** User-defined function that decodes a Base64 string to bytes. */
+  public static class MyUnbase64Function {
+    public static ByteString eval(String s) {
+      if (s == null) {
+        return null;
+      }
+      try {
+        return ByteString.ofBase64(s);
+      } catch (Exception e) {
+        return null;
+      }
+    }
+  }
 }

Reply via email to