Regardless of which direction we go (allowing zero-field record types, or 
disallowing them), Konstantin has found a bug. Konstantin, can you log it, 
please.

On 2021/04/29 14:25:27, Konstantin Orlov <[email protected]> wrote: 
> 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
> 
> 
> 
> 
> 

Reply via email to