/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.epl.expression;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.epl.core.StreamTypeService;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.spec.StatementSpecRaw;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Collection;
/**
* Represents a subselect in an expression tree.
*/
public abstract class ExprSubselectNode extends ExprNodeBase implements ExprEvaluator, ExprEvaluatorEnumeration
{
private static final long serialVersionUID = -2469169635913155764L;
private static final Log log = LogFactory.getLog(ExprSubselectNode.class);
/**
* The validated select clause.
*/
protected ExprNode[] selectClause;
protected transient ExprEvaluator[] selectClauseEvaluator;
protected String[] selectAsNames;
/**
* The validate filter expression.
*/
protected transient ExprEvaluator filterExpr;
/**
* The event type generated for wildcard selects.
*/
protected transient EventType rawEventType;
protected String statementName;
private transient StreamTypeService filterSubqueryStreamTypes;
private StatementSpecRaw statementSpecRaw;
private transient StatementSpecCompiled statementSpecCompiled;
private transient ExprSubselectStrategy strategy;
private transient boolean aggregatedSubquery;
protected int subselectNumber;
private boolean filterStreamSubselect;
/**
* Evaluate the lookup expression returning an evaluation result object.
* @param eventsPerStream is the events for each stream in a join
* @param isNewData is true for new data, or false for old data
* @param matchingEvents is filtered results from the table of stored lookup events
* @param exprEvaluatorContext context for expression evalauation
* @return evaluation result
*/
public abstract Object evaluate(EventBean[] eventsPerStream, boolean isNewData, Collection<EventBean> matchingEvents, ExprEvaluatorContext exprEvaluatorContext);
public abstract Collection<EventBean> evaluateGetCollEvents(EventBean[] eventsPerStream, boolean isNewData, Collection<EventBean> matchingEvents, ExprEvaluatorContext exprEvaluatorContext);
public abstract Collection evaluateGetCollScalar(EventBean[] eventsPerStream, boolean isNewData, Collection<EventBean> matchingEvents, ExprEvaluatorContext exprEvaluatorContext);
public abstract boolean isAllowMultiColumnSelect();
public abstract void validateSubquery(ExprValidationContext validationContext) throws ExprValidationException;
/**
* Ctor.
* @param statementSpec is the lookup statement spec from the parser, unvalidated
*/
public ExprSubselectNode(StatementSpecRaw statementSpec)
{
this.statementSpecRaw = statementSpec;
}
public ExprEvaluator getExprEvaluator()
{
return this;
}
public boolean isConstantResult()
{
return false;
}
public void validate(ExprValidationContext validationContext) throws ExprValidationException {
this.statementName = validationContext.getStatementName();
validateSubquery(validationContext);
}
/**
* Supplies a compiled statement spec.
* @param statementSpecCompiled compiled validated filters
*/
public void setStatementSpecCompiled(StatementSpecCompiled statementSpecCompiled, int subselectNumber)
{
this.statementSpecCompiled = statementSpecCompiled;
this.subselectNumber = subselectNumber;
}
/**
* Returns the compiled statement spec.
* @return compiled statement
*/
public StatementSpecCompiled getStatementSpecCompiled()
{
return statementSpecCompiled;
}
/**
* Sets the validate select clause
* @param selectClause is the expression representing the select clause
*/
public void setSelectClause(ExprNode[] selectClause)
{
this.selectClause = selectClause;
this.selectClauseEvaluator = ExprNodeUtility.getEvaluators(selectClause);
}
public Object evaluate(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
{
Collection<EventBean> matchingEvents = evaluateMatching(eventsPerStream, exprEvaluatorContext);
return evaluate(eventsPerStream, isNewData, matchingEvents, exprEvaluatorContext);
}
public Collection<EventBean> evaluateGetROCollectionEvents(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) {
Collection<EventBean> matchingEvents = evaluateMatching(eventsPerStream, exprEvaluatorContext);
return evaluateGetCollEvents(eventsPerStream, isNewData, matchingEvents, exprEvaluatorContext);
}
public Collection evaluateGetROCollectionScalar(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) {
Collection<EventBean> matchingEvents = evaluateMatching(eventsPerStream, exprEvaluatorContext);
return evaluateGetCollScalar(eventsPerStream, isNewData, matchingEvents, exprEvaluatorContext);
}
private Collection<EventBean> evaluateMatching(EventBean[] eventsPerStream, ExprEvaluatorContext exprEvaluatorContext) {
return strategy.evaluateMatching(eventsPerStream, exprEvaluatorContext);
}
/**
* Returns the uncompiled statement spec.
* @return statement spec uncompiled
*/
public StatementSpecRaw getStatementSpecRaw()
{
return statementSpecRaw;
}
/**
* Supplies the name of the select expression as-tag
* @param selectAsNames is the as-name(s)
*/
public void setSelectAsNames(String[] selectAsNames)
{
this.selectAsNames = selectAsNames;
}
/**
* Sets the validated filter expression, or null if there is none.
* @param filterExpr is the filter
*/
public void setFilterExpr(ExprEvaluator filterExpr)
{
this.filterExpr = filterExpr;
}
public String toExpressionString()
{
if ((selectAsNames != null) && (selectAsNames[0] != null))
{
return selectAsNames[0];
}
if (selectClause == null)
{
return "*";
}
return selectClause[0].toExpressionString();
}
public boolean equalsNode(ExprNode node)
{
return false; // 2 subselects are never equivalent
}
/**
* Sets the strategy for boiling down the table of lookup events into a subset against which to run the filter.
* @param strategy is the looking strategy (full table scan or indexed)
*/
public void setStrategy(ExprSubselectStrategy strategy)
{
this.strategy = strategy;
}
/**
* Sets the event type generated for wildcard selects.
* @param rawEventType is the wildcard type (parent view)
*/
public void setRawEventType(EventType rawEventType)
{
this.rawEventType = rawEventType;
}
/**
* Returns the select clause or null if none.
* @return clause
*/
public ExprNode[] getSelectClause()
{
return selectClause;
}
/**
* Returns filter expr or null if none.
* @return filter
*/
public ExprEvaluator getFilterExpr()
{
return filterExpr;
}
/**
* Returns the event type.
* @return type
*/
public EventType getRawEventType()
{
return rawEventType;
}
/**
* Return stream types.
* @return types
*/
public StreamTypeService getFilterSubqueryStreamTypes()
{
return filterSubqueryStreamTypes;
}
/**
* Set stream types.
* @param filterSubqueryStreamTypes types
*/
public void setFilterSubqueryStreamTypes(StreamTypeService filterSubqueryStreamTypes)
{
this.filterSubqueryStreamTypes = filterSubqueryStreamTypes;
}
public boolean isAggregatedSubquery() {
return aggregatedSubquery;
}
public void setAggregatedSubquery(boolean aggregatedSubquery) {
this.aggregatedSubquery = aggregatedSubquery;
}
public int getSubselectNumber() {
return subselectNumber;
}
public void setFilterStreamSubselect(boolean filterStreamSubselect) {
this.filterStreamSubselect = filterStreamSubselect;
}
public boolean isFilterStreamSubselect() {
return filterStreamSubselect;
}
}