[ https://issues.apache.org/jira/browse/CALCITE-1434?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Julian Hyde updated CALCITE-1434: --------------------------------- Description: {{AggregateFunctionImpl}} doesn't work if the class implements a generic interface. We have an interface like below which we want to expose to users for writing aggregate functions. {noformat} public interface UDAF<A, V, R> { A init(); A add(A aggregate, V val); R result(A aggregate); } {noformat} Internally we create an instance of {{AggregateFunctionImpl}} and register the Function in {{SchemaPlus}}. However this doesn't work for example if we have an implementation like below, {noformat} public class MySum implements UDAF<Number, Number, Number> { @Override public Number init() {...} @Override public Number add(Number aggregate, Number val) {...} @Override public Number result(Number aggregate) {...} } {noformat} We get an Exception "java.lang.RuntimeException: In user-defined aggregate class 'x.y.z.$MySum', first parameter to 'add' method must be the accumulator (the return type of the 'init' method)" This happens because the ReflectiveFunctionBase.findMethod is trying to look for a method name "init" and it get a method with a different signature (that returns Object) instead of the actual method defined in MySum. This happens to be a 'bridge' method inserted by java. In findMethod, the bridge methods can be skipped while looking for the method by name. was: We have an interface like below which we want to expose to users for writing aggregate functions. {noformat} public interface UDAF<A, V, R> { A init(); A add(A aggregate, V val); R result(A aggregate); } {noformat} Internally we create an instance of AggregateFunctionImpl and register the Function in SchemaPlus. However this doesn't work for example if we have an implementation like below, {noformat} public class MySum implements UDAF<Number, Number, Number> { @Override public Number init() {...} @Override public Number add(Number aggregate, Number val) {...} @Override public Number result(Number aggregate) {...} } {noformat} We get an Exception "java.lang.RuntimeException: In user-defined aggregate class 'x.y.z.$MySum', first parameter to 'add' method must be the accumulator (the return type of the 'init' method)" This happens because the ReflectiveFunctionBase.findMethod is trying to look for a method name "init" and it get a method with a different signature (that returns Object) instead of the actual method defined in MySum. This happens to be a 'bridge' method inserted by java. In findMethod, the bridge methods can be skipped while looking for the method by name. > User-defined aggregate function that uses a generic interface > ------------------------------------------------------------- > > Key: CALCITE-1434 > URL: https://issues.apache.org/jira/browse/CALCITE-1434 > Project: Calcite > Issue Type: Bug > Reporter: Arun Mahadevan > Assignee: Julian Hyde > Fix For: 1.11.0 > > > {{AggregateFunctionImpl}} doesn't work if the class implements a generic > interface. We have an interface like below which we want to expose to users > for writing aggregate functions. > {noformat} > public interface UDAF<A, V, R> { > A init(); > A add(A aggregate, V val); > R result(A aggregate); > } > {noformat} > Internally we create an instance of {{AggregateFunctionImpl}} and register > the Function in {{SchemaPlus}}. However this doesn't work for example if we > have an implementation like below, > {noformat} > public class MySum implements UDAF<Number, Number, Number> { > @Override > public Number init() {...} > @Override > public Number add(Number aggregate, Number val) {...} > @Override > public Number result(Number aggregate) {...} > } > {noformat} > We get an Exception "java.lang.RuntimeException: In user-defined aggregate > class 'x.y.z.$MySum', first parameter to 'add' method must be the accumulator > (the return type of the 'init' method)" > This happens because the ReflectiveFunctionBase.findMethod is trying to look > for a method name "init" and it get a method with a different signature (that > returns Object) instead of the actual method defined in MySum. This happens > to be a 'bridge' method inserted by java. > In findMethod, the bridge methods can be skipped while looking for the method > by name. -- This message was sent by Atlassian JIRA (v6.3.4#6332)