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);
                            }
                        }
                    }
                }
            }
        }
示例#4
0
        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));
        }