public static FilterSpecParamForge HandleRangeNode(
            ExprBetweenNode betweenNode,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            var left = betweenNode.ChildNodes[0];
            ExprFilterSpecLookupableForge lookupable = null;

            if (left is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) left;
                lookupable = filterOptimizableNode.FilterLookupable;
            }
            else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) &&
                     IsLimitedLookupableExpression(left)) {
                lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services);
            }

            if (lookupable == null) {
                return null;
            }

            FilterOperator op = FilterOperatorExtensions.ParseRangeOperator(
                betweenNode.IsLowEndpointIncluded,
                betweenNode.IsHighEndpointIncluded,
                betweenNode.IsNotBetween);

            var low = HandleRangeNodeEndpoint(betweenNode.ChildNodes[1], taggedEventTypes, arrayEventTypes, allTagNamesOrdered, statementName, raw, services);
            var high = HandleRangeNodeEndpoint(betweenNode.ChildNodes[2], taggedEventTypes, arrayEventTypes, allTagNamesOrdered, statementName, raw, services);
            return low == null || high == null ? null : new FilterSpecParamRangeForge(lookupable, op, low, high);
        }
        private static FilterSpecParamForge HandleLimitedExpr(
            FilterOperator op,
            ExprNode lookupable,
            ExprNode value,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            ExprFilterSpecLookupableForge lookupableForge;
            var lookupableType = lookupable.Forge.EvaluationType;
            var valueType = value.Forge.EvaluationType;
            if (lookupable is ExprIdentNode) {
                if (!FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services)) {
                    return null;
                }

                var identNode = (ExprIdentNode) lookupable;
                if (!identNode.FilterLookupEligible) {
                    return null;
                }

                lookupableForge = identNode.FilterLookupable;
            }
            else {
                if (!FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services)) {
                    return null;
                }

                lookupableForge = MakeLimitedLookupableForgeMayNull(lookupable, raw, services);
                if (lookupableForge == null) {
                    return null;
                }
            }

            var convertor = GetMatchEventConvertor(value, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
            var numberCoercer = GetNumberCoercer(lookupableType, valueType, lookupableForge.Expression);
            return new FilterSpecParamValueLimitedExprForge(lookupableForge, op, value, convertor, numberCoercer);
        }
        private static FilterSpecParamFilterForEvalForge HandleRangeNodeEndpoint(
            ExprNode endpoint,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // constant
            if (endpoint.Forge.ForgeConstantType.IsCompileTimeConstant) {
                var value = endpoint.Forge.ExprEvaluator.Evaluate(null, true, null);
                if (value == null) {
                    return null;
                }

                if (value is string) {
                    return new FilterForEvalConstantStringForge((string) value);
                }

                return new FilterForEvalConstantDoubleForge(value.AsDouble());
            }

            if (endpoint is ExprContextPropertyNode) {
                var node = (ExprContextPropertyNode) endpoint;
                if (node.Type == typeof(string)) {
                    return new FilterForEvalContextPropStringForge(node.Getter, node.PropertyName);
                }

                return new FilterForEvalContextPropDoubleForge(node.Getter, node.PropertyName);
            }

            if (endpoint.Forge.ForgeConstantType.IsDeployTimeTimeConstant && endpoint is ExprNodeDeployTimeConst) {
                var node = (ExprNodeDeployTimeConst) endpoint;
                if (endpoint.Forge.EvaluationType == typeof(string)) {
                    return new FilterForEvalDeployTimeConstStringForge(node);
                }

                return new FilterForEvalDeployTimeConstDoubleForge(node);
            }

            // or property
            if (endpoint is ExprIdentNode) {
                return GetIdentNodeDoubleEval((ExprIdentNode) endpoint, arrayEventTypes, statementName);
            }

            // or limited expression
            if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                IsLimitedValueExpression(endpoint)) {
                var returnType = endpoint.Forge.EvaluationType;
                MatchedEventConvertorForge convertor = GetMatchEventConvertor(endpoint, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                if (returnType == typeof(string)) {
                    return new FilterForEvalLimitedExprForge(endpoint, convertor, null);
                }

                var coercer = SimpleNumberCoercerFactory.GetCoercer(returnType, typeof(double?));
                return new FilterForEvalLimitedExprForge(endpoint, convertor, coercer);
            }

            return null;
        }
Example #4
0
        internal static FilterSpecParamForge HandleInSetNode(
            ExprInNode constituent,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            ISet <string> allTagNamesOrdered,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            var left = constituent.ChildNodes[0];
            ExprFilterSpecLookupableForge lookupable = null;

            if (left is ExprFilterOptimizableNode)
            {
                var filterOptimizableNode = (ExprFilterOptimizableNode)left;
                lookupable = filterOptimizableNode.FilterLookupable;
            }
            else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) &&
                     IsLimitedLookupableExpression(left))
            {
                lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services);
            }

            if (lookupable == null)
            {
                return(null);
            }

            var op = FilterOperator.IN_LIST_OF_VALUES;

            if (constituent.IsNotIn)
            {
                op = FilterOperator.NOT_IN_LIST_OF_VALUES;
            }

            var expectedNumberOfConstants = constituent.ChildNodes.Length - 1;
            IList <FilterSpecParamInValueForge> listofValues = new List <FilterSpecParamInValueForge>();
            var it = Arrays.AsList(constituent.ChildNodes).GetEnumerator();

            it.MoveNext();             // ignore the first node as it's the identifier
            while (it.MoveNext())
            {
                var subNode = it.Current;
                if (subNode.Forge.ForgeConstantType.IsCompileTimeConstant)
                {
                    var constant = subNode.Forge.ExprEvaluator.Evaluate(null, true, null);
                    if (constant is ICollection <object> )
                    {
                        return(null);
                    }

                    if (constant is IDictionary <object, object> )
                    {
                        return(null);
                    }

                    if ((constant != null) && (constant is Array arrayConstant))
                    {
                        for (var i = 0; i < arrayConstant.Length; i++)
                        {
                            var arrayElement        = arrayConstant.GetValue(i);
                            var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement);
                            listofValues.Add(new FilterForEvalConstantAnyTypeForge(arrayElementCoerced));
                            if (i > 0)
                            {
                                expectedNumberOfConstants++;
                            }
                        }
                    }
                    else
                    {
                        constant = HandleConstantsCoercion(lookupable, constant);
                        listofValues.Add(new FilterForEvalConstantAnyTypeForge(constant));
                    }
                }
                else if (subNode is ExprContextPropertyNode)
                {
                    var     contextPropertyNode = (ExprContextPropertyNode)subNode;
                    var     returnType          = contextPropertyNode.Type;
                    Coercer coercer;
                    if (TypeHelper.IsCollectionMapOrArray(returnType))
                    {
                        CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression);
                        coercer = null;
                    }
                    else
                    {
                        coercer = GetNumberCoercer(left.Forge.EvaluationType, contextPropertyNode.Type, lookupable.Expression);
                    }

                    var finalReturnType = coercer != null ? coercer.ReturnType : returnType;
                    listofValues.Add(new FilterForEvalContextPropForge(contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType));
                }
                else if (subNode.Forge.ForgeConstantType.IsDeployTimeTimeConstant && subNode is ExprNodeDeployTimeConst)
                {
                    var     deployTimeConst = (ExprNodeDeployTimeConst)subNode;
                    var     returnType      = subNode.Forge.EvaluationType;
                    Coercer coercer;
                    if (TypeHelper.IsCollectionMapOrArray(returnType))
                    {
                        CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression);
                        coercer = null;
                    }
                    else
                    {
                        coercer = GetNumberCoercer(left.Forge.EvaluationType, returnType, lookupable.Expression);
                    }

                    listofValues.Add(new FilterForEvalDeployTimeConstForge(deployTimeConst, coercer, returnType));
                }
                else if (subNode is ExprIdentNode)
                {
                    var identNodeInner = (ExprIdentNode)subNode;
                    if (identNodeInner.StreamId == 0)
                    {
                        break;                         // for same event evals use the boolean expression, via count compare failing below
                    }

                    var isMustCoerce    = false;
                    var coerceToType    = Boxing.GetBoxedType(lookupable.ReturnType);
                    var identReturnType = identNodeInner.Forge.EvaluationType;

                    if (TypeHelper.IsCollectionMapOrArray(identReturnType))
                    {
                        CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression);
                        coerceToType = identReturnType;
                        // no action
                    }
                    else if (identReturnType != lookupable.ReturnType)
                    {
                        if (TypeHelper.IsNumeric(lookupable.ReturnType))
                        {
                            if (!TypeHelper.CanCoerce(identReturnType, lookupable.ReturnType))
                            {
                                ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression);
                            }

                            isMustCoerce = true;
                        }
                        else
                        {
                            break;                             // assumed not compatible
                        }
                    }

                    FilterSpecParamInValueForge inValue;
                    var streamName = identNodeInner.ResolvedStreamName;
                    if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName))
                    {
                        var indexAndProp   = GetStreamIndex(identNodeInner.ResolvedPropertyName);
                        var innerEventType = GetArrayInnerEventType(arrayEventTypes, streamName);
                        inValue = new FilterForEvalEventPropIndexedForge(
                            identNodeInner.ResolvedStreamName,
                            indexAndProp.First,
                            indexAndProp.Second,
                            innerEventType,
                            isMustCoerce,
                            coerceToType);
                    }
                    else
                    {
                        inValue = new FilterForEvalEventPropForge(
                            identNodeInner.ResolvedStreamName,
                            identNodeInner.ResolvedPropertyName,
                            identNodeInner.ExprEvaluatorIdent,
                            isMustCoerce,
                            coerceToType);
                    }

                    listofValues.Add(inValue);
                }
                else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                         IsLimitedValueExpression(subNode))
                {
                    var convertor      = GetMatchEventConvertor(subNode, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                    var valueType      = subNode.Forge.EvaluationType;
                    var lookupableType = lookupable.ReturnType;
                    var numberCoercer  = GetNumberCoercer(lookupableType, valueType, lookupable.Expression);
                    var forge          = new FilterForEvalLimitedExprForge(subNode, convertor, numberCoercer);
                    listofValues.Add(forge);
                }
            }

            // Fallback if not all values in the in-node can be resolved to properties or constants
            if (listofValues.Count == expectedNumberOfConstants)
            {
                return(new FilterSpecParamInForge(lookupable, op, listofValues));
            }

            return(null);
        }