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);
        }
Example #2
0
        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="lookupable">is the lookup-able</param>
        /// <param name="filterOperator">is expected to be the BOOLEAN_EXPR operator</param>
        /// <param name="exprNode">represents the boolean expression</param>
        /// <param name="taggedEventTypes">is null if the expression doesn't need other streams, or is filled with a ordered list of stream names and types</param>
        /// <param name="arrayEventTypes">is a map of name tags and event type per tag for repeat-expressions that generate an array of events</param>
        /// <param name="variableService">provides access to variables</param>
        /// <param name="tableService">The table service.</param>
        /// <param name="eventAdapterService">for creating event types and event beans</param>
        /// <param name="configurationInformation">The configuration information.</param>
        /// <param name="statementName">Name of the statement.</param>
        /// <param name="hasSubquery">if set to <c>true</c> [has subquery].</param>
        /// <param name="hasTableAccess">if set to <c>true</c> [has table access].</param>
        /// <exception cref="System.ArgumentException">Invalid filter operator for filter expression node</exception>
        /// <throws>IllegalArgumentException for illegal args</throws>
        public FilterSpecParamExprNode(
            FilterSpecLookupable lookupable,
            FilterOperator filterOperator,
            ExprNode exprNode,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            VariableService variableService,
            TableService tableService,
            EventAdapterService eventAdapterService,
            ConfigurationInformation configurationInformation,
            string statementName,
            bool hasSubquery,
            bool hasTableAccess)
            : base(lookupable, filterOperator)
        {
            if (filterOperator != FilterOperator.BOOLEAN_EXPRESSION)
            {
                throw new ArgumentException("Invalid filter operator for filter expression node");
            }
            _exprNode                 = exprNode;
            _taggedEventTypes         = taggedEventTypes;
            _arrayEventTypes          = arrayEventTypes;
            _variableService          = variableService;
            _tableService             = tableService;
            _eventAdapterService      = eventAdapterService;
            _useLargeThreadingProfile = configurationInformation.EngineDefaults.ExecutionConfig.ThreadingProfile == ConfigurationEngineDefaults.ThreadingProfile.LARGE;
            _hasFilterStreamSubquery  = hasSubquery;
            _hasTableAccess           = hasTableAccess;

            var visitor = new ExprNodeVariableVisitor();

            exprNode.Accept(visitor);
            _hasVariable = visitor.HasVariables;
        }
Example #3
0
 public override void Accept(ExprNodeVisitor visitor)
 {
     if (visitor.IsVisit(this)) {
         visitor.Visit(this);
         inner.Accept(visitor);
     }
 }
        private bool ContainsBuiltinProperties(ExprNode expr)
        {
            var propertyVisitor = new ExprNodeIdentifierVisitor(false);

            expr.Accept(propertyVisitor);
            return(!propertyVisitor.ExprProperties.IsEmpty());
        }
        // Special-case validation: When an on-merge query in the not-matched clause uses a subquery then
        // that subquery should not reference any of the stream's properties which are not-matched
        internal static void ValidateSubqueryExcludeOuterStream(ExprNode matchCondition)
        {
            var visitorSubselects = new ExprNodeSubselectDeclaredDotVisitor();

            matchCondition.Accept(visitorSubselects);
            if (visitorSubselects.Subselects.IsEmpty())
            {
                return;
            }
            var visitorProps = new ExprNodeIdentifierCollectVisitor();

            foreach (var node in visitorSubselects.Subselects)
            {
                if (node.StatementSpecCompiled.FilterRootNode != null)
                {
                    node.StatementSpecCompiled.FilterRootNode.Accept(visitorProps);
                }
            }
            foreach (var node in visitorProps.ExprProperties)
            {
                if (node.StreamId == 1)
                {
                    throw new ExprValidationException("On-Merge not-matched filter expression may not use properties that are provided by the named window event");
                }
            }
        }
Example #6
0
        private static FilterSpecParamForge MakeBooleanExprParam(
            ExprNode exprNode,
            FilterSpecCompilerArgs args)
        {
            bool hasSubselectFilterStream = DetermineSubselectFilterStream(exprNode);
            bool hasTableAccess = DetermineTableAccessFilterStream(exprNode);

            ExprNodeVariableVisitor visitor =
                new ExprNodeVariableVisitor(args.compileTimeServices.VariableCompileTimeResolver);
            exprNode.Accept(visitor);
            bool hasVariable = visitor.IsVariables;

            ExprFilterSpecLookupableForge lookupable = new ExprFilterSpecLookupableForge(
                PROPERTY_NAME_BOOLEAN_EXPRESSION,
                null,
                exprNode.Forge.EvaluationType,
                false);

            return new FilterSpecParamExprNodeForge(
                lookupable,
                FilterOperator.BOOLEAN_EXPRESSION,
                exprNode,
                args.taggedEventTypes,
                args.arrayEventTypes,
                args.streamTypeService,
                hasSubselectFilterStream,
                hasTableAccess,
                hasVariable,
                args.compileTimeServices);
        }
Example #7
0
        public ExprDeclaredNodeImpl(
            ExpressionDeclItem prototype,
            IList<ExprNode> chainParameters,
            ContextCompileTimeDescriptor contextDescriptor,
            ExprNode expressionBodyCopy)
        {
            PrototypeWVisibility = prototype;
            ChainParameters = chainParameters;
            ExpressionBodyCopy = expressionBodyCopy;

            // replace context-properties where they are currently identifiers
            if (contextDescriptor == null) {
                return;
            }

            var visitorWParent = new ExprNodeIdentVisitorWParent();
            expressionBodyCopy.Accept(visitorWParent);
            foreach (var pair in visitorWParent.IdentNodes) {
                var streamOrProp = pair.Second.StreamOrPropertyName;
                if (streamOrProp != null &&
                    contextDescriptor.ContextPropertyRegistry.IsContextPropertyPrefix(streamOrProp)) {
                    var context =
                        new ExprContextPropertyNodeImpl(pair.Second.UnresolvedPropertyName);
                    if (pair.First == null) {
                        ExpressionBodyCopy = context;
                    }
                    else {
                        ExprNodeUtilityModify.ReplaceChildNode(pair.First, pair.Second, context);
                    }
                }
            }
        }
        private object GetFirstObjectFromMember(ExprNode memberExp, List <Node> suffixes)
        {
            if (memberExp is SelfExpression)
            {
                return(Context.CurrentFrame.Resolve("this"));
            }
            if (memberExp is Identifier)
            {
                var id = ((Identifier)memberExp).Value;
                if (Context.CurrentFrame.Exist(id))
                {
                    return(Context.CurrentFrame.Resolve(id));
                }

                // TODO handle nested type
                // propably CLR type
                if (!(suffixes[0] is TypeDescriptorSuffix) && Context.IsClrType(id))
                {
                    return(Context.LoadTypeFromName(id));
                }

                // start with namespace?  attempt further
                for (int i = 0; i < suffixes.Count; i++)
                {
                    var suffix = suffixes[i];
                    if (suffix is IndexSuffix)
                    {
                        break;
                    }

                    if (suffix is TypeDescriptorSuffix)
                    {
                        var typeParams = (Type[])suffix.Accept(this);
                        suffixes.RemoveRange(0, i + 1);
                        return(Context.LoadTypeFromName(id, typeParams));
                    }

                    id += "." + suffix.SuffixValue(this);
                    if (i < suffixes.Count - 1 && (suffixes[i + 1] is TypeDescriptorSuffix))
                    {
                        var typeParams = (Type[])suffixes[i + 1].Accept(this);
                        suffixes.RemoveRange(0, i + 2);
                        return(Context.LoadTypeFromName(id, typeParams));
                    }

                    if (Context.IsClrType(id))
                    {
                        suffixes.RemoveRange(0, i + 1);
                        return(Context.LoadTypeFromName(id));
                    }
                }

                if (id.IndexOf('.') >= 0)
                {
                    id = id.Substring(0, id.IndexOf('.'));
                }
                throw ErrorFactory.CreateNotDefinedError(id);
            }
            return(memberExp.Accept(this));
        }
Example #9
0
 public static IList<Pair<int, string>> GetExpressionProperties(
     ExprNode exprNode,
     bool visitAggregateNodes)
 {
     var visitor = new ExprNodeIdentifierVisitor(visitAggregateNodes);
     exprNode.Accept(visitor);
     return visitor.ExprProperties;
 }
Example #10
0
 public static void SetChildIdentNodesOptionalEvent(ExprNode exprNode)
 {
     ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor();
     exprNode.Accept(visitor);
     foreach (ExprIdentNode node in visitor.ExprProperties) {
         node.IsOptionalEvent = true;
     }
 }
Example #11
0
        private static ExprNode HandlePreviousFunctions(
            ExprNode defineItemExpression,
            IOrderedDictionary<int, IList<ExprPreviousMatchRecognizeNode>> previousNodes)
        {
            var previousVisitor = new ExprNodePreviousVisitorWParent();
            defineItemExpression.Accept(previousVisitor);

            if (previousVisitor.Previous == null) {
                return defineItemExpression;
            }

            foreach (var previousNodePair in previousVisitor.Previous) {
                var previousNode = previousNodePair.Second;
                var matchRecogPrevNode = new ExprPreviousMatchRecognizeNode();

                if (previousNodePair.Second.ChildNodes.Length == 1) {
                    matchRecogPrevNode.AddChildNode(previousNode.ChildNodes[0]);
                    matchRecogPrevNode.AddChildNode(new ExprConstantNodeImpl(1));
                }
                else if (previousNodePair.Second.ChildNodes.Length == 2) {
                    var first = previousNode.ChildNodes[0];
                    var second = previousNode.ChildNodes[1];
                    if (first is ExprConstantNode && !(second is ExprConstantNode)) {
                        matchRecogPrevNode.AddChildNode(second);
                        matchRecogPrevNode.AddChildNode(first);
                    }
                    else if (!(first is ExprConstantNode) && second is ExprConstantNode) {
                        matchRecogPrevNode.AddChildNode(first);
                        matchRecogPrevNode.AddChildNode(second);
                    }
                    else {
                        throw new ExprValidationException("PREV operator requires a constant index");
                    }
                }

                if (previousNodePair.First == null) {
                    defineItemExpression = matchRecogPrevNode;
                }
                else {
                    ExprNodeUtilityModify.ReplaceChildNode(
                        previousNodePair.First,
                        previousNodePair.Second,
                        matchRecogPrevNode);
                }

                // store in a list per index such that we can consolidate this into a single buffer
                var index = matchRecogPrevNode.ConstantIndexNumber;
                var callbackList = previousNodes.Get(index);
                if (callbackList == null) {
                    callbackList = new List<ExprPreviousMatchRecognizeNode>();
                    previousNodes.Put(index, callbackList);
                }

                callbackList.Add(matchRecogPrevNode);
            }

            return defineItemExpression;
        }
Example #12
0
 public static void AddNonAggregatedProps(
     ExprNode exprNode,
     ExprNodePropOrStreamSet set,
     EventType[] types,
     ContextPropertyRegistry contextPropertyRegistry)
 {
     ExprNodeIdentifierAndStreamRefVisitor visitor = new ExprNodeIdentifierAndStreamRefVisitor(false);
     exprNode.Accept(visitor);
     AddNonAggregatedProps(set, visitor.Refs, types, contextPropertyRegistry);
 }
Example #13
0
        public static ISet<int> GetIdentStreamNumbers(ExprNode child)
        {
            ISet<int> streams = new HashSet<int>();
            var visitor = new ExprNodeIdentifierCollectVisitor();
            child.Accept(visitor);
            foreach (var node in visitor.ExprProperties) {
                streams.Add(node.StreamId);
            }

            return streams;
        }
        private static bool Prequalify(ExprNode constituent)
        {
            var prequalify = new FilterSpecExprNodeVisitorBooleanLimitedExprPrequalify();
            constituent.Accept(prequalify);
            if (!prequalify.IsLimited) {
                return false;
            }

            var streamRefVisitor = new ExprNodeIdentifierAndStreamRefVisitor(false);
            constituent.Accept(streamRefVisitor);
            var hasStreamRefZero = false;
            foreach (var @ref in streamRefVisitor.Refs) {
                if (@ref.StreamNum == 0) {
                    hasStreamRefZero = true;
                    break;
                }
            }

            return hasStreamRefZero && !streamRefVisitor.HasWildcardOrStreamAlias;
        }
Example #15
0
        public static void ValidateNoProperties(string viewName, ExprNode expression, int index)
        {
            var visitor = new ExprNodeSummaryVisitor();

            expression.Accept(visitor);
            if (!visitor.IsPlain)
            {
                string message = "Invalid view parameter expression " + index + GetViewDesc(viewName) + ", " +
                                 visitor.GetMessage() + " are not allowed within the expression";
                throw new ViewParameterException(message);
            }
        }
Example #16
0
        /// <summary>Assert and throws an exception if the expression uses event property values. </summary>
        /// <param name="viewName">textual name of view</param>
        /// <param name="expression">expression to check</param>
        /// <param name="index">number offset of expression in view parameters</param>
        /// <param name="exprEvaluatorContext">context for expression evaluation</param>
        /// <returns>expression evaluation value</returns>
        /// <throws>ViewParameterException if assertion fails</throws>
        public static Object EvaluateAssertNoProperties(String viewName, ExprNode expression, int index, ExprEvaluatorContext exprEvaluatorContext)
        {
            var visitor = new ExprNodeSummaryVisitor();

            expression.Accept(visitor);
            if (!visitor.IsPlain)
            {
                var message = "Invalid view parameter expression " + index + GetViewDesc(viewName) + ", " + visitor.Message + " are not allowed within the expression";
                throw new ViewParameterException(message);
            }

            return(expression.ExprEvaluator.Evaluate(new EvaluateParams(null, false, exprEvaluatorContext)));
        }
Example #17
0
        /// <summary>
        /// Check if the expression is minimal: does not have a subselect, aggregation and does not need view resources
        /// </summary>
        /// <param name="expression">to inspect</param>
        /// <returns>null if minimal, otherwise name of offending sub-expression</returns>
        public static string IsMinimalExpression(ExprNode expression)
        {
            ExprNodeSubselectDeclaredDotVisitor subselectVisitor = new ExprNodeSubselectDeclaredDotVisitor();
            expression.Accept(subselectVisitor);
            if (subselectVisitor.Subselects.Count > 0) {
                return "a subselect";
            }

            ExprNodeViewResourceVisitor viewResourceVisitor = new ExprNodeViewResourceVisitor();
            expression.Accept(viewResourceVisitor);
            if (viewResourceVisitor.ExprNodes.Count > 0) {
                return "a function that requires view resources (prior, prev)";
            }

            IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>();
            ExprAggregateNodeUtil.GetAggregatesBottomUp(expression, aggregateNodes);
            if (!aggregateNodes.IsEmpty()) {
                return "an aggregation function";
            }

            return null;
        }
Example #18
0
        private static bool DetermineSubselectFilterStream(ExprNode exprNode)
        {
            ExprNodeSubselectDeclaredDotVisitor visitor = new ExprNodeSubselectDeclaredDotVisitor();
            exprNode.Accept(visitor);
            if (visitor.Subselects.IsEmpty()) {
                return false;
            }

            foreach (ExprSubselectNode subselectNode in visitor.Subselects) {
                if (subselectNode.IsFilterStreamSubselect) {
                    return true;
                }
            }

            return false;
        }
Example #19
0
        /// <summary>
        /// Returns true if all properties within the expression are witin data window'd streams.
        /// </summary>
        /// <param name="child">expression to interrogate</param>
        /// <param name="streamTypeService">streams</param>
        /// <param name="unidirectionalJoin">indicator unidirection join</param>
        /// <returns>indicator</returns>
        public static bool HasRemoveStreamForAggregations(
            ExprNode child,
            StreamTypeService streamTypeService,
            bool unidirectionalJoin)
        {
            // Determine whether all streams are istream-only or irstream
            bool[] isIStreamOnly = streamTypeService.IStreamOnly;
            bool isAllIStream = true; // all true?
            bool isAllIRStream = true; // all false?
            foreach (bool anIsIStreamOnly in isIStreamOnly) {
                if (!anIsIStreamOnly) {
                    isAllIStream = false;
                }
                else {
                    isAllIRStream = false;
                }
            }

            // determine if a data-window applies to this max function
            bool hasDataWindows = true;
            if (isAllIStream) {
                hasDataWindows = false;
            }
            else if (!isAllIRStream) {
                if (streamTypeService.EventTypes.Length > 1) {
                    if (unidirectionalJoin) {
                        return false;
                    }

                    // In a join we assume that a data window is present or implicit via unidirectional
                }
                else {
                    hasDataWindows = false;
                    // get all aggregated properties to determine if any is from a windowed stream
                    ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor();
                    child.Accept(visitor);
                    foreach (ExprIdentNode node in visitor.ExprProperties) {
                        if (!isIStreamOnly[node.StreamId]) {
                            hasDataWindows = true;
                            break;
                        }
                    }
                }
            }

            return hasDataWindows;
        }
Example #20
0
 private static void ValidatePlainExpression(
     ExprNodeOrigin origin,
     ExprNode expression,
     ExprNodeSummaryVisitor summaryVisitor)
 {
     expression.Accept(summaryVisitor);
     if (summaryVisitor.HasAggregation ||
         summaryVisitor.HasSubselect ||
         summaryVisitor.HasStreamSelect ||
         summaryVisitor.HasPreviousPrior) {
         string text = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expression);
         throw new ExprValidationException(
             "Invalid " +
             origin.GetClauseName() +
             " expression '" +
             text +
             "': Aggregation, sub-select, previous or prior functions are not supported in this context");
     }
 }
Example #21
0
        internal static MatchedEventConvertorForge GetMatchEventConvertor(
            ExprNode value,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered)
        {
            var streamUseCollectVisitor = new ExprNodeStreamUseCollectVisitor();
            value.Accept(streamUseCollectVisitor);

            ISet<int> streams = new HashSet<int>();
            foreach (var streamRefNode in streamUseCollectVisitor.Referenced) {
                if (streamRefNode.StreamReferencedIfAny == null) {
                    continue;
                }

                streams.Add(streamRefNode.StreamReferencedIfAny.Value);
            }

            return new MatchedEventConvertorForge(taggedEventTypes, arrayEventTypes, allTagNamesOrdered, streams, true);
        }
Example #22
0
        public ExprDeclaredNodeImpl(
            IContainer container,
            ExpressionDeclItem prototype,
            IList <ExprNode> chainParameters,
            ContextDescriptor contextDescriptor)
        {
            _prototype       = prototype;
            _chainParameters = chainParameters;

            // copy expression - we do it at this time and not later
            try {
                _expressionBodyCopy = (ExprNode)SerializableObjectCopier.Copy(container, prototype.Inner);
            } catch (Exception e) {
                throw new Exception("Internal error providing expression tree: " + e.Message, e);
            }

            // replace context-properties where they are currently identifiers
            if (contextDescriptor == null)
            {
                return;
            }
            var visitorWParent = new ExprNodeIdentVisitorWParent();

            _expressionBodyCopy.Accept(visitorWParent);
            foreach (var pair in visitorWParent.IdentNodes)
            {
                var streamOrProp = pair.Second.StreamOrPropertyName;
                if (streamOrProp != null && contextDescriptor.ContextPropertyRegistry.IsContextPropertyPrefix(streamOrProp))
                {
                    var context = new ExprContextPropertyNode(pair.Second.UnresolvedPropertyName);
                    if (pair.First == null)
                    {
                        _expressionBodyCopy = context;
                    }
                    else
                    {
                        ExprNodeUtility.ReplaceChildNode(pair.First, pair.Second, context);
                    }
                }
            }
        }
Example #23
0
        public static EligibilityDesc VerifyInputStream(
            ExprNode expression,
            int indexedStream)
        {
            var visitor = new ExprNodeIdentifierCollectVisitor();
            expression.Accept(visitor);
            var inputStreamsRequired = visitor.StreamsRequired;
            if (inputStreamsRequired.Count > 1) { // multi-stream dependency no optimization (i.e. a+b=c)
                return new EligibilityDesc(Eligibility.INELIGIBLE, null);
            }

            if (inputStreamsRequired.Count == 1 && inputStreamsRequired.First() == indexedStream) {
                // self-compared no optimization
                return new EligibilityDesc(Eligibility.INELIGIBLE, null);
            }

            if (inputStreamsRequired.IsEmpty()) {
                return new EligibilityDesc(Eligibility.REQUIRE_NONE, null);
            }

            return new EligibilityDesc(Eligibility.REQUIRE_ONE, inputStreamsRequired.First());
        }
        private static void FindValueExpr(
            ExprNode child,
            ExprNode parent,
            AtomicReference<IList<ExprNodeWithParentPair>> pairsRef)
        {
            var valueVisitor = new FilterSpecExprNodeVisitorValueLimitedExpr();
            child.Accept(valueVisitor);

            // not by itself a value expression, but itself it may decompose into some value expressions
            if (!valueVisitor.IsLimited) {
                FindValueExpressionsDeepRecursive(child, pairsRef);
                return;
            }

            // add value expression, don't traverse child
            IList<ExprNodeWithParentPair> pairs = pairsRef.Get();
            if (pairs == null) {
                pairs = new List<ExprNodeWithParentPair>(2);
                pairsRef.Set(pairs);
            }

            pairs.Add(new ExprNodeWithParentPair(child, parent));
        }
        /// <summary>
        /// Returns an instance to handle the aggregation required by the aggregation expression nodes, depending on
        /// whether there are any group-by nodes.
        /// </summary>
        /// <param name="selectAggregateExprNodes">aggregation nodes extracted out of the select expression</param>
        /// <param name="selectClauseNamedNodes">The select clause named nodes.</param>
        /// <param name="declaredExpressions">The declared expressions.</param>
        /// <param name="groupByNodes">The group by nodes.</param>
        /// <param name="havingAggregateExprNodes">aggregation nodes extracted out of the select expression</param>
        /// <param name="orderByAggregateExprNodes">aggregation nodes extracted out of the select expression</param>
        /// <param name="groupKeyExpressions">The group key expressions.</param>
        /// <param name="hasGroupByClause">indicator on whethere there is group-by required, or group-all</param>
        /// <param name="annotations">statement annotations</param>
        /// <param name="variableService">variable</param>
        /// <param name="isJoin">true for joins</param>
        /// <param name="isDisallowNoReclaim">if set to <c>true</c> [is disallow no reclaim].</param>
        /// <param name="whereClause">the where-clause function if any</param>
        /// <param name="havingClause">the having-clause function if any</param>
        /// <param name="factoryService">The factory service.</param>
        /// <param name="typesPerStream">The types per stream.</param>
        /// <param name="methodResolutionService">The method resolution service.</param>
        /// <param name="groupByRollupDesc">The group by rollup desc.</param>
        /// <param name="optionalContextName">Name of the optional context.</param>
        /// <param name="intoTableSpec">The into table spec.</param>
        /// <param name="tableService">The table service.</param>
        /// <param name="isUnidirectional">if set to <c>true</c> [is unidirectional].</param>
        /// <param name="isFireAndForget">if set to <c>true</c> [is fire and forget].</param>
        /// <param name="isOnSelect">if set to <c>true</c> [is on select].</param>
        /// <returns>
        /// instance for aggregation handling
        /// </returns>
        /// <exception cref="ExprValidationException">
        /// Into-table requires at least one aggregation function
        /// or
        /// The ' + funcname + ' function may not occur in the where-clause or having-clause of a statement with aggregations as 'previous' does not provide remove stream data; Use the 'first','last','window' or 'count' aggregation functions instead
        /// or
        /// Invalid into-table clause: Failed to find table by name ' + intoTableSpec.Name + '
        /// </exception>
        /// <exception cref="EPException">Failed to obtain hook for  + HookType.INTERNAL_AGGLOCALLEVEL</exception>
        /// <throws>com.espertech.esper.epl.expression.core.ExprValidationException if validation fails</throws>
        public static AggregationServiceFactoryDesc GetService(
            IList <ExprAggregateNode> selectAggregateExprNodes,
            IDictionary <ExprNode, string> selectClauseNamedNodes,
            IList <ExprDeclaredNode> declaredExpressions,
            ExprNode[] groupByNodes,
            IList <ExprAggregateNode> havingAggregateExprNodes,
            IList <ExprAggregateNode> orderByAggregateExprNodes,
            IList <ExprAggregateNodeGroupKey> groupKeyExpressions,
            bool hasGroupByClause,
            Attribute[] annotations,
            VariableService variableService,
            bool isJoin,
            bool isDisallowNoReclaim,
            ExprNode whereClause,
            ExprNode havingClause,
            AggregationServiceFactoryService factoryService,
            EventType[] typesPerStream,
            MethodResolutionService methodResolutionService,
            AggregationGroupByRollupDesc groupByRollupDesc,
            string optionalContextName,
            IntoTableSpec intoTableSpec,
            TableService tableService,
            bool isUnidirectional,
            bool isFireAndForget,
            bool isOnSelect)
        {
            // No aggregates used, we do not need this service
            if ((selectAggregateExprNodes.IsEmpty()) && (havingAggregateExprNodes.IsEmpty()))
            {
                if (intoTableSpec != null)
                {
                    throw new ExprValidationException("Into-table requires at least one aggregation function");
                }

                return(new AggregationServiceFactoryDesc(
                           factoryService.GetNullAggregationService(),
                           Collections.GetEmptyList <AggregationServiceAggExpressionDesc>(),
                           Collections.GetEmptyList <ExprAggregateNodeGroupKey>()));
            }

            // Validate the absence of "prev" function in where-clause:
            // Since the "previous" function does not post remove stream results, disallow when used with aggregations.
            if ((whereClause != null) || (havingClause != null))
            {
                var visitor = new ExprNodePreviousVisitorWParent();
                if (whereClause != null)
                {
                    whereClause.Accept(visitor);
                }
                if (havingClause != null)
                {
                    havingClause.Accept(visitor);
                }
                if ((visitor.Previous != null) && (!visitor.Previous.IsEmpty()))
                {
                    string funcname = visitor.Previous[0].Second.PreviousType.ToString().ToLower();
                    throw new ExprValidationException("The '" + funcname + "' function may not occur in the where-clause or having-clause of a statement with aggregations as 'previous' does not provide remove stream data; Use the 'first','last','window' or 'count' aggregation functions instead");
                }
            }

            // Compile a map of aggregation nodes and equivalent-to aggregation nodes.
            // Equivalent-to functions are for example "select sum(a*b), 5*sum(a*b)".
            // Reducing the total number of aggregation functions.
            IList <AggregationServiceAggExpressionDesc> aggregations = new List <AggregationServiceAggExpressionDesc>();

            foreach (var selectAggNode in selectAggregateExprNodes)
            {
                AddEquivalent(selectAggNode, aggregations);
            }
            foreach (var havingAggNode in havingAggregateExprNodes)
            {
                AddEquivalent(havingAggNode, aggregations);
            }
            foreach (var orderByAggNode in orderByAggregateExprNodes)
            {
                AddEquivalent(orderByAggNode, aggregations);
            }

            // Construct a list of evaluation node for the aggregation functions (regular agg).
            // For example "sum(2 * 3)" would make the sum an evaluation node.
            IList <ExprEvaluator> methodAggEvaluatorsList = new List <ExprEvaluator>();

            foreach (var aggregation in aggregations)
            {
                var aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation)
                {
                    var evaluator = aggregateNode.Factory.GetMethodAggregationEvaluator(
                        typesPerStream.Length > 1, typesPerStream);
                    methodAggEvaluatorsList.Add(evaluator);
                }
            }

            // determine local group-by, report when hook provided
            AggregationGroupByLocalGroupDesc localGroupDesc = AnalyzeLocalGroupBy(aggregations, groupByNodes, groupByRollupDesc, intoTableSpec);

            // determine binding
            if (intoTableSpec != null)
            {
                // obtain metadata
                var metadata = tableService.GetTableMetadata(intoTableSpec.Name);
                if (metadata == null)
                {
                    throw new ExprValidationException("Invalid into-table clause: Failed to find table by name '" + intoTableSpec.Name + "'");
                }

                EPLValidationUtil.ValidateContextName(true, intoTableSpec.Name, metadata.ContextName, optionalContextName, false);

                // validate group keys
                var groupByTypes = ExprNodeUtility.GetExprResultTypes(groupByNodes);
                ExprTableNodeUtil.ValidateExpressions(intoTableSpec.Name, groupByTypes, "group-by", groupByNodes,
                                                      metadata.KeyTypes, "group-by");

                // determine how this binds to existing aggregations, assign column numbers
                var bindingMatchResult = MatchBindingsAssignColumnNumbers(intoTableSpec, metadata, aggregations, selectClauseNamedNodes, methodAggEvaluatorsList, declaredExpressions);

                // return factory
                AggregationServiceFactory aggregationServiceFactory;
                if (!hasGroupByClause)
                {
                    aggregationServiceFactory = factoryService.GetNoGroupWBinding(bindingMatchResult.Accessors, isJoin, bindingMatchResult.MethodPairs, intoTableSpec.Name, bindingMatchResult.TargetStates, bindingMatchResult.AccessStateExpr, bindingMatchResult.Agents);
                }
                else
                {
                    aggregationServiceFactory = factoryService.GetGroupWBinding(metadata, bindingMatchResult.MethodPairs, bindingMatchResult.Accessors, isJoin, intoTableSpec, bindingMatchResult.TargetStates, bindingMatchResult.AccessStateExpr, bindingMatchResult.Agents, groupByRollupDesc);
                }
                return(new AggregationServiceFactoryDesc(aggregationServiceFactory, aggregations, groupKeyExpressions));
            }

            // Assign a column number to each aggregation node. The regular aggregation goes first followed by access-aggregation.
            var columnNumber = 0;

            foreach (var entry in aggregations)
            {
                if (!entry.Factory.IsAccessAggregation)
                {
                    entry.ColumnNum = columnNumber++;
                }
            }
            foreach (var entry in aggregations)
            {
                if (entry.Factory.IsAccessAggregation)
                {
                    entry.ColumnNum = columnNumber++;
                }
            }

            // determine method aggregation factories and evaluators(non-access)
            ExprEvaluator[] methodAggEvaluators = methodAggEvaluatorsList.ToArray();
            var             methodAggFactories  = new AggregationMethodFactory[methodAggEvaluators.Length];
            var             count = 0;

            foreach (var aggregation in aggregations)
            {
                var aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation)
                {
                    methodAggFactories[count] = aggregateNode.Factory;
                    count++;
                }
            }

            // handle access aggregations
            var multiFunctionAggPlan = AggregationMultiFunctionAnalysisHelper.AnalyzeAccessAggregations(aggregations);
            var accessorPairs        = multiFunctionAggPlan.AccessorPairs;
            var accessAggregations   = multiFunctionAggPlan.StateFactories;

            AggregationServiceFactory serviceFactory;

            // analyze local group by
            AggregationLocalGroupByPlan localGroupByPlan = null;

            if (localGroupDesc != null)
            {
                localGroupByPlan = AggregationGroupByLocalGroupByAnalyzer.Analyze(methodAggEvaluators, methodAggFactories, accessAggregations, localGroupDesc, groupByNodes, accessorPairs);
                try {
                    AggregationLocalLevelHook hook = (AggregationLocalLevelHook)TypeHelper.GetAnnotationHook(annotations, HookType.INTERNAL_AGGLOCALLEVEL, typeof(AggregationLocalLevelHook), null);
                    if (hook != null)
                    {
                        hook.Planned(localGroupDesc, localGroupByPlan);
                    }
                }
                catch (ExprValidationException e) {
                    throw new EPException("Failed to obtain hook for " + HookType.INTERNAL_AGGLOCALLEVEL);
                }
            }

            // Handle without a group-by clause: we group all into the same pot
            if (!hasGroupByClause)
            {
                if (localGroupByPlan != null)
                {
                    var groupKeyBinding = methodResolutionService.GetGroupKeyBinding(localGroupByPlan);
                    serviceFactory = factoryService.GetNoGroupLocalGroupBy(isJoin, localGroupByPlan, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                {
                    serviceFactory = factoryService.GetNoGroupNoAccess(methodAggEvaluators, methodAggFactories, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else if ((methodAggEvaluators.Length == 0) && (accessorPairs.Length > 0))
                {
                    serviceFactory = factoryService.GetNoGroupAccessOnly(accessorPairs, accessAggregations, isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else
                {
                    serviceFactory = factoryService.GetNoGroupAccessMixed(methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                }
            }
            else
            {
                var hasNoReclaim          = HintEnum.DISABLE_RECLAIM_GROUP.GetHint(annotations) != null;
                var reclaimGroupAged      = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                var reclaimGroupFrequency = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                if (localGroupByPlan != null)
                {
                    var groupKeyBinding = methodResolutionService.GetGroupKeyBinding(localGroupByPlan);
                    serviceFactory = factoryService.GetGroupLocalGroupBy(isJoin, localGroupByPlan, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else
                {
                    var groupKeyBinding = methodResolutionService.GetGroupKeyBinding(groupByNodes, groupByRollupDesc);
                    if (!isDisallowNoReclaim && hasNoReclaim)
                    {
                        if (groupByRollupDesc != null)
                        {
                            throw GetRollupReclaimEx();
                        }
                        if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                        {
                            serviceFactory = factoryService.GetGroupedNoReclaimNoAccess(methodAggEvaluators, methodAggFactories, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                        else if ((methodAggEvaluators.Length == 0) && (accessorPairs.Length > 0))
                        {
                            serviceFactory = factoryService.GetGroupNoReclaimAccessOnly(accessorPairs, accessAggregations, groupKeyBinding, isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                        else
                        {
                            serviceFactory = factoryService.GetGroupNoReclaimMixed(methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                    }
                    else if (!isDisallowNoReclaim && reclaimGroupAged != null)
                    {
                        if (groupByRollupDesc != null)
                        {
                            throw GetRollupReclaimEx();
                        }
                        serviceFactory = factoryService.GetGroupReclaimAged(methodAggEvaluators, methodAggFactories, reclaimGroupAged, reclaimGroupFrequency, variableService, accessorPairs, accessAggregations, isJoin, groupKeyBinding, optionalContextName, isUnidirectional, isFireAndForget, isOnSelect);
                    }
                    else if (groupByRollupDesc != null)
                    {
                        serviceFactory = factoryService.GetGroupReclaimMixableRollup(methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin, groupKeyBinding, groupByRollupDesc, isUnidirectional, isFireAndForget, isOnSelect);
                    }
                    else
                    {
                        if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                        {
                            serviceFactory = factoryService.GetGroupReclaimNoAccess(methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                        else
                        {
                            serviceFactory = factoryService.GetGroupReclaimMixable(methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin, groupKeyBinding, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                    }
                }
            }

            return(new AggregationServiceFactoryDesc(serviceFactory, aggregations, groupKeyExpressions));
        }
Example #26
0
 private static bool DetermineTableAccessFilterStream(ExprNode exprNode)
 {
     ExprNodeTableAccessFinderVisitor visitor = new ExprNodeTableAccessFinderVisitor();
     exprNode.Accept(visitor);
     return visitor.HasTableAccess;
 }
Example #27
0
        private object GetFirstObjectFromMember(ExprNode memberExp, List<Node> suffixes)
        {
            if (memberExp is SelfExpression)
            {
                return Context.CurrentFrame.Resolve("this");
            }
            if (memberExp is Identifier)
            {
                var id = ((Identifier)memberExp).Value;
                if (Context.CurrentFrame.Exist(id))
                    return Context.CurrentFrame.Resolve(id);

                // TODO handle nested type
                // propably CLR type
                if (!(suffixes[0] is TypeDescriptorSuffix) && Context.IsClrType(id))
                    return Context.LoadTypeFromName(id);

                // start with namespace?  attempt further
                for (int i = 0; i < suffixes.Count; i++)
                {
                    var suffix = suffixes[i];
                    if (suffix is IndexSuffix)
                        break;

                    if (suffix is TypeDescriptorSuffix)
                    {
                        var typeParams = (Type[])suffix.Accept(this);
                        suffixes.RemoveRange(0, i + 1);
                        return Context.LoadTypeFromName(id, typeParams);
                    }

                    id += "." + suffix.SuffixValue(this);
                    if (i < suffixes.Count - 1 && (suffixes[i + 1] is TypeDescriptorSuffix))
                    {
                        var typeParams = (Type[])suffixes[i + 1].Accept(this);
                        suffixes.RemoveRange(0, i + 2);
                        return Context.LoadTypeFromName(id, typeParams);
                    }

                    if (Context.IsClrType(id))
                    {
                        suffixes.RemoveRange(0, i + 1);
                        return Context.LoadTypeFromName(id);
                    }
                }

                if (id.IndexOf('.') >= 0)
                    id = id.Substring(0, id.IndexOf('.'));
                throw ErrorFactory.CreateNotDefinedError(id);
            }
            return memberExp.Accept(this);
        }
Example #28
0
        public OutputConditionExpressionFactory(
            ExprNode whenExpressionNode,
            IList<OnTriggerSetAssignment> assignments,
            StatementContext statementContext,
            ExprNode andWhenTerminatedExpr,
            IList<OnTriggerSetAssignment> afterTerminateAssignments,
            bool isStartConditionOnCreation)
        {
            _whenExpressionNodeEval = whenExpressionNode.ExprEvaluator;
            _andWhenTerminatedExpressionNodeEval = andWhenTerminatedExpr != null ? andWhenTerminatedExpr.ExprEvaluator : null;
            _isStartConditionOnCreation = isStartConditionOnCreation;

            // determine if using variables
            var variableVisitor = new ExprNodeVariableVisitor(statementContext.VariableService);
            whenExpressionNode.Accept(variableVisitor);
            _variableNames = variableVisitor.VariableNames;

            // determine if using properties
            bool containsBuiltinProperties = ContainsBuiltinProperties(whenExpressionNode);
            if (!containsBuiltinProperties && assignments != null)
            {
                foreach (OnTriggerSetAssignment assignment in assignments)
                {
                    if (ContainsBuiltinProperties(assignment.Expression))
                    {
                        containsBuiltinProperties = true;
                    }
                }
            }
            if (!containsBuiltinProperties && _andWhenTerminatedExpressionNodeEval != null)
            {
                containsBuiltinProperties = ContainsBuiltinProperties(andWhenTerminatedExpr);
            }
            if (!containsBuiltinProperties && afterTerminateAssignments != null)
            {
                foreach (OnTriggerSetAssignment assignment in afterTerminateAssignments)
                {
                    if (ContainsBuiltinProperties(assignment.Expression))
                    {
                        containsBuiltinProperties = true;
                    }
                }
            }

            if (containsBuiltinProperties)
            {
                _builtinPropertiesEventType = GetBuiltInEventType(statementContext.EventAdapterService);
            }

            if (assignments != null)
            {
                _variableReadWritePackage = new VariableReadWritePackage(
                    assignments, statementContext.VariableService, statementContext.EventAdapterService);
            }
            else
            {
                _variableReadWritePackage = null;
            }

            if (afterTerminateAssignments != null)
            {
                _variableReadWritePackageAfterTerminated = new VariableReadWritePackage(
                    afterTerminateAssignments, statementContext.VariableService, statementContext.EventAdapterService);
            }
            else
            {
                _variableReadWritePackageAfterTerminated = null;
            }
        }
Example #29
0
        private ExprNode HandlePreviousFunctions(ExprNode defineItemExpression)
        {
            var previousVisitor = new ExprNodePreviousVisitorWParent();

            defineItemExpression.Accept(previousVisitor);

            if (previousVisitor.Previous == null)
            {
                return(defineItemExpression);
            }

            foreach (var previousNodePair in previousVisitor.Previous)
            {
                var previousNode       = previousNodePair.Second;
                var matchRecogPrevNode = new ExprPreviousMatchRecognizeNode();

                if (previousNodePair.Second.ChildNodes.Count == 1)
                {
                    matchRecogPrevNode.AddChildNode(previousNode.ChildNodes[0]);
                    matchRecogPrevNode.AddChildNode(new ExprConstantNodeImpl(1));
                }
                else if (previousNodePair.Second.ChildNodes.Count == 2)
                {
                    var first  = previousNode.ChildNodes[0];
                    var second = previousNode.ChildNodes[1];
                    if ((first.IsConstantResult) && (!second.IsConstantResult))
                    {
                        matchRecogPrevNode.AddChildNode(second);
                        matchRecogPrevNode.AddChildNode(first);
                    }
                    else if ((!first.IsConstantResult) && (second.IsConstantResult))
                    {
                        matchRecogPrevNode.AddChildNode(first);
                        matchRecogPrevNode.AddChildNode(second);
                    }
                    else
                    {
                        throw new ExprValidationException("PREV operator requires a constant index");
                    }
                }

                if (previousNodePair.First == null)
                {
                    defineItemExpression = matchRecogPrevNode;
                }
                else
                {
                    ExprNodeUtility.ReplaceChildNode(previousNodePair.First, previousNodePair.Second, matchRecogPrevNode);
                }

                // store in a list per index such that we can consolidate this into a single buffer
                var index        = matchRecogPrevNode.ConstantIndexNumber;
                var callbackList = _callbacksPerIndex.Get(index);
                if (callbackList == null)
                {
                    callbackList = new List <ExprPreviousMatchRecognizeNode>();
                    _callbacksPerIndex.Put(index, callbackList);
                }
                callbackList.Add(matchRecogPrevNode);
            }

            return(defineItemExpression);
        }
Example #30
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (_prototype.IsAlias)
            {
                try
                {
                    _expressionBodyCopy = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.ALIASEXPRBODY, _expressionBodyCopy, validationContext);
                }
                catch (ExprValidationException ex)
                {
                    var message = "Error validating expression alias '" + _prototype.Name + "': " + ex.Message;
                    throw new ExprValidationException(message, ex);
                }

                _exprEvaluator = _expressionBodyCopy.ExprEvaluator;
                return(null);
            }

            if (_exprEvaluator != null)
            {
                return(null); // already evaluated
            }

            if (ChildNodes.Length > 0)
            {
                throw new IllegalStateException("Execution node has its own child nodes");
            }

            // validate chain
            var validated = _chainParameters
                            .Select(expr => ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.DECLAREDEXPRPARAM, expr, validationContext))
                            .ToList();

            _chainParameters = validated;

            // validate parameter count
            CheckParameterCount();

            // create context for expression body
            var eventTypes          = new EventType[_prototype.ParametersNames.Count];
            var streamNames         = new String[_prototype.ParametersNames.Count];
            var isIStreamOnly       = new bool[_prototype.ParametersNames.Count];
            var streamsIdsPerStream = new int[_prototype.ParametersNames.Count];
            var allStreamIdsMatch   = true;

            for (var i = 0; i < _prototype.ParametersNames.Count; i++)
            {
                var parameter = _chainParameters[i];
                streamNames[i] = _prototype.ParametersNames[i];

                if (parameter is ExprStreamUnderlyingNode)
                {
                    var und = (ExprStreamUnderlyingNode)parameter;
                    eventTypes[i]          = validationContext.StreamTypeService.EventTypes[und.StreamId];
                    isIStreamOnly[i]       = validationContext.StreamTypeService.IsIStreamOnly[und.StreamId];
                    streamsIdsPerStream[i] = und.StreamId;
                }
                else if (parameter is ExprWildcard)
                {
                    if (validationContext.StreamTypeService.EventTypes.Length != 1)
                    {
                        throw new ExprValidationException("Expression '" + _prototype.Name + "' only allows a wildcard parameter if there is a single stream available, please use a stream or tag name instead");
                    }
                    eventTypes[i]          = validationContext.StreamTypeService.EventTypes[0];
                    isIStreamOnly[i]       = validationContext.StreamTypeService.IsIStreamOnly[0];
                    streamsIdsPerStream[i] = 0;
                }
                else
                {
                    throw new ExprValidationException("Expression '" + _prototype.Name + "' requires a stream name as a parameter");
                }

                if (streamsIdsPerStream[i] != i)
                {
                    allStreamIdsMatch = false;
                }
            }

            var streamTypeService = validationContext.StreamTypeService;
            var copyTypes         = new StreamTypeServiceImpl(eventTypes, streamNames, isIStreamOnly, streamTypeService.EngineURIQualifier, streamTypeService.IsOnDemandStreams);

            copyTypes.RequireStreamNames = true;

            // validate expression body in this context
            try {
                var expressionBodyContext = new ExprValidationContext(copyTypes, validationContext);
                _expressionBodyCopy = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.DECLAREDEXPRBODY, _expressionBodyCopy, expressionBodyContext);
            }
            catch (ExprValidationException ex) {
                var message = "Error validating expression declaration '" + _prototype.Name + "': " + ex.Message;
                throw new ExprValidationException(message, ex);
            }

            // analyze child node
            var summaryVisitor = new ExprNodeSummaryVisitor();

            _expressionBodyCopy.Accept(summaryVisitor);

            var isCache = !(summaryVisitor.HasAggregation || summaryVisitor.HasPreviousPrior);

            // determine a suitable evaluation
            if (_expressionBodyCopy.IsConstantResult)
            {
                // pre-evaluated
                _exprEvaluator = new ExprDeclaredEvalConstant(
                    _expressionBodyCopy.ExprEvaluator.ReturnType, _prototype,
                    _expressionBodyCopy.ExprEvaluator.Evaluate(new EvaluateParams(null, true, null)));
            }
            else if (_prototype.ParametersNames.IsEmpty() ||
                     (allStreamIdsMatch && _prototype.ParametersNames.Count == streamTypeService.EventTypes.Length))
            {
                _exprEvaluator = new ExprDeclaredEvalNoRewrite(_expressionBodyCopy.ExprEvaluator, _prototype, isCache);
            }
            else
            {
                _exprEvaluator = new ExprDeclaredEvalRewrite(_expressionBodyCopy.ExprEvaluator, _prototype, isCache, streamsIdsPerStream);
            }

            var audit = AuditEnum.EXPRDEF.GetAudit(validationContext.Annotations);

            if (audit != null)
            {
                _exprEvaluator = (ExprEvaluator)ExprEvaluatorProxy.NewInstance(validationContext.StreamTypeService.EngineURIQualifier, validationContext.StatementName, _prototype.Name, _exprEvaluator);
            }

            return(null);
        }
Example #31
0
        public static AggregationServiceForgeDesc GetService(
            IList<ExprAggregateNode> selectAggregateExprNodes,
            IDictionary<ExprNode, string> selectClauseNamedNodes,
            IList<ExprDeclaredNode> declaredExpressions,
            ExprNode[] groupByNodes,
            MultiKeyClassRef groupByMultiKey,
            IList<ExprAggregateNode> havingAggregateExprNodes,
            IList<ExprAggregateNode> orderByAggregateExprNodes,
            IList<ExprAggregateNodeGroupKey> groupKeyExpressions,
            bool hasGroupByClause,
            Attribute[] annotations,
            VariableCompileTimeResolver variableCompileTimeResolver,
            bool isDisallowNoReclaim,
            ExprNode whereClause,
            ExprNode havingClause,
            EventType[] typesPerStream,
            AggregationGroupByRollupDescForge groupByRollupDesc,
            string optionalContextName,
            IntoTableSpec intoTableSpec,
            TableCompileTimeResolver tableCompileTimeResolver,
            bool isUnidirectional,
            bool isFireAndForget,
            bool isOnSelect,
            ImportServiceCompileTime importService,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            // No aggregates used, we do not need this service
            if (selectAggregateExprNodes.IsEmpty() && havingAggregateExprNodes.IsEmpty()) {
                if (intoTableSpec != null) {
                    throw new ExprValidationException("Into-table requires at least one aggregation function");
                }

                return new AggregationServiceForgeDesc(
                    AggregationServiceNullFactory.INSTANCE,
                    EmptyList<AggregationServiceAggExpressionDesc>.Instance,
                    EmptyList<ExprAggregateNodeGroupKey>.Instance,
                    EmptyList<StmtClassForgeableFactory>.Instance);
            }

            // Validate the absence of "prev" function in where-clause:
            // Since the "previous" function does not post remove stream results, disallow when used with aggregations.
            if (whereClause != null || havingClause != null) {
                var visitor = new ExprNodePreviousVisitorWParent();
                whereClause?.Accept(visitor);

                havingClause?.Accept(visitor);

                if (visitor.Previous != null && !visitor.Previous.IsEmpty()) {
                    string funcname = visitor.Previous[0]
                        .Second.PreviousType.ToString()
                        .ToLowerInvariant();
                    throw new ExprValidationException(
                        "The '" +
                        funcname +
                        "' function may not occur in the where-clause or having-clause of a statement with aggregations as 'previous' does not provide remove stream data; Use the 'first','last','window' or 'count' aggregation functions instead");
                }
            }

            // Compile a map of aggregation nodes and equivalent-to aggregation nodes.
            // Equivalent-to functions are for example "select sum(a*b), 5*sum(a*b)".
            // Reducing the total number of aggregation functions.
            var aggregations = new List<AggregationServiceAggExpressionDesc>();
            var intoTableNonRollup = groupByRollupDesc == null && intoTableSpec != null;
            foreach (var selectAggNode in selectAggregateExprNodes) {
                AddEquivalent(selectAggNode, aggregations, intoTableNonRollup);
            }

            foreach (var havingAggNode in havingAggregateExprNodes) {
                AddEquivalent(havingAggNode, aggregations, intoTableNonRollup);
            }

            foreach (var orderByAggNode in orderByAggregateExprNodes) {
                AddEquivalent(orderByAggNode, aggregations, intoTableNonRollup);
            }

            // Construct a list of evaluation node for the aggregation functions (regular agg).
            // For example "sum(2 * 3)" would make the sum an evaluation node.
            IList<ExprForge[]> methodAggForgesList = new List<ExprForge[]>();
            foreach (var aggregation in aggregations) {
                var aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation) {
                    var forges = aggregateNode.Factory.GetMethodAggregationForge(
                        typesPerStream.Length > 1,
                        typesPerStream);
                    methodAggForgesList.Add(forges);
                }
            }

            // determine local group-by, report when hook provided
            var localGroupDesc = AnalyzeLocalGroupBy(aggregations, groupByNodes, groupByRollupDesc, intoTableSpec);

            // determine binding
            if (intoTableSpec != null) {
                // obtain metadata
                var metadata = tableCompileTimeResolver.Resolve(intoTableSpec.Name);
                if (metadata == null) {
                    throw new ExprValidationException(
                        "Invalid into-table clause: Failed to find table by name '" + intoTableSpec.Name + "'");
                }

                EPLValidationUtil.ValidateContextName(
                    true,
                    intoTableSpec.Name,
                    metadata.OptionalContextName,
                    optionalContextName,
                    false);

                // validate group keys
                var groupByTypes = ExprNodeUtilityQuery.GetExprResultTypes(groupByNodes);
                var keyTypes = metadata.IsKeyed ? metadata.KeyTypes : new Type[0];
                ExprTableNodeUtil.ValidateExpressions(
                    intoTableSpec.Name,
                    groupByTypes,
                    "group-by",
                    groupByNodes,
                    keyTypes,
                    "group-by");

                // determine how this binds to existing aggregations, assign column numbers
                var bindingMatchResult = MatchBindingsAssignColumnNumbers(
                    intoTableSpec,
                    metadata,
                    aggregations,
                    selectClauseNamedNodes,
                    methodAggForgesList,
                    declaredExpressions,
                    importService,
                    raw.StatementName);

                // return factory
                AggregationServiceFactoryForge serviceForgeX = new AggregationServiceFactoryForgeTable(
                    metadata,
                    bindingMatchResult.MethodPairs,
                    bindingMatchResult.TargetStates,
                    bindingMatchResult.Agents,
                    groupByRollupDesc);
                return new AggregationServiceForgeDesc(serviceForgeX, aggregations, groupKeyExpressions, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            // Assign a column number to each aggregation node. The regular aggregation goes first followed by access-aggregation.
            var columnNumber = 0;
            foreach (var entry in aggregations) {
                if (!entry.Factory.IsAccessAggregation) {
                    entry.SetColumnNum(columnNumber++);
                }
            }

            foreach (var entry in aggregations) {
                if (entry.Factory.IsAccessAggregation) {
                    entry.SetColumnNum(columnNumber++);
                }
            }

            // determine method aggregation factories and evaluators(non-access)
            var methodAggForges = methodAggForgesList.ToArray();
            var methodAggFactories = new AggregationForgeFactory[methodAggForges.Length];
            var count = 0;
            foreach (var aggregation in aggregations) {
                var aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation) {
                    methodAggFactories[count] = aggregateNode.Factory;
                    count++;
                }
            }

            // handle access aggregations
            var multiFunctionAggPlan = AggregationMultiFunctionAnalysisHelper.AnalyzeAccessAggregations(
                aggregations,
                importService,
                isFireAndForget,
                raw.StatementName,
                groupByNodes);
            var accessorPairsForge = multiFunctionAggPlan.AccessorPairsForge;
            var accessFactories = multiFunctionAggPlan.StateFactoryForges;
            var hasAccessAgg = accessorPairsForge.Length > 0;
            var hasMethodAgg = methodAggFactories.Length > 0;

            AggregationServiceFactoryForge serviceForge;
            var useFlags = new AggregationUseFlags(isUnidirectional, isFireAndForget, isOnSelect);
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            // analyze local group by
            AggregationLocalGroupByPlanForge localGroupByPlan = null;
            if (localGroupDesc != null) {
                AggregationLocalGroupByPlanDesc plan = AggregationGroupByLocalGroupByAnalyzer.Analyze(
                    methodAggForges,
                    methodAggFactories,
                    accessFactories,
                    localGroupDesc,
                    groupByNodes,
                    groupByMultiKey,
                    accessorPairsForge,
                    raw,
                    serdeResolver);
                localGroupByPlan = plan.Forge;
                additionalForgeables.AddAll(plan.AdditionalForgeables);

                try {
                    var hook = (AggregationLocalLevelHook) ImportUtil.GetAnnotationHook(
                        annotations,
                        HookType.INTERNAL_AGGLOCALLEVEL,
                        typeof(AggregationLocalLevelHook),
                        importService);
                    hook?.Planned(localGroupDesc, localGroupByPlan);
                }
                catch (ExprValidationException) {
                    throw new EPException("Failed to obtain hook for " + HookType.INTERNAL_AGGLOCALLEVEL);
                }
            }

            // Handle without a group-by clause: we group all into the same pot
            var rowStateDesc = new AggregationRowStateForgeDesc(
                hasMethodAgg ? methodAggFactories : null,
                hasMethodAgg ? methodAggForges : null,
                hasAccessAgg ? accessFactories : null,
                hasAccessAgg ? accessorPairsForge : null,
                useFlags);
            if (!hasGroupByClause) {
                if (localGroupByPlan != null) {
                    serviceForge = new AggSvcLocalGroupByForge(false, localGroupByPlan, useFlags);
                }
                else {
                    serviceForge = new AggregationServiceGroupAllForge(rowStateDesc);
                }
            }
            else {
                var groupDesc = new AggGroupByDesc(
                    rowStateDesc,
                    isUnidirectional,
                    isFireAndForget,
                    isOnSelect,
                    groupByNodes,
                    groupByMultiKey);
                var hasNoReclaim = HintEnum.DISABLE_RECLAIM_GROUP.GetHint(annotations) != null;
                var reclaimGroupAged = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                var reclaimGroupFrequency = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                if (localGroupByPlan != null) {
                    serviceForge = new AggSvcLocalGroupByForge(true, localGroupByPlan, useFlags);
                }
                else {
                    if (!isDisallowNoReclaim && hasNoReclaim) {
                        if (groupByRollupDesc != null) {
                            throw GetRollupReclaimEx();
                        }

                        serviceForge = new AggregationServiceGroupByForge(groupDesc, importService.TimeAbacus);
                    }
                    else if (!isDisallowNoReclaim && reclaimGroupAged != null) {
                        if (groupByRollupDesc != null) {
                            throw GetRollupReclaimEx();
                        }

                        CompileReclaim(
                            groupDesc,
                            reclaimGroupAged,
                            reclaimGroupFrequency,
                            variableCompileTimeResolver,
                            optionalContextName);
                        serviceForge = new AggregationServiceGroupByForge(groupDesc, importService.TimeAbacus);
                    }
                    else if (groupByRollupDesc != null) {
                        serviceForge = new AggSvcGroupByRollupForge(rowStateDesc, groupByRollupDesc, groupByNodes);
                    }
                    else {
                        groupDesc.IsRefcounted = true;
                        serviceForge = new AggregationServiceGroupByForge(groupDesc, importService.TimeAbacus);
                    }
                }
            }

            return new AggregationServiceForgeDesc(serviceForge, aggregations, groupKeyExpressions, additionalForgeables);
        }