espertechinc / esper

Esper Complex Event Processing, Streaming SQL and Event Series Analysis
GNU General Public License v2.0
839 stars 259 forks source link

failed to compile chain invocation of mapped event property #274

Closed kaicao closed 6 months ago

kaicao commented 1 year ago

Example which works for 8.5.0 but not for 8.9.0 is Event class like:

import java.util.Map;

public class EsperTestEvent {

  private Map<String, String> properties;

  public String getProperty(String key) {
    return properties.get(key);
  }

  public Map<String, String> getProperties() {
    return properties;
  }

  public EsperTestEvent setProperties(Map<String, String> properties) {
    this.properties = properties;
    return this;
  }
}

Statement like:

 "SELECT event\n" +
            "FROM EsperTestEvent(\n" +
            "   property(\"key1\").toString().length() > 2\n" +
            ").win:time(60 MINUTES) event\n" +
            "\n" +
            "GROUP BY event.property(\"key1\")\n" +
            "HAVING COUNT(DISTINCT event.property(\"key1\")) > 1\n" +
            "OUTPUT SNAPSHOT EVERY 60 MINUTES"

So the statement is using the getProperty method from EsperTestEvent. The statement was able to compile with 8.5.0, but when upgrading to 8.9.0 it failed with:

Caused by: com.espertech.esper.compiler.client.EPCompileExceptionItem: Unexpected error compiling statement: java.lang.IllegalArgumentException:Not available for null clazz
    at com.espertech.esper.compiler.internal.util.CompilerHelperModuleProvider.compileToBytes(CompilerHelperModuleProvider.java:148)
    ... 76 more
Caused by: com.espertech.esper.common.internal.compile.stage2.StatementSpecCompileException: Unexpected error compiling statement: java.lang.IllegalArgumentException:Not available for null clazz
    at com.espertech.esper.common.internal.compile.stage2.StatementRawCompiler.compile(StatementRawCompiler.java:179)
    at com.espertech.esper.compiler.internal.util.CompilerHelperStatementProvider.compileItem(CompilerHelperStatementProvider.java:162)
    at com.espertech.esper.compiler.internal.util.CompilerHelperModuleProvider.compileToBytes(CompilerHelperModuleProvider.java:128)
    ... 76 more
Caused by: java.lang.IllegalArgumentException: Not available for null clazz
    at com.espertech.esper.common.client.type.EPTypePremade.getOrCreate(EPTypePremade.java:676)
    at com.espertech.esper.common.internal.rettype.EPChainableTypeClass.<init>(EPChainableTypeClass.java:31)
    at com.espertech.esper.common.internal.epl.expression.dot.core.ExprDotNodeImpl.handlePropertyInfoPair(ExprDotNodeImpl.java:456)
    at com.espertech.esper.common.internal.epl.expression.dot.core.ExprDotNodeImpl.validate(ExprDotNodeImpl.java:313)
    at com.espertech.esper.common.internal.epl.expression.core.ExprNodeUtilityValidate.getValidatedSubtreeInternal(ExprNodeUtilityValidate.java:297)
    at com.espertech.esper.common.internal.epl.expression.core.ExprNodeUtilityValidate.getValidatedSubtreeInternal(ExprNodeUtilityValidate.java:292)
    at com.espertech.esper.common.internal.epl.expression.core.ExprNodeUtilityValidate.getValidatedSubtree(ExprNodeUtilityValidate.java:156)
    at com.espertech.esper.common.internal.compile.stage2.FilterSpecCompiler.validateAllowSubquery(FilterSpecCompiler.java:150)
    at com.espertech.esper.common.internal.compile.stage2.FilterSpecCompiler.makeFilterSpec(FilterSpecCompiler.java:58)
    at com.espertech.esper.common.internal.compile.stage2.StreamSpecCompiler.compileFilter(StreamSpecCompiler.java:129)
    at com.espertech.esper.common.internal.compile.stage2.StreamSpecCompiler.compile(StreamSpecCompiler.java:79)
    at com.espertech.esper.common.internal.compile.stage2.StatementRawCompiler.compile(StatementRawCompiler.java:164)
    ... 78 more

And by checking the failure occurred for the

property("key1").toString().length() > 2

Besides I tried to change property("key1").toString() to getProperty("key1").toString() but that failed compilation with error like

Failed to resolve 'getProperty.toString' to a property, single-row function, aggregation function, script, stream or class name
kaicao commented 1 year ago

I did some digging to understand what might be going on here that ends up with null clazz exception. The EPTypePremade#getOrCreate throws out due to the input argument clazz is null. The input argument clazz was supplied from ExprDotNodeImpl#handlePropertyInfoPair (line 456) by desc.getPropertyComponentType.

The method javadoc for desc.getPropertyComponentType said:

     * Returns the component type, if applicable.
     * This is applicable only to arrays and collections, queues and iterators.
     * Returns null if not applicable.

Since the EsperTestEvent#getProperty return single String instead of arrays or collections, queues, iterators that is expected by desc.getPropertyComponentType, that ends up getting null.

How to make it possible to let Esper detect the type of single return value like for EsperTestEvent#getProperty in order to avoid such null clazz error?

Thank you!