/************************************************************************************** * 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.core.start; import com.espertech.esper.client.EventType; import com.espertech.esper.client.VariableValueException; import com.espertech.esper.collection.Pair; import com.espertech.esper.core.context.activator.ViewableActivator; import com.espertech.esper.core.context.activator.ViewableActivatorFilterProxy; import com.espertech.esper.core.context.activator.ViewableActivatorNamedWindow; import com.espertech.esper.core.context.activator.ViewableActivatorPattern; import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryOnTrigger; import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryOnTriggerResult; import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryOnTriggerSplitDesc; import com.espertech.esper.core.context.mgr.ContextManagedStatementOnTriggerDesc; import com.espertech.esper.core.context.stmt.AIRegistryExpr; import com.espertech.esper.core.context.stmt.AIRegistrySubselect; import com.espertech.esper.core.context.subselect.SubSelectActivationCollection; import com.espertech.esper.core.context.subselect.SubSelectStrategyCollection; 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.ContextPropertyRegistry; import com.espertech.esper.core.service.*; import com.espertech.esper.epl.agg.service.AggregationService; import com.espertech.esper.epl.core.ResultSetProcessorFactoryDesc; import com.espertech.esper.epl.core.ResultSetProcessorFactoryFactory; import com.espertech.esper.epl.core.StreamTypeService; import com.espertech.esper.epl.core.StreamTypeServiceImpl; import com.espertech.esper.epl.expression.*; import com.espertech.esper.epl.metric.StatementMetricHandle; import com.espertech.esper.epl.named.NamedWindowOnExprFactory; import com.espertech.esper.epl.named.NamedWindowOnExprFactoryFactory; import com.espertech.esper.epl.named.NamedWindowProcessor; import com.espertech.esper.epl.spec.*; import com.espertech.esper.epl.variable.OnSetVariableViewFactory; import com.espertech.esper.epl.view.OutputProcessViewFactory; import com.espertech.esper.epl.view.OutputProcessViewFactoryFactory; import com.espertech.esper.event.EventTypeMetadata; import com.espertech.esper.event.map.MapEventType; import com.espertech.esper.pattern.EvalRootFactoryNode; import com.espertech.esper.pattern.PatternContext; import com.espertech.esper.util.StopCallback; import com.espertech.esper.util.UuidGenerator; import com.espertech.esper.view.ViewProcessingException; import com.espertech.esper.view.Viewable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.*; /** * Starts and provides the stop method for EPL statements. */ public class EPStatementStartMethodOnTrigger extends EPStatementStartMethodBase { private static final Log log = LogFactory.getLog(EPStatementStartMethodOnTrigger.class); public static final String INITIAL_VALUE_STREAM_NAME = "initial"; public EPStatementStartMethodOnTrigger(StatementSpecCompiled statementSpec) { super(statementSpec); } public EPStatementStartResult startInternal(final EPServicesContext services, final StatementContext statementContext, boolean isNewStatement, boolean isRecoveringStatement, boolean isRecoveringResilient) throws ExprValidationException, ViewProcessingException { // define stop final List<StopCallback> stopCallbacks = new LinkedList<StopCallback>(); final EPStatementStopMethod stopMethod = new EPStatementStopMethodImpl(statementContext, stopCallbacks); // determine context final String contextName = statementSpec.getOptionalContextName(); final ContextPropertyRegistry contextPropertyRegistry = (contextName != null) ? services.getContextManagementService().getContextDescriptor(contextName).getContextPropertyRegistry() : null; // create subselect information SubSelectActivationCollection subSelectStreamDesc = EPStatementStartMethodHelperSubselect.createSubSelectActivation(services, statementSpec, statementContext); // obtain activator final StreamSpecCompiled streamSpec = statementSpec.getStreamSpecs().get(0); ViewableActivator activator; String triggereventTypeName = null; EventType activatorResultEventType; if (streamSpec instanceof FilterStreamSpecCompiled) { FilterStreamSpecCompiled filterStreamSpec = (FilterStreamSpecCompiled) streamSpec; triggereventTypeName = filterStreamSpec.getFilterSpec().getFilterForEventTypeName(); activator = new ViewableActivatorFilterProxy(services, filterStreamSpec.getFilterSpec(), statementContext.getAnnotations(), false); activatorResultEventType = filterStreamSpec.getFilterSpec().getResultEventType(); } else if (streamSpec instanceof PatternStreamSpecCompiled) { PatternStreamSpecCompiled patternStreamSpec = (PatternStreamSpecCompiled) streamSpec; boolean usedByChildViews = !streamSpec.getViewSpecs().isEmpty() || (statementSpec.getInsertIntoDesc() != null); String patternTypeName = statementContext.getStatementId() + "_patternon"; final EventType eventType = services.getEventAdapterService().createSemiAnonymousMapType(patternTypeName, patternStreamSpec.getTaggedEventTypes(), patternStreamSpec.getArrayEventTypes(), usedByChildViews); EvalRootFactoryNode rootNode = services.getPatternNodeFactory().makeRootNode(); rootNode.addChildNode(patternStreamSpec.getEvalFactoryNode()); PatternContext patternContext = statementContext.getPatternContextFactory().createContext(statementContext, 0, rootNode, patternStreamSpec.getMatchedEventMapMeta(), true); activator = new ViewableActivatorPattern(patternContext, rootNode, eventType, EPStatementStartMethodHelperUtil.isConsumingFilters(patternStreamSpec.getEvalFactoryNode())); activatorResultEventType = eventType; } else if (streamSpec instanceof NamedWindowConsumerStreamSpec) { NamedWindowConsumerStreamSpec namedSpec = (NamedWindowConsumerStreamSpec) streamSpec; NamedWindowProcessor processor = services.getNamedWindowService().getProcessor(namedSpec.getWindowName()); if (processor == null) { throw new ExprValidationException("A named window by name '" + namedSpec.getWindowName() + "' does not exist"); } triggereventTypeName = namedSpec.getWindowName(); activator = new ViewableActivatorNamedWindow(processor, namedSpec.getFilterExpressions(), namedSpec.getOptPropertyEvaluator()); activatorResultEventType = processor.getNamedWindowType(); if (namedSpec.getOptPropertyEvaluator() != null) { activatorResultEventType = namedSpec.getOptPropertyEvaluator().getFragmentEventType(); } } else { throw new ExprValidationException("Unknown stream specification type: " + streamSpec); } // validation SubSelectStrategyCollection subSelectStrategyCollection; ResultSetProcessorFactoryDesc resultSetProcessorPrototype = null; ExprNode validatedJoin = null; StatementAgentInstanceFactoryOnTriggerSplitDesc splitDesc = null; ResultSetProcessorFactoryDesc outputResultSetProcessorPrototype = null; EventType outputEventType = null; OnSetVariableViewFactory onSetVariableViewFactory = null; NamedWindowOnExprFactory onExprFactory = null; // validation: For on-delete and on-select and on-update triggers if (statementSpec.getOnTriggerDesc() instanceof OnTriggerWindowDesc) { // Determine event types OnTriggerWindowDesc onTriggerDesc = (OnTriggerWindowDesc) statementSpec.getOnTriggerDesc(); NamedWindowProcessor processor = services.getNamedWindowService().getProcessor(onTriggerDesc.getWindowName()); if (processor == null) { throw new ExprValidationException("A named window by name '" + onTriggerDesc.getWindowName() + "' does not exist"); } // validate context processor.validateOnExpressionContext(contextName); EventType namedWindowType = processor.getNamedWindowType(); outputEventType = namedWindowType; statementContext.getDynamicReferenceEventTypes().add(onTriggerDesc.getWindowName()); String namedWindowName = onTriggerDesc.getOptionalAsName(); if (namedWindowName == null) { namedWindowName = "stream_0"; } String streamName = streamSpec.getOptionalStreamName(); if (streamName == null) { streamName = "stream_1"; } String namedWindowTypeName = onTriggerDesc.getWindowName(); // Materialize sub-select views // 0 - named window stream // 1 - arriving stream // 2 - initial value before update subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.planSubSelect(services, statementContext, isQueryPlanLogging(services), subSelectStreamDesc, new String[]{namedWindowName, streamSpec.getOptionalStreamName()}, new EventType[]{processor.getNamedWindowType(), activatorResultEventType}, new String[]{namedWindowTypeName, triggereventTypeName}, stopCallbacks, statementSpec.getAnnotations(), statementSpec.getDeclaredExpressions(), contextPropertyRegistry); StreamTypeServiceImpl typeService = new StreamTypeServiceImpl(new EventType[] {namedWindowType, activatorResultEventType}, new String[] {namedWindowName, streamName}, new boolean[] {false, true}, services.getEngineURI(), true); // allow "initial" as a prefix to properties StreamTypeServiceImpl assignmentTypeService; if (namedWindowName.equals(INITIAL_VALUE_STREAM_NAME) || streamName.equals(INITIAL_VALUE_STREAM_NAME)) { assignmentTypeService = typeService; } else { assignmentTypeService = new StreamTypeServiceImpl(new EventType[] {namedWindowType, activatorResultEventType, namedWindowType}, new String[] {namedWindowName, streamName, INITIAL_VALUE_STREAM_NAME}, new boolean[] {false, true, true}, services.getEngineURI(), false); assignmentTypeService.setStreamZeroUnambigous(true); } if (onTriggerDesc instanceof OnTriggerWindowUpdateDesc) { OnTriggerWindowUpdateDesc updateDesc = (OnTriggerWindowUpdateDesc) onTriggerDesc; ExprValidationContext validationContext = new ExprValidationContext(assignmentTypeService, statementContext.getMethodResolutionService(), null, statementContext.getSchedulingService(), statementContext.getVariableService(), getDefaultAgentInstanceContext(statementContext), statementContext.getEventAdapterService(), statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations(), statementContext.getContextDescriptor()); for (OnTriggerSetAssignment assignment : updateDesc.getAssignments()) { ExprNode validated = ExprNodeUtility.getValidatedSubtree(assignment.getExpression(), validationContext); assignment.setExpression(validated); EPStatementStartMethodHelperValidate.validateNoAggregations(validated, "Aggregation functions may not be used within an on-update-clause"); } } if (onTriggerDesc instanceof OnTriggerMergeDesc) { OnTriggerMergeDesc mergeDesc = (OnTriggerMergeDesc) onTriggerDesc; validateMergeDesc(mergeDesc, statementContext, processor.getNamedWindowType(), namedWindowName, activatorResultEventType, streamName); } // validate join expression validatedJoin = validateJoinNamedWindow(services.getEngineURI(), statementContext, statementSpec.getFilterRootNode(), namedWindowType, namedWindowName, namedWindowTypeName, activatorResultEventType, streamName, triggereventTypeName); // validate filter, output rate limiting EPStatementStartMethodHelperValidate.validateNodes(statementSpec, statementContext, typeService, null); // Construct a processor for results; for use in on-select to process selection results // Use a wildcard select if the select-clause is empty, such as for on-delete. // For on-select the select clause is not empty. if (statementSpec.getSelectClauseSpec().getSelectExprList().size() == 0) { statementSpec.getSelectClauseSpec().add(new SelectClauseElementWildcard()); } resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.getProcessorPrototype( statementSpec, statementContext, typeService, null, new boolean[0], true, contextPropertyRegistry, null); InternalEventRouter routerService = null; boolean addToFront = false; if (statementSpec.getInsertIntoDesc() != null || onTriggerDesc instanceof OnTriggerMergeDesc) { routerService = services.getInternalEventRouter(); } if (statementSpec.getInsertIntoDesc() != null) { addToFront = statementContext.getNamedWindowService().isNamedWindow(statementSpec.getInsertIntoDesc().getEventTypeName()); } boolean isDistinct = statementSpec.getSelectClauseSpec().isDistinct(); EventType selectResultEventType = resultSetProcessorPrototype.getResultSetProcessorFactory().getResultEventType(); StatementMetricHandle createNamedWindowMetricsHandle = processor.getCreateNamedWindowMetricsHandle(); onExprFactory = NamedWindowOnExprFactoryFactory.make(namedWindowType, onTriggerDesc.getWindowName(), namedWindowName, onTriggerDesc, activatorResultEventType, streamSpec.getOptionalStreamName(), addToFront, routerService, selectResultEventType, statementContext, createNamedWindowMetricsHandle, isDistinct); } // variable assignments else if (statementSpec.getOnTriggerDesc() instanceof OnTriggerSetDesc) { OnTriggerSetDesc desc = (OnTriggerSetDesc) statementSpec.getOnTriggerDesc(); StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[] {activatorResultEventType}, new String[] {streamSpec.getOptionalStreamName()}, new boolean[] {true}, services.getEngineURI(), false); ExprValidationContext validationContext = new ExprValidationContext(typeService, statementContext.getMethodResolutionService(), null, statementContext.getSchedulingService(), statementContext.getVariableService(), getDefaultAgentInstanceContext(statementContext), statementContext.getEventAdapterService(), statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations(), statementContext.getContextDescriptor()); // Materialize sub-select views subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.planSubSelect(services, statementContext, isQueryPlanLogging(services), subSelectStreamDesc, new String[]{streamSpec.getOptionalStreamName()}, new EventType[]{activatorResultEventType}, new String[]{triggereventTypeName}, stopCallbacks, statementSpec.getAnnotations(), statementSpec.getDeclaredExpressions(), contextPropertyRegistry); for (OnTriggerSetAssignment assignment : desc.getAssignments()) { ExprNode validated = ExprNodeUtility.getValidatedSubtree(assignment.getExpression(), validationContext); assignment.setExpression(validated); } try { ExprEvaluatorContextStatement exprEvaluatorContext = new ExprEvaluatorContextStatement(statementContext); onSetVariableViewFactory = new OnSetVariableViewFactory(statementContext.getStatementId(), desc, statementContext.getEventAdapterService(), statementContext.getVariableService(), statementContext.getStatementResultService(), exprEvaluatorContext); } catch (VariableValueException ex) { throw new ExprValidationException("Error in variable assignment: " + ex.getMessage(), ex); } outputEventType = onSetVariableViewFactory.getEventType(); } // split-stream use case else { OnTriggerSplitStreamDesc desc = (OnTriggerSplitStreamDesc) statementSpec.getOnTriggerDesc(); String streamName = streamSpec.getOptionalStreamName(); if (streamName == null) { streamName = "stream_0"; } StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[] {activatorResultEventType}, new String[] {streamName}, new boolean[] {true}, services.getEngineURI(), false); if (statementSpec.getInsertIntoDesc() == null) { throw new ExprValidationException("Required insert-into clause is not provided, the clause is required for split-stream syntax"); } if ((!statementSpec.getGroupByExpressions().isEmpty()) || (statementSpec.getHavingExprRootNode() != null) || (!statementSpec.getOrderByList().isEmpty())) { throw new ExprValidationException("A group-by clause, having-clause or order-by clause is not allowed for the split stream syntax"); } // Materialize sub-select views subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.planSubSelect(services, statementContext, isQueryPlanLogging(services), subSelectStreamDesc, new String[]{streamSpec.getOptionalStreamName()}, new EventType[]{activatorResultEventType}, new String[]{triggereventTypeName}, stopCallbacks, statementSpec.getAnnotations(), statementSpec.getDeclaredExpressions(), contextPropertyRegistry); EPStatementStartMethodHelperValidate.validateNodes(statementSpec, statementContext, typeService, null); ResultSetProcessorFactoryDesc[] processorFactories = new ResultSetProcessorFactoryDesc[desc.getSplitStreams().size() + 1]; ExprNode[] whereClauses = new ExprNode[desc.getSplitStreams().size() + 1]; processorFactories[0] = ResultSetProcessorFactoryFactory.getProcessorPrototype( statementSpec, statementContext, typeService, null, new boolean[0], false, contextPropertyRegistry, null); whereClauses[0] = statementSpec.getFilterRootNode(); boolean[] isNamedWindowInsert = new boolean[desc.getSplitStreams().size() + 1]; isNamedWindowInsert[0] = false; int index = 1; for (OnTriggerSplitStream splits : desc.getSplitStreams()) { StatementSpecCompiled splitSpec = new StatementSpecCompiled(); splitSpec.setInsertIntoDesc(splits.getInsertInto()); splitSpec.setSelectClauseSpec(StatementLifecycleSvcImpl.compileSelectAllowSubselect(splits.getSelectClause())); splitSpec.setFilterExprRootNode(splits.getWhereClause()); EPStatementStartMethodHelperValidate.validateNodes(splitSpec, statementContext, typeService, null); processorFactories[index] = ResultSetProcessorFactoryFactory.getProcessorPrototype( splitSpec, statementContext, typeService, null, new boolean[0], false, contextPropertyRegistry, null); whereClauses[index] = splitSpec.getFilterRootNode(); isNamedWindowInsert[index] = statementContext.getNamedWindowService().isNamedWindow(splits.getInsertInto().getEventTypeName()); index++; } splitDesc = new StatementAgentInstanceFactoryOnTriggerSplitDesc(processorFactories, whereClauses, isNamedWindowInsert); } // For on-delete/set/update/merge, create an output processor that passes on as a wildcard the underlying event if ((statementSpec.getOnTriggerDesc().getOnTriggerType() == OnTriggerType.ON_DELETE) || (statementSpec.getOnTriggerDesc().getOnTriggerType() == OnTriggerType.ON_SET) || (statementSpec.getOnTriggerDesc().getOnTriggerType() == OnTriggerType.ON_UPDATE) || (statementSpec.getOnTriggerDesc().getOnTriggerType() == OnTriggerType.ON_MERGE)) { StatementSpecCompiled defaultSelectAllSpec = new StatementSpecCompiled(); defaultSelectAllSpec.getSelectClauseSpec().add(new SelectClauseElementWildcard()); StreamTypeService streamTypeService = new StreamTypeServiceImpl(new EventType[] {outputEventType}, new String[] {"trigger_stream"}, new boolean[] {true}, services.getEngineURI(), false); outputResultSetProcessorPrototype = ResultSetProcessorFactoryFactory.getProcessorPrototype(defaultSelectAllSpec, statementContext, streamTypeService, null, new boolean[0], true, contextPropertyRegistry, null); } EventType resultEventType = resultSetProcessorPrototype == null ? null : resultSetProcessorPrototype.getResultSetProcessorFactory().getResultEventType(); OutputProcessViewFactory outputViewFactory = OutputProcessViewFactoryFactory.make(statementSpec, services.getInternalEventRouter(), statementContext, resultEventType, null); // create context factory StatementAgentInstanceFactoryOnTrigger contextFactory = new StatementAgentInstanceFactoryOnTrigger(statementContext, statementSpec, services, activator, subSelectStrategyCollection, resultSetProcessorPrototype, validatedJoin, activatorResultEventType, splitDesc, outputResultSetProcessorPrototype, onSetVariableViewFactory, onExprFactory, outputViewFactory, isRecoveringStatement); // perform start of hook-up to start Viewable finalViewable; EPStatementStopMethod stopStatementMethod; EPStatementDestroyMethod destroyStatementMethod; Map<ExprSubselectNode, SubSelectStrategyHolder> subselectStrategyInstances; AggregationService aggregationService; // 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 (ExprSubselectNode node : subSelectStrategyCollection.getSubqueries().keySet()) { AIRegistrySubselect specificService = aiRegistryExpr.allocateSubselect(node); node.setStrategy(specificService); subselectStrategyInstances.put(node, new SubSelectStrategyHolder(specificService, null, null, null, null, null)); } ContextMergeView mergeView = new ContextMergeView(resultSetProcessorPrototype.getResultSetProcessorFactory().getResultEventType()); finalViewable = mergeView; ContextManagedStatementOnTriggerDesc statement = new ContextManagedStatementOnTriggerDesc(statementSpec, statementContext, mergeView, contextFactory); services.getContextManagementService().addStatement(contextName, statement, isRecoveringResilient); stopStatementMethod = new EPStatementStopMethod(){ public void stop() { services.getContextManagementService().stoppedStatement(contextName, statementContext.getStatementName(), statementContext.getStatementId()); stopMethod.stop(); } }; destroyStatementMethod = new EPStatementDestroyMethod(){ public void destroy() { services.getContextManagementService().destroyedStatement(contextName, statementContext.getStatementName(), statementContext.getStatementId()); } }; } // Without context - start here else { AgentInstanceContext agentInstanceContext = getDefaultAgentInstanceContext(statementContext); final StatementAgentInstanceFactoryOnTriggerResult resultOfStart = contextFactory.newContext(agentInstanceContext, false); finalViewable = resultOfStart.getFinalView(); stopStatementMethod = new EPStatementStopMethod() { public void stop() { resultOfStart.getStopCallback().stop(); stopMethod.stop(); } }; destroyStatementMethod = null; aggregationService = resultOfStart.getOptionalAggegationService(); subselectStrategyInstances = resultOfStart.getSubselectStrategies(); if (statementContext.getExtensionServicesContext() != null) { statementContext.getExtensionServicesContext().startContextPartition(resultOfStart, 0); } } // initialize aggregation expression nodes if (resultSetProcessorPrototype != null && resultSetProcessorPrototype.getAggregationServiceFactoryDesc() != null) { EPStatementStartMethodHelperAssignExpr.assignAggregations(aggregationService, resultSetProcessorPrototype.getAggregationServiceFactoryDesc().getExpressions()); } // assign subquery nodes EPStatementStartMethodHelperAssignExpr.assignSubqueryStrategies(subSelectStrategyCollection, subselectStrategyInstances); return new EPStatementStartResult(finalViewable, stopStatementMethod, destroyStatementMethod); } private void validateMergeDesc(OnTriggerMergeDesc mergeDesc, StatementContext statementContext, EventType namedWindowType, String namedWindowName, EventType triggerStreamType, String triggerStreamName) throws ExprValidationException { String exprNodeErrorMessage = "Aggregation functions may not be used within an merge-clause"; ExprEvaluatorContextStatement evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext); for (OnTriggerMergeMatched matchedItem : mergeDesc.getItems()) { EventType dummyTypeNoProperties = new MapEventType(EventTypeMetadata.createAnonymous("merge_named_window_insert"), "merge_named_window_insert", 0, null, Collections.<String, Object>emptyMap(), null, null, null); StreamTypeServiceImpl twoStreamTypeSvc = new StreamTypeServiceImpl(new EventType[] {namedWindowType, triggerStreamType}, new String[] {namedWindowName, triggerStreamName}, new boolean[] {true, true}, statementContext.getEngineURI(), true); StreamTypeService insertOnlyTypeSvc = new StreamTypeServiceImpl(new EventType[] {dummyTypeNoProperties, triggerStreamType}, new String[] {UuidGenerator.generate(), triggerStreamName}, new boolean[] {true, true}, statementContext.getEngineURI(), true); // we may provide an additional stream "initial" for the prior value, unless already defined StreamTypeServiceImpl assignmentStreamTypeSvc; if (namedWindowName.equals(INITIAL_VALUE_STREAM_NAME) || triggerStreamName.equals(INITIAL_VALUE_STREAM_NAME)) { assignmentStreamTypeSvc = twoStreamTypeSvc; } else { assignmentStreamTypeSvc = new StreamTypeServiceImpl(new EventType[] {namedWindowType, triggerStreamType, namedWindowType}, new String[] {namedWindowName, triggerStreamName, INITIAL_VALUE_STREAM_NAME}, new boolean[] {true, true, true}, statementContext.getEngineURI(), false); assignmentStreamTypeSvc.setStreamZeroUnambigous(true); } if (matchedItem.getOptionalMatchCond() != null) { StreamTypeService matchValidStreams = matchedItem.isMatchedUnmatched() ? twoStreamTypeSvc : insertOnlyTypeSvc; matchedItem.setOptionalMatchCond(EPStatementStartMethodHelperValidate.validateExprNoAgg(matchedItem.getOptionalMatchCond(), matchValidStreams, statementContext, evaluatorContextStmt, exprNodeErrorMessage)); if (!matchedItem.isMatchedUnmatched()) { EPStatementStartMethodHelperValidate.validateSubqueryExcludeOuterStream(matchedItem.getOptionalMatchCond()); } } for (OnTriggerMergeAction item : matchedItem.getActions()) { if (item instanceof OnTriggerMergeActionDelete) { OnTriggerMergeActionDelete delete = (OnTriggerMergeActionDelete) item; if (delete.getOptionalWhereClause() != null) { delete.setOptionalWhereClause(EPStatementStartMethodHelperValidate.validateExprNoAgg(delete.getOptionalWhereClause(), twoStreamTypeSvc, statementContext, evaluatorContextStmt, exprNodeErrorMessage)); } } else if (item instanceof OnTriggerMergeActionUpdate) { OnTriggerMergeActionUpdate update = (OnTriggerMergeActionUpdate) item; if (update.getOptionalWhereClause() != null) { update.setOptionalWhereClause(EPStatementStartMethodHelperValidate.validateExprNoAgg(update.getOptionalWhereClause(), twoStreamTypeSvc, statementContext, evaluatorContextStmt, exprNodeErrorMessage)); } for (OnTriggerSetAssignment assignment : update.getAssignments()) { assignment.setExpression(EPStatementStartMethodHelperValidate.validateExprNoAgg(assignment.getExpression(), assignmentStreamTypeSvc, statementContext, evaluatorContextStmt, exprNodeErrorMessage)); } } else if (item instanceof OnTriggerMergeActionInsert) { OnTriggerMergeActionInsert insert = (OnTriggerMergeActionInsert) item; StreamTypeService insertTypeSvc; if (insert.getOptionalStreamName() == null || insert.getOptionalStreamName().equals(namedWindowName)) { insertTypeSvc = insertOnlyTypeSvc; } else { insertTypeSvc = twoStreamTypeSvc; } List<SelectClauseElementCompiled> compiledSelect = new ArrayList<SelectClauseElementCompiled>(); if (insert.getOptionalWhereClause() != null) { insert.setOptionalWhereClause(EPStatementStartMethodHelperValidate.validateExprNoAgg(insert.getOptionalWhereClause(), insertTypeSvc, statementContext, evaluatorContextStmt, exprNodeErrorMessage)); } int colIndex = 0; for (SelectClauseElementRaw raw : insert.getSelectClause()) { if (raw instanceof SelectClauseStreamRawSpec) { SelectClauseStreamRawSpec rawStreamSpec = (SelectClauseStreamRawSpec) raw; Integer foundStreamNum = null; for (int s = 0; s < insertTypeSvc.getStreamNames().length; s++) { if (rawStreamSpec.getStreamName().equals(insertTypeSvc.getStreamNames()[s])) { foundStreamNum = s; break; } } if (foundStreamNum == null) { throw new ExprValidationException("Stream by name '" + rawStreamSpec.getStreamName() + "' was not found"); } SelectClauseStreamCompiledSpec streamSelectSpec = new SelectClauseStreamCompiledSpec(rawStreamSpec.getStreamName(), rawStreamSpec.getOptionalAsName()); streamSelectSpec.setStreamNumber(foundStreamNum); compiledSelect.add(streamSelectSpec); } else if (raw instanceof SelectClauseExprRawSpec) { SelectClauseExprRawSpec exprSpec = (SelectClauseExprRawSpec) raw; ExprValidationContext validationContext = new ExprValidationContext(insertTypeSvc, statementContext.getMethodResolutionService(), null, statementContext.getTimeProvider(), statementContext.getVariableService(), evaluatorContextStmt, statementContext.getEventAdapterService(), statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations(), statementContext.getContextDescriptor()); ExprNode exprCompiled = ExprNodeUtility.getValidatedSubtree(exprSpec.getSelectExpression(), validationContext); String resultName = exprSpec.getOptionalAsName(); if (resultName == null) { if (insert.getColumns().size() > colIndex) { resultName = insert.getColumns().get(colIndex); } else { resultName = exprCompiled.toExpressionString(); } } compiledSelect.add(new SelectClauseExprCompiledSpec(exprCompiled, resultName, exprSpec.getOptionalAsName())); EPStatementStartMethodHelperValidate.validateNoAggregations(exprCompiled, "Expression in a merge-selection may not utilize aggregation functions"); } else if (raw instanceof SelectClauseElementWildcard) { compiledSelect.add(new SelectClauseElementWildcard()); } else { throw new IllegalStateException("Unknown select clause item:" + raw); } colIndex++; } insert.setSelectClauseCompiled(compiledSelect); } else { throw new IllegalArgumentException("Unrecognized merge item '" + item.getClass().getName() + "'"); } } } } // For delete actions from named windows protected ExprNode validateJoinNamedWindow(String engineURI, StatementContext statementContext, ExprNode deleteJoinExpr, EventType namedWindowType, String namedWindowStreamName, String namedWindowName, EventType filteredType, String filterStreamName, String filteredTypeName) throws ExprValidationException { if (deleteJoinExpr == null) { return null; } LinkedHashMap<String, Pair<EventType, String>> namesAndTypes = new LinkedHashMap<String, Pair<EventType, String>>(); namesAndTypes.put(namedWindowStreamName, new Pair<EventType, String>(namedWindowType, namedWindowName)); namesAndTypes.put(filterStreamName, new Pair<EventType, String>(filteredType, filteredTypeName)); StreamTypeService typeService = new StreamTypeServiceImpl(namesAndTypes, engineURI, false, false); ExprEvaluatorContextStatement evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext); ExprValidationContext validationContext = new ExprValidationContext(typeService, statementContext.getMethodResolutionService(), null, statementContext.getSchedulingService(), statementContext.getVariableService(), evaluatorContextStmt, statementContext.getEventAdapterService(), statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations(), statementContext.getContextDescriptor()); return ExprNodeUtility.getValidatedSubtree(deleteJoinExpr, validationContext); } }