From my point of view any bug that is fixed is a step forward.

I am not sure there is any systematic plan to address this.

Mihai

________________________________
From: Chris Dennis <chris.w.den...@ibm.com.INVALID>
Sent: Wednesday, July 30, 2025 1:58 PM
To: dev@calcite.apache.org <dev@calcite.apache.org>
Subject: Re: Dynamic parameter typing & code generation

Putting this in context a little… I’m dealing with a NoSQL store with a native 
‘java.lang.Character’ type, that gets naturally mapped to CHAR(1). 
Unfortunately, this nuance of the EnumerableConvention behavior means prepared 
statements that interact with these columns behave differently depending on how 
much push-down is achieved on a query. The pushed-down query will have that 
value mapped into the native character type, whereas the enumerable code 
essentially treats the parameter as ‘dynamically typed’

Given that there may be bigger problems in this area would a PR to fix this 
class of CHAR(N) issues for dynamic parameters be welcomed, or would it be 
pushed out in the hopes of a more holistic approach in the future?

From: Mihai Budiu <mbu...@gmail.com>
Date: Wednesday, July 30, 2025 at 2:02 PM
To: dev@calcite.apache.org <dev@calcite.apache.org>
Subject: [EXTERNAL] Re: Dynamic parameter typing & code generation
I am not sure this is only a problem with dynamic parameters; I haven't noticed 
any code that enforces CHAR(N) limits at runtime, but maybe I haven't looked 
carefully enough. There are certainly known problems related to CHAR(N): 
https://issues.apache.org/jira/browse/CALCITE-4493

Mihai

________________________________
From: Chris Dennis <chris.w.den...@ibm.com.INVALID>
Sent: Tuesday, July 29, 2025 12:07 PM
To: dev@calcite.apache.org <dev@calcite.apache.org>
Subject: Dynamic parameter typing & code generation

I’m trying to figure out if the following test represents an error in the rel 
graph generation, the enumerable code generation, or just a grey area in the 
SQL spec/Calcite implementation:

  @Test void bindCharParameter() {
    final String sql = "select * from (values ('a'), ('b')) as tab (foo) where 
foo = ?";
    CalciteAssert.that()
        .query(sql)
        .convertMatches(root -> {
          RelNodes.findRex(root, RexUtil.find(SqlKind.EQUALS), null, (rel, rex) 
-> {
            ((RexCall) ((Filter) rel).getCondition()).getOperands().forEach(o 
-> {
              assertThat(o.getType().getPrecision(), is(1));
            });
          });
        })
        .consumesPreparedStatement(p -> {
          p.setString(1, "a");
        })
        .returnsUnordered("FOO=a")
        .consumesPreparedStatement(p -> {
          p.setString(1, "aa");
        })
        .returnsUnordered("");
  }

In the test above the Rel graph generated from the query types both the column 
‘foo’ and the RelDynamicParam as CHAR(1). The code generated by Calcite however 
treats the values passed through the prepared statement as simple Java Strings 
of arbitrary length. This means the second invocation returns no rows. Is this 
correct? Would it also be correct for an implementation of the query to 
truncate the value of the dynamic parameter to one character before performing 
the comparison, and thereby return a non-empty result set?

Thanks,

Chris

Reply via email to