Okay… so more digging in this area throws up some more weirdness. Executing the 
following query (via prepared statement):

INSERT INTO “foo” (KEY, "cell") values (?, ?)

where:
TABLE_NAME=foo; COLUMN_NAME=KEY; DATA_TYPE=-5; TYPE_NAME=JavaType(long) NOT 
NULL;
TABLE_NAME=foo; COLUMN_NAME=cell; DATA_TYPE=-3; TYPE_NAME=JavaType(class [B);

seems to be impossible. Avatica wants to be passed a byte[] through setObject 
or setBytes… which it hard casts and then wraps in a ByteString. The type 
inference in Calcite infers the type that ultimately propagates in to the 
EnumerableCalc as byte[] though so generates an cast of the ByteString back to 
a byte[].

java.lang.ClassCastException: class org.apache.calcite.avatica.util.ByteString 
cannot be cast to class [B (org.apache.calcite.avatica.util.ByteString is in 
unnamed module of loader 'app'; [B is in module java.base of loader 'bootstrap')
     at Baz$2.apply(Unknown Source)
     at 
org.apache.calcite.linq4j.EnumerableDefaults.longCount(EnumerableDefaults.java:2373)
     at 
org.apache.calcite.linq4j.EnumerableDefaults.count(EnumerableDefaults.java:397)
     at 
org.apache.calcite.linq4j.DefaultEnumerable.count(DefaultEnumerable.java:187)
     at Baz.bind(Unknown Source)
     at 
org.apache.calcite.jdbc.CalcitePrepare$CalciteSignature.enumerable(CalcitePrepare.java:363)
     at 
org.apache.calcite.jdbc.CalciteConnectionImpl.enumerable(CalciteConnectionImpl.java:325)
     at 
org.apache.calcite.jdbc.CalciteMetaImpl._createIterable(CalciteMetaImpl.java:585)
     at 
org.apache.calcite.jdbc.CalciteMetaImpl.execute(CalciteMetaImpl.java:715)
     at 
org.apache.calcite.avatica.AvaticaConnection.executeQueryInternal(AvaticaConnection.java:551)

Unfortunately there are just too many places this could be “fixed” and I lack 
the necessary context to know if I’m using something wrong or if a fix is 
needed, and if so which layer of code is dropping the ball.

Thanks,

Chris
From: Chris Dennis <chris.w.den...@ibm.com.INVALID>
Date: Friday, March 21, 2025 at 4:13 PM
To: dev@calcite.apache.org <dev@calcite.apache.org>
Subject: [EXTERNAL] Type Discrepancies between PreparedStatement, and row 
RelDataType
Hi All,

Trying to figure out what’s amiss in my Calcite based driver and whether there 
are bugs in this area in Avatica/Calcite or if I’m using something wrong.

I have a table in a database that reports its columns as: JavaType(long) NOT 
NULL (BIGINT), JavaType(class java.lang.Character) (CHAR)

I then build a prepared statement against the same connection: INSERT INTO foo 
(KEY, \"character\") values (?, ?)
The parameter metadata reports the parameter types as: java.lang.Object 
(BIGINT). java.lang.Object (CHAR)
The Enumerable node that is input to my adapters part of the graph reports its 
row type as: RecordType(JavaType(class java.lang.Long) KEY, JavaType(class 
java.lang.Character) character)

At code generation I’m then presented with a field that claims it’s a 
java.lang.Character, but at runtime I get a ClassCastException because 
arbitrary java types (notably Strings) are getting all the way through from the 
JDBC PreparedStatement unmodified. My understanding of the JDBC spec says that 
the parameter values should get converted, at but it’s not clear to me who’s 
responsibility that is.

Anyone have any thoughts on where I should look first?

Thanks,

Chris

Reply via email to