public override EPPreparedExecuteIUDSingleStreamExec GetExecutor(FilterSpecCompiled filter, string aliasName) { var services = base.Services; var processor = base.Processor; var statementContext = base.StatementContext; var statementSpec = base.StatementSpec; var updateSpec = (FireAndForgetSpecUpdate)statementSpec.FireAndForgetSpec; var assignmentTypeService = new StreamTypeServiceImpl( new EventType[] { processor.EventTypeResultSetProcessor, null, processor.EventTypeResultSetProcessor }, new string[] { aliasName, "", EPStatementStartMethodOnTrigger.INITIAL_VALUE_STREAM_NAME }, new bool[] { true, true, true }, services.EngineURI, true); assignmentTypeService.IsStreamZeroUnambigous = true; var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, true); var validationContext = new ExprValidationContext( assignmentTypeService, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, null, false); // validate update expressions try { foreach (OnTriggerSetAssignment assignment in updateSpec.Assignments) { ExprNode validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.UPDATEASSIGN, assignment.Expression, validationContext); assignment.Expression = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "Aggregation functions may not be used within an update-clause"); } } catch (ExprValidationException e) { throw new EPException(e.Message, e); } // make updater EventBeanUpdateHelper updateHelper; TableUpdateStrategy tableUpdateStrategy = null; try { bool copyOnWrite = !(processor is FireAndForgetProcessorTable); updateHelper = EventBeanUpdateHelperFactory.Make(processor.NamedWindowOrTableName, (EventTypeSPI)processor.EventTypeResultSetProcessor, updateSpec.Assignments, aliasName, null, copyOnWrite, statementContext.StatementName, services.EngineURI, services.EventAdapterService); if (processor is FireAndForgetProcessorTable) { FireAndForgetProcessorTable tableProcessor = (FireAndForgetProcessorTable)processor; tableUpdateStrategy = services.TableService.GetTableUpdateStrategy(tableProcessor.TableMetadata, updateHelper, false); copyOnWrite = false; } } catch (ExprValidationException e) { throw new EPException(e.Message, e); } return(new EPPreparedExecuteIUDSingleStreamExecUpdate(filter, statementSpec.FilterRootNode, statementSpec.Annotations, updateHelper, tableUpdateStrategy, statementSpec.TableNodes, services)); }
private static void ValidateThenSetAssignments( IList <OnTriggerSetAssignment> assignments, ExprValidationContext validationContext) { if (assignments == null || assignments.IsEmpty()) { return; } foreach (var assign in assignments) { var node = ExprNodeUtility.GetValidatedAssignment(assign, validationContext); assign.Expression = node; EPStatementStartMethodHelperValidate.ValidateNoAggregations(node, "An aggregate function may not appear in a OUTPUT LIMIT clause"); } }
/// <summary> /// Validate filter and join expression nodes. /// </summary> /// <param name="statementSpec">the compiled statement</param> /// <param name="statementContext">the statement services</param> /// <param name="typeService">the event types for streams</param> /// <param name="viewResourceDelegate">the delegate to verify expressions that use view resources</param> internal static void ValidateNodes( StatementSpecCompiled statementSpec, StatementContext statementContext, StreamTypeService typeService, ViewResourceDelegateUnverified viewResourceDelegate) { var methodResolutionService = statementContext.MethodResolutionService; var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false); var intoTableName = statementSpec.IntoTableSpec == null ? null : statementSpec.IntoTableSpec.Name; if (statementSpec.FilterRootNode != null) { var optionalFilterNode = statementSpec.FilterRootNode; // Validate where clause, initializing nodes to the stream ids used try { var validationContext = new ExprValidationContext( typeService, methodResolutionService, viewResourceDelegate, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, intoTableName, false); optionalFilterNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.FILTER, optionalFilterNode, validationContext); if (optionalFilterNode.ExprEvaluator.ReturnType != typeof(bool) && optionalFilterNode.ExprEvaluator.ReturnType != typeof(bool?)) { throw new ExprValidationException("The where-clause filter expression must return a boolean value"); } statementSpec.FilterExprRootNode = optionalFilterNode; // Make sure there is no aggregation in the where clause var aggregateNodes = new List <ExprAggregateNode>(); ExprAggregateNodeUtil.GetAggregatesBottomUp(optionalFilterNode, aggregateNodes); if (!aggregateNodes.IsEmpty()) { throw new ExprValidationException("An aggregate function may not appear in a WHERE clause (use the HAVING clause)"); } } catch (ExprValidationException ex) { Log.Debug(".validateNodes Validation exception for filter=" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(optionalFilterNode), ex); throw new EPStatementException("Error validating expression: " + ex.Message, ex, statementContext.Expression); } } if ((statementSpec.OutputLimitSpec != null) && ((statementSpec.OutputLimitSpec.WhenExpressionNode != null) || (statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null))) { // Validate where clause, initializing nodes to the stream ids used try { var outputLimitType = OutputConditionExpressionFactory.GetBuiltInEventType(statementContext.EventAdapterService); StreamTypeService typeServiceOutputWhen = new StreamTypeServiceImpl(new EventType[] { outputLimitType }, new String[] { null }, new bool[] { true }, statementContext.EngineURI, false); var validationContext = new ExprValidationContext( typeServiceOutputWhen, methodResolutionService, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, false, false, intoTableName, false); var outputLimitWhenNode = statementSpec.OutputLimitSpec.WhenExpressionNode; if (outputLimitWhenNode != null) { outputLimitWhenNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.OUTPUTLIMIT, outputLimitWhenNode, validationContext); statementSpec.OutputLimitSpec.WhenExpressionNode = outputLimitWhenNode; if (TypeHelper.GetBoxedType(outputLimitWhenNode.ExprEvaluator.ReturnType) != typeof(bool?)) { throw new ExprValidationException("The when-trigger expression in the OUTPUT WHEN clause must return a boolean-type value"); } EPStatementStartMethodHelperValidate.ValidateNoAggregations(outputLimitWhenNode, "An aggregate function may not appear in a OUTPUT LIMIT clause"); } // validate and-terminate expression if provided if (statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null) { if (statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.WHEN_EXPRESSION && statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.TERM) { throw new ExprValidationException("A terminated-and expression must be used with the OUTPUT WHEN clause"); } var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.OUTPUTLIMIT, statementSpec.OutputLimitSpec.AndAfterTerminateExpr, validationContext); statementSpec.OutputLimitSpec.AndAfterTerminateExpr = validated; if (validated.ExprEvaluator.ReturnType.GetBoxedType() != typeof(bool?)) { throw new ExprValidationException("The terminated-and expression must return a boolean-type value"); } EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "An aggregate function may not appear in a terminated-and clause"); } // validate then-expression ValidateThenSetAssignments(statementSpec.OutputLimitSpec.ThenExpressions, validationContext); // validate after-terminated then-expression ValidateThenSetAssignments(statementSpec.OutputLimitSpec.AndAfterTerminateThenExpressions, validationContext); } catch (ExprValidationException ex) { throw new EPStatementException("Error validating expression: " + ex.Message, statementContext.Expression); } } for (var outerJoinCount = 0; outerJoinCount < statementSpec.OuterJoinDescList.Length; outerJoinCount++) { var outerJoinDesc = statementSpec.OuterJoinDescList[outerJoinCount]; // validate on-expression nodes, if provided if (outerJoinDesc.OptLeftNode != null) { var streamIdPair = ValidateOuterJoinPropertyPair(statementContext, outerJoinDesc.OptLeftNode, outerJoinDesc.OptRightNode, outerJoinCount, typeService, viewResourceDelegate); if (outerJoinDesc.AdditionalLeftNodes != null) { ISet <int?> streamSet = new HashSet <int?>(); streamSet.Add(streamIdPair.First); streamSet.Add(streamIdPair.Second); for (var i = 0; i < outerJoinDesc.AdditionalLeftNodes.Length; i++) { var streamIdPairAdd = ValidateOuterJoinPropertyPair(statementContext, outerJoinDesc.AdditionalLeftNodes[i], outerJoinDesc.AdditionalRightNodes[i], outerJoinCount, typeService, viewResourceDelegate); // make sure all additional properties point to the same two streams if ((!streamSet.Contains(streamIdPairAdd.First) || (!streamSet.Contains(streamIdPairAdd.Second)))) { const string message = "Outer join ON-clause columns must refer to properties of the same joined streams" + " when using multiple columns in the on-clause"; throw new EPStatementException("Error validating expression: " + message, statementContext.Expression); } } } } } }
public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient) { // define stop and destroy var stopCallbacks = new List <StopCallback>(); var destroyCallbacks = new EPStatementDestroyCallbackList(); // determine context var contextName = StatementSpec.OptionalContextName; if (contextName != null) { throw new ExprValidationException("Update IStream is not supported in conjunction with a context"); } // First we create streams for subselects, if there are any var subSelectStreamDesc = EPStatementStartMethodHelperSubselect.CreateSubSelectActivation( services, StatementSpec, statementContext, destroyCallbacks); var streamSpec = StatementSpec.StreamSpecs[0]; var updateSpec = StatementSpec.UpdateSpec; String triggereventTypeName; if (streamSpec is FilterStreamSpecCompiled) { var filterStreamSpec = (FilterStreamSpecCompiled)streamSpec; triggereventTypeName = filterStreamSpec.FilterSpec.FilterForEventTypeName; } else if (streamSpec is NamedWindowConsumerStreamSpec) { var namedSpec = (NamedWindowConsumerStreamSpec)streamSpec; triggereventTypeName = namedSpec.WindowName; } else if (streamSpec is TableQueryStreamSpec) { throw new ExprValidationException("Tables cannot be used in an update-istream statement"); } else { throw new ExprValidationException("Unknown stream specification streamEventType: " + streamSpec); } // determine a stream name var streamName = triggereventTypeName; if (updateSpec.OptionalStreamName != null) { streamName = updateSpec.OptionalStreamName; } var streamEventType = services.EventAdapterService.GetEventTypeByName(triggereventTypeName); StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[] { streamEventType }, new String[] { streamName }, new bool[] { true }, services.EngineURI, false); // determine subscriber result types var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false); statementContext.StatementResultService.SetSelectClause(new Type[] { streamEventType.UnderlyingType }, new String[] { "*" }, false, null, evaluatorContextStmt); // Materialize sub-select views var subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.PlanSubSelect(services, statementContext, IsQueryPlanLogging(services), subSelectStreamDesc, new String[] { streamName }, new EventType[] { streamEventType }, new String[] { triggereventTypeName }, StatementSpec.DeclaredExpressions, null); var validationContext = new ExprValidationContext( typeService, statementContext.MethodResolutionService, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, false, false, null, false); foreach (var assignment in updateSpec.Assignments) { var validated = ExprNodeUtility.GetValidatedAssignment(assignment, validationContext); assignment.Expression = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "Aggregation functions may not be used within an update-clause"); } if (updateSpec.OptionalWhereClause != null) { var validated = ExprNodeUtility.GetValidatedSubtree( ExprNodeOrigin.WHERE, updateSpec.OptionalWhereClause, validationContext); updateSpec.OptionalWhereClause = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "Aggregation functions may not be used within an update-clause"); } // preprocessing view var onExprView = new InternalRoutePreprocessView(streamEventType, statementContext.StatementResultService); // validation var routerDesc = services.InternalEventRouter.GetValidatePreprocessing(onExprView.EventType, updateSpec, statementContext.Annotations); // create context factory var contextFactory = new StatementAgentInstanceFactoryUpdate(statementContext, services, streamEventType, updateSpec, onExprView, routerDesc, subSelectStrategyCollection); // perform start of hook-up to start Viewable finalViewable; EPStatementStopMethod stopStatementMethod; IDictionary <ExprSubselectNode, SubSelectStrategyHolder> subselectStrategyInstances; // With context - delegate instantiation to context EPStatementStopMethod stopMethod = new EPStatementStopMethodImpl(statementContext, stopCallbacks).Stop; if (StatementSpec.OptionalContextName != null) { // use statement-wide agent-instance-specific subselects var aiRegistryExpr = statementContext.StatementAgentInstanceRegistry.AgentInstanceExprService; subselectStrategyInstances = new Dictionary <ExprSubselectNode, SubSelectStrategyHolder>(); foreach (var node in subSelectStrategyCollection.Subqueries.Keys) { var specificService = aiRegistryExpr.AllocateSubselect(node); node.Strategy = specificService; subselectStrategyInstances.Put(node, new SubSelectStrategyHolder(null, null, null, null, null, null)); } var mergeView = new ContextMergeView(onExprView.EventType); finalViewable = mergeView; var statement = new ContextManagedStatementOnTriggerDesc(StatementSpec, statementContext, mergeView, contextFactory); services.ContextManagementService.AddStatement(StatementSpec.OptionalContextName, statement, isRecoveringResilient); stopStatementMethod = () => { services.ContextManagementService.StoppedStatement(contextName, statementContext.StatementName, statementContext.StatementId); stopMethod.Invoke(); }; destroyCallbacks.AddCallback(EPStatementDestroyCallbackContext.New( services.ContextManagementService, StatementSpec.OptionalContextName, statementContext.StatementName, statementContext.StatementId)); } // Without context - start here else { var agentInstanceContext = GetDefaultAgentInstanceContext(statementContext); var resultOfStart = (StatementAgentInstanceFactoryUpdateResult) contextFactory.NewContext(agentInstanceContext, isRecoveringResilient); finalViewable = resultOfStart.FinalView; stopStatementMethod = new EPStatementStopMethod(() => { resultOfStart.StopCallback.Invoke(); stopMethod.Invoke(); }); subselectStrategyInstances = resultOfStart.SubselectStrategies; } // assign subquery nodes EPStatementStartMethodHelperAssignExpr.AssignSubqueryStrategies(subSelectStrategyCollection, subselectStrategyInstances); return(new EPStatementStartResult(finalViewable, stopStatementMethod, destroyCallbacks.Destroy)); }