// Determine stream names for each stream - some streams may not have a name given
String[] streamNames = EPStatementStartMethodHelperUtil.determineStreamNames(statementSpec.getStreamSpecs());
int numStreams = streamNames.length;
if (numStreams == 0) {
throw new ExprValidationException("The from-clause is required but has not been specified");
}
final boolean isJoin = statementSpec.getStreamSpecs().length > 1;
final boolean hasContext = statementSpec.getOptionalContextName() != null;
// First we create streams for subselects, if there are any
SubSelectActivationCollection subSelectStreamDesc = EPStatementStartMethodHelperSubselect.createSubSelectActivation(services, statementSpec, statementContext);
// Create streams and views
ViewableActivator[] eventStreamParentViewableActivators = new ViewableActivator[numStreams];
ViewFactoryChain[] unmaterializedViewChain = new ViewFactoryChain[numStreams];
String[] eventTypeNames = new String[numStreams];
boolean[] isNamedWindow = new boolean[numStreams];
HistoricalEventViewable[] historicalEventViewables = new HistoricalEventViewable[numStreams];
// verify for joins that required views are present
StreamJoinAnalysisResult joinAnalysisResult = verifyJoinViews(statementSpec, statementContext.getNamedWindowService(), defaultAgentInstanceContext);
final ExprEvaluatorContextStatement evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext);
for (int i = 0; i < statementSpec.getStreamSpecs().length; i++)
{
StreamSpecCompiled streamSpec = statementSpec.getStreamSpecs()[i];
// Create view factories and parent view based on a filter specification
if (streamSpec instanceof FilterStreamSpecCompiled)
{
final FilterStreamSpecCompiled filterStreamSpec = (FilterStreamSpecCompiled) streamSpec;
eventTypeNames[i] = filterStreamSpec.getFilterSpec().getFilterForEventTypeName();
// Since only for non-joins we get the existing stream's lock and try to reuse it's views
final boolean filterSubselectSameStream = EPStatementStartMethodHelperUtil.determineSubquerySameStream(statementSpec, filterStreamSpec);
// create activator
ViewableActivator activatorDeactivator;
if (optionalViewableActivatorFactory != null) {
activatorDeactivator = optionalViewableActivatorFactory.createActivator(filterStreamSpec);
if (activatorDeactivator == null) {
throw new IllegalStateException("Viewable activate is null for " + filterStreamSpec.getFilterSpec().getFilterForEventType().getName());
}
}
else {
if (!hasContext) {
activatorDeactivator = new ViewableActivatorStreamReuseView(services, statementContext, statementSpec, filterStreamSpec, isJoin, evaluatorContextStmt, filterSubselectSameStream, i);
}
else {
InstrumentationAgent instrumentationAgentFilter = null;
if (InstrumentationHelper.ENABLED) {
final String eventTypeName = filterStreamSpec.getFilterSpec().getFilterForEventType().getName();
final int streamNumber = i;
instrumentationAgentFilter = new InstrumentationAgent() {
public void indicateQ() {
InstrumentationHelper.get().qFilterActivationStream(eventTypeName, streamNumber);
}
public void indicateA() {
InstrumentationHelper.get().aFilterActivationStream();
}
};
}
activatorDeactivator = new ViewableActivatorFilterProxy(services, filterStreamSpec.getFilterSpec(), statementSpec.getAnnotations(), false, instrumentationAgentFilter);
}
}
eventStreamParentViewableActivators[i] = activatorDeactivator;
EventType resultEventType = filterStreamSpec.getFilterSpec().getResultEventType();
unmaterializedViewChain[i] = services.getViewService().createFactories(i, resultEventType, streamSpec.getViewSpecs(), streamSpec.getOptions(), statementContext);
}
// Create view factories and parent view based on a pattern expression
else if (streamSpec instanceof PatternStreamSpecCompiled)
{
PatternStreamSpecCompiled patternStreamSpec = (PatternStreamSpecCompiled) streamSpec;
boolean usedByChildViews = streamSpec.getViewSpecs().length > 0 || (statementSpec.getInsertIntoDesc() != null);
String patternTypeName = statementContext.getStatementId() + "_pattern_" + i;
final EventType eventType = services.getEventAdapterService().createSemiAnonymousMapType(patternTypeName, patternStreamSpec.getTaggedEventTypes(), patternStreamSpec.getArrayEventTypes(), usedByChildViews);
unmaterializedViewChain[i] = services.getViewService().createFactories(i, eventType, streamSpec.getViewSpecs(), streamSpec.getOptions(), statementContext);
final EvalRootFactoryNode rootFactoryNode = services.getPatternNodeFactory().makeRootNode();
rootFactoryNode.addChildNode(patternStreamSpec.getEvalFactoryNode());
final PatternContext patternContext = statementContext.getPatternContextFactory().createContext(statementContext, i, rootFactoryNode, patternStreamSpec.getMatchedEventMapMeta(), true);
// create activator
ViewableActivator patternActivator = new ViewableActivatorPattern(patternContext, rootFactoryNode, eventType, EPStatementStartMethodHelperUtil.isConsumingFilters(patternStreamSpec.getEvalFactoryNode()), patternStreamSpec.isSuppressSameEventMatches(), patternStreamSpec.isDiscardPartialsOnMatch());
eventStreamParentViewableActivators[i] = patternActivator;
}
// Create view factories and parent view based on a database SQL statement
else if (streamSpec instanceof DBStatementStreamSpec)
{
if (streamSpec.getViewSpecs().length > 0)
{
throw new ExprValidationException("Historical data joins do not allow views onto the data, view '"
+ streamSpec.getViewSpecs()[0].getObjectNamespace() + ':' + streamSpec.getViewSpecs()[0].getObjectName() + "' is not valid in this context");
}
DBStatementStreamSpec sqlStreamSpec = (DBStatementStreamSpec) streamSpec;
SQLColumnTypeConversion typeConversionHook = (SQLColumnTypeConversion) JavaClassHelper.getAnnotationHook(statementSpec.getAnnotations(), HookType.SQLCOL, SQLColumnTypeConversion.class, statementContext.getMethodResolutionService());
SQLOutputRowConversion outputRowConversionHook = (SQLOutputRowConversion) JavaClassHelper.getAnnotationHook(statementSpec.getAnnotations(), HookType.SQLROW, SQLOutputRowConversion.class, statementContext.getMethodResolutionService());
EPStatementAgentInstanceHandle epStatementAgentInstanceHandle = defaultAgentInstanceContext.getEpStatementAgentInstanceHandle();
final HistoricalEventViewable historicalEventViewable = DatabasePollingViewableFactory.createDBStatementView(statementContext.getStatementId(), i, sqlStreamSpec, services.getDatabaseRefService(), services.getEventAdapterService(), epStatementAgentInstanceHandle, typeConversionHook, outputRowConversionHook,
statementContext.getConfigSnapshot().getEngineDefaults().getLogging().isEnableJDBC());
historicalEventViewables[i] = historicalEventViewable;
unmaterializedViewChain[i] = new ViewFactoryChain(historicalEventViewable.getEventType(), new LinkedList<ViewFactory>());
eventStreamParentViewableActivators[i] = new ViewableActivator() {
public ViewableActivationResult activate(AgentInstanceContext agentInstanceContext, boolean isSubselect, boolean isRecoveringResilient) {
return new ViewableActivationResult(historicalEventViewable, CollectionUtil.STOP_CALLBACK_NONE, null, null, false, false);
}
};
stopCallbacks.add(historicalEventViewable);
}
else if (streamSpec instanceof MethodStreamSpec)
{
if (streamSpec.getViewSpecs().length > 0)
{
throw new ExprValidationException("Method data joins do not allow views onto the data, view '"
+ streamSpec.getViewSpecs()[0].getObjectNamespace() + ':' + streamSpec.getViewSpecs()[0].getObjectName() + "' is not valid in this context");
}
MethodStreamSpec methodStreamSpec = (MethodStreamSpec) streamSpec;
EPStatementAgentInstanceHandle epStatementAgentInstanceHandle = defaultAgentInstanceContext.getEpStatementAgentInstanceHandle();
final HistoricalEventViewable historicalEventViewable = MethodPollingViewableFactory.createPollMethodView(i, methodStreamSpec, services.getEventAdapterService(), epStatementAgentInstanceHandle, statementContext.getMethodResolutionService(), services.getEngineImportService(), statementContext.getSchedulingService(), statementContext.getScheduleBucket(), evaluatorContextStmt);
historicalEventViewables[i] = historicalEventViewable;
unmaterializedViewChain[i] = new ViewFactoryChain(historicalEventViewable.getEventType(), new LinkedList<ViewFactory>());
eventStreamParentViewableActivators[i] = new ViewableActivator() {
public ViewableActivationResult activate(AgentInstanceContext agentInstanceContext, boolean isSubselect, boolean isRecoveringResilient) {
return new ViewableActivationResult(historicalEventViewable, CollectionUtil.STOP_CALLBACK_NONE, null, null, false, false);
}
};
stopCallbacks.add(historicalEventViewable);
}
else if (streamSpec instanceof NamedWindowConsumerStreamSpec)
{
final NamedWindowConsumerStreamSpec namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
final NamedWindowProcessor processor = services.getNamedWindowService().getProcessor(namedSpec.getWindowName());
EventType namedWindowType = processor.getTailView().getEventType();
if (namedSpec.getOptPropertyEvaluator() != null) {
namedWindowType = namedSpec.getOptPropertyEvaluator().getFragmentEventType();
}
eventStreamParentViewableActivators[i] = new ViewableActivatorNamedWindow(processor, namedSpec.getFilterExpressions(), namedSpec.getOptPropertyEvaluator());
unmaterializedViewChain[i] = services.getViewService().createFactories(i, namedWindowType, namedSpec.getViewSpecs(), namedSpec.getOptions(), statementContext);
joinAnalysisResult.setNamedWindow(i);
eventTypeNames[i] = namedSpec.getWindowName();
isNamedWindow[i] = true;
// Consumers to named windows cannot declare a data window view onto the named window to avoid duplicate remove streams
EPStatementStartMethodHelperValidate.validateNoDataWindowOnNamedWindow(unmaterializedViewChain[i].getViewFactoryChain());
}
else
{
throw new ExprValidationException("Unknown stream specification type: " + streamSpec);
}
}
// handle match-recognize pattern
if (statementSpec.getMatchRecognizeSpec() != null)
{
if (isJoin)
{
throw new ExprValidationException("Joins are not allowed when using match recognize");
}
boolean isUnbound = (unmaterializedViewChain[0].getViewFactoryChain().isEmpty()) && (!(statementSpec.getStreamSpecs()[0] instanceof NamedWindowConsumerStreamSpec));
AgentInstanceContext agentInstanceContext = defaultAgentInstanceContext;
EventRowRegexNFAViewFactory factory = new EventRowRegexNFAViewFactory(unmaterializedViewChain[0], statementSpec.getMatchRecognizeSpec(), agentInstanceContext, isUnbound, statementSpec.getAnnotations());
unmaterializedViewChain[0].getViewFactoryChain().add(factory);
EPStatementStartMethodHelperAssignExpr.assignAggregations(factory.getAggregationService(), factory.getAggregationExpressions());
}
// Obtain event types from view factory chains
EventType[] streamEventTypes = new EventType[statementSpec.getStreamSpecs().length];
for (int i = 0; i < unmaterializedViewChain.length; i++)
{
streamEventTypes[i] = unmaterializedViewChain[i].getEventType();
}
// Add uniqueness information useful for joins
joinAnalysisResult.addUniquenessInfo(unmaterializedViewChain, statementSpec.getAnnotations());
// Validate sub-select views
SubSelectStrategyCollection subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.planSubSelect(services, statementContext, queryPlanLogging, subSelectStreamDesc, streamNames, streamEventTypes, eventTypeNames, stopCallbacks, statementSpec.getAnnotations(), statementSpec.getDeclaredExpressions(), contextPropertyRegistry);
// Construct type information per stream
StreamTypeService typeService = new StreamTypeServiceImpl(streamEventTypes, streamNames, EPStatementStartMethodHelperUtil.getHasIStreamOnly(isNamedWindow, unmaterializedViewChain), services.getEngineURI(), false);
ViewResourceDelegateUnverified viewResourceDelegateUnverified = new ViewResourceDelegateUnverified();
// Validate views that require validation, specifically streams that don't have
// sub-views such as DB SQL joins
HistoricalViewableDesc historicalViewableDesc = new HistoricalViewableDesc(numStreams);
for (int stream = 0; stream < historicalEventViewables.length; stream++)
{
HistoricalEventViewable historicalEventViewable = historicalEventViewables[stream];
if (historicalEventViewable == null) {
continue;
}
historicalEventViewable.validate(services.getEngineImportService(),
typeService,
statementContext.getMethodResolutionService(),
statementContext.getTimeProvider(),
statementContext.getVariableService(), evaluatorContextStmt,
services.getConfigSnapshot(), services.getSchedulingService(), services.getEngineURI(),
statementSpec.getSqlParameters(),
statementContext.getEventAdapterService(), statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations());
historicalViewableDesc.setHistorical(stream, historicalEventViewable.getRequiredStreams());
if (historicalEventViewable.getRequiredStreams().contains(stream))
{
throw new ExprValidationException("Parameters for historical stream " + stream + " indicate that the stream is subordinate to itself as stream parameters originate in the same stream");
}
}
// Construct a processor for results posted by views and joins, which takes care of aggregation if required.
// May return null if we don't need to post-process results posted by views or joins.