/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.core.start;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactorySelectResult;
import com.espertech.esper.core.context.factory.StatementAgentInstancePreload;
import com.espertech.esper.core.context.mgr.ContextManagedStatementSelectDesc;
import com.espertech.esper.core.context.stmt.*;
import com.espertech.esper.core.context.subselect.SubSelectStrategyFactoryDesc;
import com.espertech.esper.core.context.subselect.SubSelectStrategyHolder;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.core.context.util.ContextMergeView;
import com.espertech.esper.core.context.util.StatementAgentInstanceUtil;
import com.espertech.esper.core.service.EPServicesContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.core.service.resource.StatementResourceHolder;
import com.espertech.esper.epl.agg.service.AggregationService;
import com.espertech.esper.epl.expression.core.ExprNodeUtility;
import com.espertech.esper.epl.expression.core.ExprValidationException;
import com.espertech.esper.epl.expression.prev.ExprPreviousEvalStrategy;
import com.espertech.esper.epl.expression.prev.ExprPreviousMatchRecognizeNode;
import com.espertech.esper.epl.expression.prev.ExprPreviousNode;
import com.espertech.esper.epl.expression.prior.ExprPriorEvalStrategy;
import com.espertech.esper.epl.expression.prior.ExprPriorNode;
import com.espertech.esper.epl.expression.subquery.ExprSubselectNode;
import com.espertech.esper.epl.expression.table.ExprTableAccessEvalStrategy;
import com.espertech.esper.epl.expression.table.ExprTableAccessNode;
import com.espertech.esper.epl.spec.IntoTableSpec;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.rowregex.EventRowRegexHelper;
import com.espertech.esper.rowregex.EventRowRegexNFAViewService;
import com.espertech.esper.rowregex.RegexExprPreviousEvalStrategy;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.ViewProcessingException;
import com.espertech.esper.view.Viewable;
import java.util.*;
/**
* Starts and provides the stop method for EPL statements.
*/
public class EPStatementStartMethodSelect extends EPStatementStartMethodBase {
public EPStatementStartMethodSelect(StatementSpecCompiled statementSpec) {
super(statementSpec);
}
public EPStatementStartResult startInternal(final EPServicesContext services, final StatementContext statementContext, boolean isNewStatement, boolean isRecoveringStatement, boolean isRecoveringResilient) throws ExprValidationException, ViewProcessingException {
// validate use of table: may not both read and write
validateTableAccessUse(statementSpec.getIntoTableSpec(), statementSpec.getTableNodes());
final String contextName = statementSpec.getOptionalContextName();
AgentInstanceContext defaultAgentInstanceContext = getDefaultAgentInstanceContext(statementContext);
EPStatementStartMethodSelectDesc selectDesc = EPStatementStartMethodSelectUtil.prepare(statementSpec, services, statementContext, isRecoveringResilient, defaultAgentInstanceContext, isQueryPlanLogging(services), null, null, null);
statementContext.setStatementAgentInstanceFactory(selectDesc.getStatementAgentInstanceFactorySelect());
// allow extension to walk
statementContext.getStatementExtensionServicesContext().preStartWalk(selectDesc);
// Determine context
EPStatementStopMethod stopStatementMethod;
Viewable finalViewable;
AggregationService aggregationService;
Map<ExprSubselectNode, SubSelectStrategyHolder> subselectStrategyInstances;
Map<ExprPriorNode, ExprPriorEvalStrategy> priorStrategyInstances;
Map<ExprPreviousNode, ExprPreviousEvalStrategy> previousStrategyInstances;
Map<ExprTableAccessNode, ExprTableAccessEvalStrategy> tableAccessStrategyInstances;
List<StatementAgentInstancePreload> preloadList = Collections.emptyList();
RegexExprPreviousEvalStrategy matchRecognizePrevEvalStrategy;
// With context - delegate instantiation to context
if (statementSpec.getOptionalContextName() != null) {
// use statement-wide agent-instance-specific aggregation service
aggregationService = statementContext.getStatementAgentInstanceRegistry().getAgentInstanceAggregationService();
// use statement-wide agent-instance-specific subselects
AIRegistryExpr aiRegistryExpr = statementContext.getStatementAgentInstanceRegistry().getAgentInstanceExprService();
subselectStrategyInstances = new HashMap<ExprSubselectNode, SubSelectStrategyHolder>();
for (Map.Entry<ExprSubselectNode, SubSelectStrategyFactoryDesc> entry : selectDesc.getSubSelectStrategyCollection().getSubqueries().entrySet()) {
AIRegistrySubselect specificService = aiRegistryExpr.allocateSubselect(entry.getKey());
entry.getKey().setStrategy(specificService);
Map<ExprPriorNode, ExprPriorEvalStrategy> subselectPriorStrategies = new HashMap<ExprPriorNode, ExprPriorEvalStrategy>();
for (ExprPriorNode subselectPrior : entry.getValue().getPriorNodesList()) {
AIRegistryPrior specificSubselectPriorService = aiRegistryExpr.allocatePrior(subselectPrior);
subselectPriorStrategies.put(subselectPrior, specificSubselectPriorService);
}
Map<ExprPreviousNode, ExprPreviousEvalStrategy> subselectPreviousStrategies = new HashMap<ExprPreviousNode, ExprPreviousEvalStrategy>();
for (ExprPreviousNode subselectPrevious : entry.getValue().getPrevNodesList()) {
AIRegistryPrevious specificSubselectPreviousService = aiRegistryExpr.allocatePrevious(subselectPrevious);
subselectPreviousStrategies.put(subselectPrevious, specificSubselectPreviousService);
}
AIRegistryAggregation subselectAggregation = aiRegistryExpr.allocateSubselectAggregation(entry.getKey());
SubSelectStrategyHolder strategyHolder = new SubSelectStrategyHolder(specificService, subselectAggregation, subselectPriorStrategies, subselectPreviousStrategies, null, null, null);
subselectStrategyInstances.put(entry.getKey(), strategyHolder);
}
// use statement-wide agent-instance-specific "prior"
priorStrategyInstances = new HashMap<ExprPriorNode, ExprPriorEvalStrategy>();
for (ExprPriorNode priorNode : selectDesc.getViewResourceDelegateUnverified().getPriorRequests()) {
AIRegistryPrior specificService = aiRegistryExpr.allocatePrior(priorNode);
priorStrategyInstances.put(priorNode, specificService);
}
// use statement-wide agent-instance-specific "previous"
previousStrategyInstances = new HashMap<ExprPreviousNode, ExprPreviousEvalStrategy>();
for (ExprPreviousNode previousNode : selectDesc.getViewResourceDelegateUnverified().getPreviousRequests()) {
AIRegistryPrevious specificService = aiRegistryExpr.allocatePrevious(previousNode);
previousStrategyInstances.put(previousNode, specificService);
}
// use statement-wide agent-instance-specific match-recognize "previous"
matchRecognizePrevEvalStrategy = aiRegistryExpr.allocateMatchRecognizePrevious();
// use statement-wide agent-instance-specific tables
tableAccessStrategyInstances = new HashMap<ExprTableAccessNode, ExprTableAccessEvalStrategy>();
if (statementSpec.getTableNodes() != null) {
for (ExprTableAccessNode tableNode : statementSpec.getTableNodes()) {
AIRegistryTableAccess specificService = aiRegistryExpr.allocateTableAccess(tableNode);
tableAccessStrategyInstances.put(tableNode, specificService);
}
}
ContextMergeView mergeView = new ContextMergeView(selectDesc.getResultSetProcessorPrototypeDesc().getResultSetProcessorFactory().getResultEventType());
finalViewable = mergeView;
ContextManagedStatementSelectDesc statement = new ContextManagedStatementSelectDesc(statementSpec, statementContext, mergeView, selectDesc.getStatementAgentInstanceFactorySelect(),
selectDesc.getResultSetProcessorPrototypeDesc().getAggregationServiceFactoryDesc().getExpressions(),
selectDesc.getSubSelectStrategyCollection());
services.getContextManagementService().addStatement(contextName, statement, isRecoveringResilient);
final EPStatementStopMethod selectStop = selectDesc.getStopMethod();
stopStatementMethod = new EPStatementStopMethod() {
public void stop() {
services.getContextManagementService().stoppedStatement(contextName, statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getExpression(), statementContext.getExceptionHandlingService());
selectStop.stop();
}
};
selectDesc.getDestroyCallbacks().addCallback(new EPStatementDestroyCallbackContext(services.getContextManagementService(), contextName, statementContext.getStatementName(), statementContext.getStatementId()));
} else {
// Without context - start here
StatementAgentInstanceFactorySelectResult resultOfStart = (StatementAgentInstanceFactorySelectResult) selectDesc.getStatementAgentInstanceFactorySelect().newContext(defaultAgentInstanceContext, isRecoveringResilient);
finalViewable = resultOfStart.getFinalView();
final StopCallback startResultStop = services.getEpStatementFactory().makeStopMethod(resultOfStart);
final EPStatementStopMethod selectStop = selectDesc.getStopMethod();
stopStatementMethod = new EPStatementStopMethod() {
public void stop() {
StatementAgentInstanceUtil.stopSafe(startResultStop, statementContext);
selectStop.stop();
}
};
aggregationService = resultOfStart.getOptionalAggegationService();
subselectStrategyInstances = resultOfStart.getSubselectStrategies();
priorStrategyInstances = resultOfStart.getPriorNodeStrategies();
previousStrategyInstances = resultOfStart.getPreviousNodeStrategies();
tableAccessStrategyInstances = resultOfStart.getTableAccessEvalStrategies();
preloadList = resultOfStart.getPreloadList();
matchRecognizePrevEvalStrategy = null;
if (resultOfStart.getTopViews().length > 0) {
EventRowRegexNFAViewService matchRecognize = EventRowRegexHelper.recursiveFindRegexService(resultOfStart.getTopViews()[0]);
if (matchRecognize != null) {
matchRecognizePrevEvalStrategy = matchRecognize.getPreviousEvaluationStrategy();
}
}
if (statementContext.getStatementExtensionServicesContext() != null && statementContext.getStatementExtensionServicesContext().getStmtResources() != null) {
StatementResourceHolder holder = statementContext.getStatementExtensionServicesContext().extractStatementResourceHolder(resultOfStart);
statementContext.getStatementExtensionServicesContext().getStmtResources().setUnpartitioned(holder);
statementContext.getStatementExtensionServicesContext().postProcessStart(resultOfStart, isRecoveringResilient);
}
}
Set<ExprPreviousMatchRecognizeNode> matchRecognizeNodes = selectDesc.getStatementAgentInstanceFactorySelect().getViewResourceDelegate().getPerStream()[0].getMatchRecognizePreviousRequests();
// assign strategies to expression nodes
EPStatementStartMethodHelperAssignExpr.assignExpressionStrategies(selectDesc, aggregationService, subselectStrategyInstances, priorStrategyInstances, previousStrategyInstances, matchRecognizeNodes, matchRecognizePrevEvalStrategy, tableAccessStrategyInstances);
// execute preload if any
for (StatementAgentInstancePreload preload : preloadList) {
preload.executePreload(defaultAgentInstanceContext);
}
// handle association to table
if (statementSpec.getIntoTableSpec() != null) {
services.getStatementVariableRefService().addReferences(statementContext.getStatementName(), statementSpec.getIntoTableSpec().getName());
}
return new EPStatementStartResult(finalViewable, stopStatementMethod, selectDesc.getDestroyCallbacks());
}
private void validateTableAccessUse(IntoTableSpec bindingSpec, ExprTableAccessNode[] tableNodes)
throws ExprValidationException {
if (statementSpec.getIntoTableSpec() != null && statementSpec.getTableNodes() != null && statementSpec.getTableNodes().length > 0) {
for (ExprTableAccessNode node : statementSpec.getTableNodes()) {
if (node.getTableName().equals(statementSpec.getIntoTableSpec().getName())) {
throw new ExprValidationException("Invalid use of table '" + statementSpec.getIntoTableSpec().getName() + "', aggregate-into requires write-only, the expression '" +
ExprNodeUtility.toExpressionStringMinPrecedenceSafe(statementSpec.getTableNodes()[0]) + "' is not allowed");
}
}
}
}
}