private bool ContainsBuiltinProperties(ExprNode expr)
        {
            var propertyVisitor = new ExprNodeIdentifierVisitor(false);

            expr.Accept(propertyVisitor);
            return(!propertyVisitor.ExprProperties.IsEmpty());
        }
Пример #2
0
        public void TestVisit()
        {
            // test without aggregation nodes
            ExprNodeIdentifierVisitor visitor = new ExprNodeIdentifierVisitor(false);

            exprNode.Accept(visitor);

            Assert.AreEqual(2, visitor.ExprProperties.Count);
            Assert.AreEqual(0, (Object)visitor.ExprProperties[0].First);
            Assert.AreEqual("IntBoxed", (Object)visitor.ExprProperties[0].Second);
            Assert.AreEqual(0, (Object)visitor.ExprProperties[1].First);
            Assert.AreEqual("IntPrimitive", (Object)visitor.ExprProperties[1].Second);

            // test with aggregation nodes, such as "IntBoxed * sum(IntPrimitive)"
            exprNode = SupportExprNodeFactory.MakeSumAndFactorNode();
            visitor  = new ExprNodeIdentifierVisitor(true);
            exprNode.Accept(visitor);
            Assert.AreEqual(2, visitor.ExprProperties.Count);
            Assert.AreEqual("IntBoxed", (Object)visitor.ExprProperties[0].Second);
            Assert.AreEqual("IntPrimitive", (Object)visitor.ExprProperties[1].Second);

            visitor = new ExprNodeIdentifierVisitor(false);
            exprNode.Accept(visitor);
            Assert.AreEqual(1, visitor.ExprProperties.Count);
            Assert.AreEqual("IntBoxed", (Object)visitor.ExprProperties[0].Second);
        }
Пример #3
0
 public static IList<Pair<int, string>> GetExpressionProperties(
     ExprNode exprNode,
     bool visitAggregateNodes)
 {
     var visitor = new ExprNodeIdentifierVisitor(visitAggregateNodes);
     exprNode.Accept(visitor);
     return visitor.ExprProperties;
 }
Пример #4
0
        public void Validate(EngineImportService engineImportService, StreamTypeService streamTypeService, TimeProvider timeProvider, VariableService variableService, TableService tableService, ScriptingService scriptingService, ExprEvaluatorContext exprEvaluatorContext, ConfigurationInformation configSnapshot, SchedulingService schedulingService, string engineURI, IDictionary <int, IList <ExprNode> > sqlParameters, EventAdapterService eventAdapterService, StatementContext statementContext)
        {
            _statementContext = statementContext;

            // validate and visit
            var validationContext = new ExprValidationContext(
                streamTypeService, engineImportService,
                statementContext.StatementExtensionServicesContext, null,
                timeProvider, variableService, tableService,
                exprEvaluatorContext, eventAdapterService,
                statementContext.StatementName,
                statementContext.StatementId,
                statementContext.Annotations, null,
                scriptingService, false, false, true, false, null, false);
            var visitor = new ExprNodeIdentifierVisitor(true);
            IList <ExprNode> validatedInputParameters = new List <ExprNode>();

            foreach (var exprNode in _inputParameters)
            {
                var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.METHODINVJOIN, exprNode, validationContext);
                validatedInputParameters.Add(validated);
                validated.Accept(visitor);
            }

            // determine required streams
            _requiredStreams = new SortedSet <int>();
            foreach (var identifier in visitor.ExprProperties)
            {
                _requiredStreams.Add(identifier.First);
            }

            ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler
            {
                ProcHandle = (e) => {
                    if (_inputParameters.Count == 0)
                    {
                        return(new ExprValidationException("Method footprint does not match the number or type of expression parameters, expecting no parameters in method: " + e.Message));
                    }
                    var resultTypes = ExprNodeUtility.GetExprResultTypes(validatedInputParameters);
                    return(new ExprValidationException("Method footprint does not match the number or type of expression parameters, expecting a method where parameters are typed '" +
                                                       TypeHelper.GetParameterAsString(resultTypes) + "': " + e.Message));
                },
            };

            var desc = ExprNodeUtility.ResolveMethodAllowWildcardAndStream(
                _methodProviderClass.FullName, _isStaticMethod ? null : _methodProviderClass,
                _methodStreamSpec.MethodName, validatedInputParameters, engineImportService, eventAdapterService,
                statementContext.StatementId,
                false, null, handler, _methodStreamSpec.MethodName, tableService);

            _validatedExprNodes = desc.ChildEvals;
        }
Пример #5
0
        public static string[] GetPropertiesPerExpressionExpectSingle(IList<ExprNode> exprNodes)
        {
            var indexedProperties = new string[exprNodes.Count];
            for (var i = 0; i < exprNodes.Count; i++) {
                var visitor = new ExprNodeIdentifierVisitor(true);
                exprNodes[i].Accept(visitor);
                if (visitor.ExprProperties.Count != 1) {
                    throw new IllegalStateException("Failed to find indexed property");
                }

                indexedProperties[i] = visitor.ExprProperties.First().Second;
            }

            return indexedProperties;
        }
Пример #6
0
        public void Validate(
            EngineImportService engineImportService,
            StreamTypeService streamTypeService,
            TimeProvider timeProvider,
            VariableService variableService,
            TableService tableService,
            ScriptingService scriptingService,
            ExprEvaluatorContext exprEvaluatorContext,
            ConfigurationInformation configSnapshot,
            SchedulingService schedulingService,
            string engineURI,
            IDictionary <int, IList <ExprNode> > sqlParameters,
            EventAdapterService eventAdapterService,
            StatementContext statementContext)
        {
            _statementContext = statementContext;

            // validate and visit
            var validationContext        = new ExprValidationContext(streamTypeService, engineImportService, statementContext.StatementExtensionServicesContext, null, timeProvider, variableService, tableService, exprEvaluatorContext, eventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, null, statementContext.ScriptingService, false, false, true, false, null, false);
            var visitor                  = new ExprNodeIdentifierVisitor(true);
            var validatedInputParameters = new List <ExprNode>();

            foreach (var exprNode in _methodStreamSpec.Expressions)
            {
                var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.METHODINVJOIN, exprNode, validationContext);
                validatedInputParameters.Add(validated);
                validated.Accept(visitor);
            }

            // determine required streams
            _requiredStreams = new SortedSet <int>();
            foreach (var identifier in visitor.ExprProperties)
            {
                _requiredStreams.Add(identifier.First);
            }

            // class-based evaluation
            if (_metadata.MethodProviderClass != null)
            {
                // resolve actual method to use
                var handler = new ProxyExprNodeUtilResolveExceptionHandler {
                    ProcHandle = e => {
                        if (_methodStreamSpec.Expressions.Count == 0)
                        {
                            return(new ExprValidationException("Method footprint does not match the number or type of expression parameters, expecting no parameters in method: " + e.Message, e));
                        }
                        var resultTypes = ExprNodeUtility.GetExprResultTypes(validatedInputParameters);
                        return(new ExprValidationException(
                                   string.Format("Method footprint does not match the number or type of expression parameters, expecting a method where parameters are typed '{0}': {1}", TypeHelper.GetParameterAsString(resultTypes), e.Message), e));
                    }
                };
                var desc = ExprNodeUtility.ResolveMethodAllowWildcardAndStream(
                    _metadata.MethodProviderClass.FullName, _metadata.IsStaticMethod ? null : _metadata.MethodProviderClass,
                    _methodStreamSpec.MethodName, validatedInputParameters, engineImportService, eventAdapterService, statementContext.StatementId,
                    false, null, handler, _methodStreamSpec.MethodName, tableService, statementContext.EngineURI);
                _validatedExprNodes = desc.ChildEvals;

                // Construct polling strategy as a method invocation
                var invocationTarget = _metadata.InvocationTarget;
                var strategy         = _metadata.Strategy;
                var variableReader   = _metadata.VariableReader;
                var variableName     = _metadata.VariableName;
                var methodFastClass  = desc.FastMethod;
                if (_metadata.EventTypeEventBeanArray != null)
                {
                    _pollExecStrategy = new MethodPollingExecStrategyEventBeans(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                }
                else if (_metadata.OptionalMapType != null)
                {
                    if (desc.FastMethod.ReturnType.IsArray)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyMapArray(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsCollection)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyMapCollection(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsEnumerator)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyMapIterator(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyMapPlain(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                }
                else if (_metadata.OptionalOaType != null)
                {
                    if (desc.FastMethod.ReturnType == typeof(Object[][]))
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyOAArray(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsCollection)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyOACollection(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsEnumerator)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyOAIterator(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyOAPlain(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                }
                else
                {
                    if (desc.FastMethod.ReturnType.IsArray)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyPONOArray(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsCollection)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyPONOCollection(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else if (_metadata.IsEnumerator)
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyPONOIterator(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                    else
                    {
                        _pollExecStrategy = new MethodPollingExecStrategyPONOPlain(eventAdapterService, methodFastClass, _eventType, invocationTarget, strategy, variableReader, variableName, variableService);
                    }
                }
            }
            else
            {
                // script-based evaluation
                _pollExecStrategy   = new MethodPollingExecStrategyScript(_metadata.ScriptExpression, _metadata.EventTypeEventBeanArray);
                _validatedExprNodes = ExprNodeUtility.GetEvaluators(validatedInputParameters);
            }
        }
Пример #7
0
        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="viewChain">views</param>
        /// <param name="matchRecognizeSpec">specification</param>
        /// <param name="agentInstanceContext">The agent instance context.</param>
        /// <param name="isUnbound">true for unbound stream</param>
        /// <param name="annotations">annotations</param>
        /// <exception cref="ExprValidationException">
        /// Variable ' + defineItem.Identifier + ' has already been defined
        /// or
        /// An aggregate function may not appear in a DEFINE clause
        /// or
        /// Failed to validate condition expression for variable ' + defineItem.Identifier + ':  + ex.Message
        /// or
        /// Aggregation functions in the measure-clause must only refer to properties of exactly one group variable returning multiple events
        /// or
        /// Aggregation functions in the measure-clause must refer to one or more properties of exactly one group variable returning multiple events
        /// or
        /// The measures clause requires that each expression utilizes the AS keyword to assign a column name
        /// </exception>
        /// <throws>ExprValidationException if validation fails</throws>
        public EventRowRegexNFAViewFactory(
            ViewFactoryChain viewChain,
            MatchRecognizeSpec matchRecognizeSpec,
            AgentInstanceContext agentInstanceContext,
            bool isUnbound,
            Attribute[] annotations,
            ConfigurationEngineDefaults.MatchRecognizeConfig matchRecognizeConfig)
        {
            var parentViewType = viewChain.EventType;

            _matchRecognizeSpec   = matchRecognizeSpec;
            _isUnbound            = isUnbound;
            _isIterateOnly        = HintEnum.ITERATE_ONLY.GetHint(annotations) != null;
            _matchRecognizeConfig = matchRecognizeConfig;

            var statementContext = agentInstanceContext.StatementContext;

            // Expand repeats and permutations
            _expandedPatternNode = RegexPatternExpandUtil.Expand(matchRecognizeSpec.Pattern);

            // Determine single-row and multiple-row variables
            _variablesSingle = new LinkedHashSet <string>();
            ISet <string> variablesMultiple = new LinkedHashSet <string>();

            EventRowRegexHelper.RecursiveInspectVariables(_expandedPatternNode, false, _variablesSingle, variablesMultiple);

            // each variable gets associated with a stream number (multiple-row variables as well to hold the current event for the expression).
            var streamNum = 0;

            _variableStreams = new LinkedHashMap <string, Pair <int, bool> >();
            foreach (var variableSingle in _variablesSingle)
            {
                _variableStreams.Put(variableSingle, new Pair <int, bool>(streamNum, false));
                streamNum++;
            }
            foreach (var variableMultiple in variablesMultiple)
            {
                _variableStreams.Put(variableMultiple, new Pair <int, bool>(streamNum, true));
                streamNum++;
            }

            // mapping of stream to variable
            _streamVariables = new SortedDictionary <int, string>();
            foreach (var entry in _variableStreams)
            {
                _streamVariables.Put(entry.Value.First, entry.Key);
            }

            // determine visibility rules
            var visibility = EventRowRegexHelper.DetermineVisibility(_expandedPatternNode);

            // assemble all single-row variables for expression validation
            var allStreamNames = new string[_variableStreams.Count];
            var allTypes       = new EventType[_variableStreams.Count];

            streamNum = 0;
            foreach (var variableSingle in _variablesSingle)
            {
                allStreamNames[streamNum] = variableSingle;
                allTypes[streamNum]       = parentViewType;
                streamNum++;
            }
            foreach (var variableMultiple in variablesMultiple)
            {
                allStreamNames[streamNum] = variableMultiple;
                allTypes[streamNum]       = parentViewType;
                streamNum++;
            }

            // determine type service for use with DEFINE
            // validate each DEFINE clause expression
            ISet <string>             definedVariables = new HashSet <string>();
            IList <ExprAggregateNode> aggregateNodes   = new List <ExprAggregateNode>();
            var exprEvaluatorContext = new ExprEvaluatorContextStatement(statementContext, false);

            _isExprRequiresMultimatchState = new bool[_variableStreams.Count];

            for (var defineIndex = 0; defineIndex < matchRecognizeSpec.Defines.Count; defineIndex++)
            {
                var defineItem = matchRecognizeSpec.Defines[defineIndex];
                if (definedVariables.Contains(defineItem.Identifier))
                {
                    throw new ExprValidationException("Variable '" + defineItem.Identifier + "' has already been defined");
                }
                definedVariables.Add(defineItem.Identifier);

                // stream-type visibilities handled here
                var typeServiceDefines = EventRowRegexNFAViewFactoryHelper.BuildDefineStreamTypeServiceDefine(statementContext, _variableStreams, defineItem, visibility, parentViewType);

                var exprNodeResult    = HandlePreviousFunctions(defineItem.Expression);
                var validationContext = new ExprValidationContext(
                    typeServiceDefines,
                    statementContext.EngineImportService,
                    statementContext.StatementExtensionServicesContext, null,
                    statementContext.SchedulingService,
                    statementContext.VariableService,
                    statementContext.TableService, exprEvaluatorContext,
                    statementContext.EventAdapterService,
                    statementContext.StatementName,
                    statementContext.StatementId,
                    statementContext.Annotations,
                    statementContext.ContextDescriptor,
                    statementContext.ScriptingService,
                    true, false, true, false, null, false);

                ExprNode validated;
                try {
                    // validate
                    validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.MATCHRECOGDEFINE, exprNodeResult, validationContext);

                    // check aggregates
                    defineItem.Expression = validated;
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(validated, aggregateNodes);
                    if (!aggregateNodes.IsEmpty())
                    {
                        throw new ExprValidationException("An aggregate function may not appear in a DEFINE clause");
                    }
                }
                catch (ExprValidationException ex) {
                    throw new ExprValidationException("Failed to validate condition expression for variable '" + defineItem.Identifier + "': " + ex.Message, ex);
                }

                // determine access to event properties from multi-matches
                var visitor = new ExprNodeStreamRequiredVisitor();
                validated.Accept(visitor);
                var streamsRequired = visitor.StreamsRequired;
                foreach (var streamRequired in streamsRequired)
                {
                    if (streamRequired >= _variableStreams.Count)
                    {
                        var streamNumIdent = _variableStreams.Get(defineItem.Identifier).First;
                        _isExprRequiresMultimatchState[streamNumIdent] = true;
                        break;
                    }
                }
            }
            _isDefineAsksMultimatches  = CollectionUtil.IsAnySet(_isExprRequiresMultimatchState);
            _defineMultimatchEventBean = _isDefineAsksMultimatches ? EventRowRegexNFAViewFactoryHelper.GetDefineMultimatchBean(statementContext, _variableStreams, parentViewType) : null;

            // assign "prev" node indexes
            // Since an expression such as "prior(2, price), prior(8, price)" translates into {2, 8} the relative index is {0, 1}.
            // Map the expression-supplied index to a relative index
            var countPrev = 0;

            foreach (var entry in _callbacksPerIndex)
            {
                foreach (var callback in entry.Value)
                {
                    callback.AssignedIndex = countPrev;
                }
                countPrev++;
            }

            // determine type service for use with MEASURE
            IDictionary <string, object> measureTypeDef = new LinkedHashMap <string, object>();

            foreach (var variableSingle in _variablesSingle)
            {
                measureTypeDef.Put(variableSingle, parentViewType);
            }
            foreach (var variableMultiple in variablesMultiple)
            {
                measureTypeDef.Put(variableMultiple, new EventType[] { parentViewType });
            }
            var outputEventTypeName = statementContext.StatementId + "_rowrecog";

            _compositeEventType = (ObjectArrayEventType)statementContext.EventAdapterService.CreateAnonymousObjectArrayType(outputEventTypeName, measureTypeDef);
            StreamTypeService typeServiceMeasure = new StreamTypeServiceImpl(_compositeEventType, "MATCH_RECOGNIZE", true, statementContext.EngineURI);

            // find MEASURE clause aggregations
            var measureReferencesMultivar = false;
            IList <ExprAggregateNode> measureAggregateExprNodes = new List <ExprAggregateNode>();

            foreach (var measureItem in matchRecognizeSpec.Measures)
            {
                ExprAggregateNodeUtil.GetAggregatesBottomUp(measureItem.Expr, measureAggregateExprNodes);
            }
            if (!measureAggregateExprNodes.IsEmpty())
            {
                var isIStreamOnly = new bool[allStreamNames.Length];
                CompatExtensions.Fill(isIStreamOnly, true);
                var typeServiceAggregateMeasure  = new StreamTypeServiceImpl(allTypes, allStreamNames, isIStreamOnly, statementContext.EngineURI, false);
                var measureExprAggNodesPerStream = new Dictionary <int, IList <ExprAggregateNode> >();

                foreach (var aggregateNode in measureAggregateExprNodes)
                {
                    // validate absence of group-by
                    aggregateNode.ValidatePositionals();
                    if (aggregateNode.OptionalLocalGroupBy != null)
                    {
                        throw new ExprValidationException("Match-recognize does not allow aggregation functions to specify a group-by");
                    }

                    // validate node and params
                    var count   = 0;
                    var visitor = new ExprNodeIdentifierVisitor(true);

                    var validationContext = new ExprValidationContext(
                        typeServiceAggregateMeasure,
                        statementContext.EngineImportService,
                        statementContext.StatementExtensionServicesContext, null,
                        statementContext.SchedulingService,
                        statementContext.VariableService,
                        statementContext.TableService,
                        exprEvaluatorContext,
                        statementContext.EventAdapterService,
                        statementContext.StatementName,
                        statementContext.StatementId,
                        statementContext.Annotations,
                        statementContext.ContextDescriptor,
                        statementContext.ScriptingService,
                        false, false, true, false, null, false);
                    for (int ii = 0; ii < aggregateNode.ChildNodes.Count; ii++)
                    {
                        var child     = aggregateNode.ChildNodes[ii];
                        var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.MATCHRECOGMEASURE, child, validationContext);
                        validated.Accept(visitor);
                        aggregateNode.SetChildNode(count++, new ExprNodeValidated(validated));
                    }
                    validationContext = new ExprValidationContext(
                        typeServiceMeasure,
                        statementContext.EngineImportService,
                        statementContext.StatementExtensionServicesContext, null,
                        statementContext.SchedulingService,
                        statementContext.VariableService,
                        statementContext.TableService,
                        exprEvaluatorContext,
                        statementContext.EventAdapterService,
                        statementContext.StatementName,
                        statementContext.StatementId,
                        statementContext.Annotations,
                        statementContext.ContextDescriptor,
                        statementContext.ScriptingService,
                        false, false, true, false, null, false);
                    aggregateNode.Validate(validationContext);

                    // verify properties used within the aggregation
                    var aggregatedStreams = new HashSet <int>();
                    foreach (var pair in visitor.ExprProperties)
                    {
                        aggregatedStreams.Add(pair.First);
                    }

                    int?multipleVarStream = null;
                    foreach (int streamNumAggregated in aggregatedStreams)
                    {
                        var variable = _streamVariables.Get(streamNumAggregated);
                        if (variablesMultiple.Contains(variable))
                        {
                            measureReferencesMultivar = true;
                            if (multipleVarStream == null)
                            {
                                multipleVarStream = streamNumAggregated;
                                continue;
                            }
                            throw new ExprValidationException("Aggregation functions in the measure-clause must only refer to properties of exactly one group variable returning multiple events");
                        }
                    }

                    if (multipleVarStream == null)
                    {
                        throw new ExprValidationException("Aggregation functions in the measure-clause must refer to one or more properties of exactly one group variable returning multiple events");
                    }

                    var aggNodesForStream = measureExprAggNodesPerStream.Get(multipleVarStream.Value);
                    if (aggNodesForStream == null)
                    {
                        aggNodesForStream = new List <ExprAggregateNode>();
                        measureExprAggNodesPerStream.Put(multipleVarStream.Value, aggNodesForStream);
                    }
                    aggNodesForStream.Add(aggregateNode);
                }

                var factoryDesc = AggregationServiceFactoryFactory.GetServiceMatchRecognize(_streamVariables.Count, measureExprAggNodesPerStream, typeServiceAggregateMeasure.EventTypes);
                _aggregationService     = factoryDesc.AggregationServiceFactory.MakeService(agentInstanceContext);
                _aggregationExpressions = factoryDesc.Expressions;
            }
            else
            {
                _aggregationService     = null;
                _aggregationExpressions = Collections.GetEmptyList <AggregationServiceAggExpressionDesc>();
            }

            // validate each MEASURE clause expression
            IDictionary <string, object> rowTypeDef = new LinkedHashMap <string, object>();
            var streamRefVisitor = new ExprNodeStreamUseCollectVisitor();

            foreach (var measureItem in matchRecognizeSpec.Measures)
            {
                if (measureItem.Name == null)
                {
                    throw new ExprValidationException("The measures clause requires that each expression utilizes the AS keyword to assign a column name");
                }
                var validated = ValidateMeasureClause(measureItem.Expr, typeServiceMeasure, variablesMultiple, _variablesSingle, statementContext);
                measureItem.Expr = validated;
                rowTypeDef.Put(measureItem.Name, validated.ExprEvaluator.ReturnType);
                validated.Accept(streamRefVisitor);
            }

            // Determine if any of the multi-var streams are referenced in the measures (non-aggregated only)
            foreach (var @ref in streamRefVisitor.Referenced)
            {
                var rootPropName = @ref.RootPropertyNameIfAny;
                if (rootPropName != null)
                {
                    if (variablesMultiple.Contains(rootPropName))
                    {
                        measureReferencesMultivar = true;
                        break;
                    }
                }

                var streamRequired = @ref.StreamReferencedIfAny;
                if (streamRequired != null)
                {
                    var streamVariable = _streamVariables.Get(streamRequired.Value);
                    if (streamVariable != null)
                    {
                        var def = _variableStreams.Get(streamVariable);
                        if (def != null && def.Second)
                        {
                            measureReferencesMultivar = true;
                            break;
                        }
                    }
                }
            }
            _isCollectMultimatches = measureReferencesMultivar || _isDefineAsksMultimatches;

            // create rowevent type
            var rowEventTypeName = statementContext.StatementId + "_rowrecogrow";

            _rowEventType = statementContext.EventAdapterService.CreateAnonymousMapType(rowEventTypeName, rowTypeDef, true);

            // validate partition-by expressions, if any
            if (!matchRecognizeSpec.PartitionByExpressions.IsEmpty())
            {
                var typeServicePartition = new StreamTypeServiceImpl(parentViewType, "MATCH_RECOGNIZE_PARTITION", true, statementContext.EngineURI);
                var validated            = new List <ExprNode>();
                var validationContext    = new ExprValidationContext(
                    typeServicePartition,
                    statementContext.EngineImportService,
                    statementContext.StatementExtensionServicesContext, null,
                    statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService,
                    exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName,
                    statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor,
                    statementContext.ScriptingService,
                    false, false, true, false, null, false);
                foreach (var partitionExpr in matchRecognizeSpec.PartitionByExpressions)
                {
                    validated.Add(ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.MATCHRECOGPARTITION, partitionExpr, validationContext));
                }
                matchRecognizeSpec.PartitionByExpressions = validated;
            }

            // validate interval if present
            if (matchRecognizeSpec.Interval != null)
            {
                var validationContext =
                    new ExprValidationContext(
                        new StreamTypeServiceImpl(statementContext.EngineURI, false),
                        statementContext.EngineImportService,
                        statementContext.StatementExtensionServicesContext, null,
                        statementContext.SchedulingService,
                        statementContext.VariableService, statementContext.TableService, exprEvaluatorContext,
                        statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId,
                        statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService,
                        false, false, true, false, null, false);
                matchRecognizeSpec.Interval.Validate(validationContext);
            }
        }
Пример #8
0
        private static AggregationServiceForgeDesc[] PlanAggregations(
            IList<ExprAggregateNode> measureAggregateExprNodes,
            StreamTypeService compositeTypeServiceMeasure,
            string[] allStreamNames,
            EventType[] allTypes,
            IOrderedDictionary<int, string> streamVariables,
            ISet<string> variablesMultiple,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            IDictionary<int, IList<ExprAggregateNode>> measureExprAggNodesPerStream =
                new Dictionary<int, IList<ExprAggregateNode>>();

            foreach (var aggregateNode in measureAggregateExprNodes) {
                // validate node and params
                var count = 0;
                var visitor = new ExprNodeIdentifierVisitor(true);
                var isIStreamOnly = new bool[allStreamNames.Length];
                var typeServiceAggregateMeasure = new StreamTypeServiceImpl(
                    allTypes,
                    allStreamNames,
                    isIStreamOnly,
                    false,
                    true);

                var validationContext =
                    new ExprValidationContextBuilder(typeServiceAggregateMeasure, @base.StatementRawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                aggregateNode.ValidatePositionals(validationContext);

                if (aggregateNode.OptionalLocalGroupBy != null) {
                    throw new ExprValidationException(
                        "Match-recognize does not allow aggregation functions to specify a group-by");
                }

                foreach (var child in aggregateNode.ChildNodes) {
                    var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.MATCHRECOGMEASURE,
                        child,
                        validationContext);
                    validated.Accept(visitor);
                    aggregateNode.SetChildNode(count++, new ExprNodeValidated(validated));
                }

                // verify properties used within the aggregation
                ISet<int> aggregatedStreams = new HashSet<int>();
                foreach (var pair in visitor.ExprProperties) {
                    aggregatedStreams.Add(pair.First);
                }

                int? multipleVarStream = null;
                foreach (var streamNumAggregated in aggregatedStreams) {
                    var variable = streamVariables.Get(streamNumAggregated);
                    if (variablesMultiple.Contains(variable)) {
                        if (multipleVarStream == null) {
                            multipleVarStream = streamNumAggregated;
                            continue;
                        }

                        throw new ExprValidationException(
                            "Aggregation functions in the measure-clause must only refer to properties of exactly one group variable returning multiple events");
                    }
                }

                if (multipleVarStream == null) {
                    throw new ExprValidationException(
                        "Aggregation functions in the measure-clause must refer to one or more properties of exactly one group variable returning multiple events");
                }

                var aggNodesForStream = measureExprAggNodesPerStream.Get(multipleVarStream.Value);
                if (aggNodesForStream == null) {
                    aggNodesForStream = new List<ExprAggregateNode>();
                    measureExprAggNodesPerStream.Put(multipleVarStream.Value, aggNodesForStream);
                }

                aggNodesForStream.Add(aggregateNode);
            }

            // validate aggregation itself
            foreach (var entry in measureExprAggNodesPerStream) {
                foreach (var aggregateNode in entry.Value) {
                    var validationContext = new ExprValidationContextBuilder(
                            compositeTypeServiceMeasure,
                            @base.StatementRawInfo,
                            services)
                        .WithAllowBindingConsumption(true)
                        .WithMemberName(new ExprValidationMemberNameQualifiedRowRecogAgg(entry.Key))
                        .Build();
                    aggregateNode.Validate(validationContext);
                }
            }

            // get aggregation service per variable
            var aggServices = new AggregationServiceForgeDesc[allStreamNames.Length];
            var declareds = Arrays.AsList(@base.StatementSpec.DeclaredExpressions);
            foreach (var entry in measureExprAggNodesPerStream) {
                EventType[] typesPerStream = {allTypes[entry.Key]};
                AggregationServiceForgeDesc desc = AggregationServiceFactoryFactory.GetService(
                    entry.Value,
                    EmptyDictionary<ExprNode, string>.Instance, 
                    declareds,
                    new ExprNode[0],
                    null,
                    EmptyList<ExprAggregateNode>.Instance,
                    EmptyList<ExprAggregateNode>.Instance,
                    EmptyList<ExprAggregateNodeGroupKey>.Instance,
                    false,
                    @base.StatementRawInfo.Annotations,
                    services.VariableCompileTimeResolver,
                    true,
                    null,
                    null,
                    typesPerStream,
                    null,
                    @base.ContextName,
                    null,
                    services.TableCompileTimeResolver,
                    false,
                    true,
                    false,
                    services.ImportServiceCompileTime,
                    @base.StatementRawInfo,
                    services.SerdeResolver);

                aggServices[entry.Key] = desc;
            }

            return aggServices;
        }