[
https://issues.apache.org/jira/browse/CALCITE-5229?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17579354#comment-17579354
]
Zhengqiang Duan commented on CALCITE-5229:
------------------------------------------
I found out that the type returned by the generated getElementType is based on
the rowType in the RelNode . If it is RelRocordType, then a new Synthetic type
is created.
{code:java}
@Override public Type getJavaClass(RelDataType type) {
if (type instanceof JavaType) {
JavaType javaType = (JavaType) type;
return javaType.getJavaClass();
}
if (type instanceof BasicSqlType || type instanceof IntervalSqlType) {
switch (type.getSqlTypeName()) {
case VARCHAR:
case CHAR:
return String.class;
case DATE:
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case INTEGER:
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
return type.isNullable() ? Integer.class : int.class;
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
case BIGINT:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
return type.isNullable() ? Long.class : long.class;
case SMALLINT:
return type.isNullable() ? Short.class : short.class;
case TINYINT:
return type.isNullable() ? Byte.class : byte.class;
case DECIMAL:
return BigDecimal.class;
case BOOLEAN:
return type.isNullable() ? Boolean.class : boolean.class;
case DOUBLE:
case FLOAT: // sic
return type.isNullable() ? Double.class : double.class;
case REAL:
return type.isNullable() ? Float.class : float.class;
case BINARY:
case VARBINARY:
return ByteString.class;
case GEOMETRY:
return Geometries.Geom.class;
case SYMBOL:
return Enum.class;
case ANY:
return Object.class;
case NULL:
return Void.class;
default:
break;
}
}
switch (type.getSqlTypeName()) {
case ROW:
assert type instanceof RelRecordType;
if (type instanceof JavaRecordType) {
return ((JavaRecordType) type).clazz;
} else {
return createSyntheticType((RelRecordType) type);
}
case MAP:
return Map.class;
case ARRAY:
case MULTISET:
return List.class;
default:
break;
}
return Object.class;
}
/** Creates a synthetic Java class whose fields have the same names and
* relational types. */
private Type createSyntheticType(RelRecordType type) {
final String name =
"Record" + type.getFieldCount() + "_" + syntheticTypes.size();
final SyntheticRecordType syntheticType =
new SyntheticRecordType(type, name);
for (final RelDataTypeField recordField : type.getFieldList()) {
final Type javaClass = getJavaClass(recordField.getType());
syntheticType.fields.add(
new RecordFieldImpl(
syntheticType,
recordField.getName(),
javaClass,
recordField.getType().isNullable()
&& !Primitive.is(javaClass),
Modifier.PUBLIC));
}
return register(syntheticType);
} {code}
In addition, the code generation getElementType is based on the physType type
of the parent node in the execution plan.
{code:java}
org/apache/calcite/adapter/enumerable/EnumerableRelImplementor.java:171
memberDeclarations.add(
Expressions.methodDecl(Modifier.PUBLIC, Class.class,
BuiltInMethod.TYPED_GET_ELEMENT_TYPE.method.getName(),
ImmutableList.of(),
Blocks.toFunctionBlock(
Expressions.return_(null,
Expressions.constant(result.physType.getJavaRowType())))));
{code}
So, we need to investigate why the rowType type in EnumerableLimit is not
Employee type.
> JdbcTest#testDynamicParameterInLimitOffset throws IllegalArgumentException
> --------------------------------------------------------------------------
>
> Key: CALCITE-5229
> URL: https://issues.apache.org/jira/browse/CALCITE-5229
> Project: Calcite
> Issue Type: Bug
> Components: core
> Affects Versions: 1.31.0
> Reporter: Benchao Li
> Assignee: Zhengqiang Duan
> Priority: Major
>
> After CALCITE-5201, this test will fail because we can transform more cases
> to semi join, and the physical type for some {{EnumerableRel}}s is wrong, we
> should fix them.
> See https://github.com/apache/calcite/pull/2848/files#r913566595
> {code:java}
> java.lang.IllegalArgumentException: Can not set int field Baz$Record5_1.empid
> to null value
> java.sql.SQLException: java.lang.IllegalArgumentException: Can not set int
> field Baz$Record5_1.empid to null value
> at
> org.apache.calcite.avatica.util.PositionedCursor$FieldGetter.getObject(PositionedCursor.java:132)
> at
> org.apache.calcite.avatica.util.AbstractCursor$AccessorImpl.getObject(AbstractCursor.java:357)
> at
> org.apache.calcite.avatica.util.AbstractCursor$AccessorImpl.getString(AbstractCursor.java:300)
> at
> org.apache.calcite.avatica.AvaticaResultSet.getString(AvaticaResultSet.java:241)
> at
> org.apache.calcite.test.CalciteAssert$ResultSetFormatter.rowToString(CalciteAssert.java:1986)
> at
> org.apache.calcite.test.CalciteAssert$ResultSetFormatter.resultSet(CalciteAssert.java:1972)
> at
> org.apache.calcite.test.CalciteAssert.lambda$checkResult$2(CalciteAssert.java:310)
> at
> org.apache.calcite.test.CalciteAssert.assertPrepare(CalciteAssert.java:631)
> at
> org.apache.calcite.test.CalciteAssert.access$700(CalciteAssert.java:149)
> at
> org.apache.calcite.test.CalciteAssert$AssertQuery.lambda$returns$1(CalciteAssert.java:1448)
> at
> org.apache.calcite.test.CalciteAssert$AssertQuery.withConnection(CalciteAssert.java:1384)
> at
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1443)
> at
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1433)
> at
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1396)
> at
> org.apache.calcite.test.JdbcTest.testDynamicParameterInLimitOffset(JdbcTest.java:5448){code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)