Hi all.
I faced a problem preventing certain queries being planned because
RelFieldTrimmer throws
an ArrayIndexOutOfBoundsException with message "Index -1 out of bounds for
length 0”.
The problem is here [1]:
// If they are asking for no fields, we can't give them what they want,
// because zero-column records are illegal. Give them the last field,
// which is unlikely to be a system field.
if (fieldsUsed.isEmpty()) {
fieldsUsed = ImmutableBitSet.range(fieldCount - 1, fieldCount);
}
In case fieldsUsed.isEmpty we returns last field, but it is currently possible
that fieldCount=0 as well.
After some investigation I find out that the reason is empty record derived as
row type for Aggregate.
It is possible when an aggregate has an empty group key and no aggregate calls.
So the question is whether an empty record is a legal row type for an
aggregation node?
Below is a reproducer for this problem, just put it at RelFieldTrimmerTest:
@Test void test() {
class ContextImpl implements Context {
final Object target;
ContextImpl(Object target) {
this.target = Objects.requireNonNull(target, "target");
}
@Override public <T extends Object> @Nullable T unwrap(Class<T> clazz) {
if (clazz.isInstance(target)) {
return clazz.cast(target);
}
return null;
}
}
// RelBuilder hides problem when simplifyValues=true, hence we need to
disable it
final RelBuilder builder = RelBuilder.create(config()
.context(new
ContextImpl(RelBuilder.Config.DEFAULT.withSimplifyValues(false))).build());
final RelNode root =
builder.scan("EMP")
.aggregate(builder.groupKey())
.filter(builder.literal(false))
.project(builder.literal(42))
.build();
final RelFieldTrimmer fieldTrimmer = new RelFieldTrimmer(null, builder);
fieldTrimmer.trim(root); // fails with ArrayIndexOutOfBoundsException:
Index -1 out of bounds for length 0
}
[1]
https://github.com/apache/calcite/blob/master/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java#L1197
--
Regards,
Konstantin Orlov