Example #1
0
        protected override AggregationMethodFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            const string message          = "The nth aggregation function requires two parameters, an expression returning aggregation values and a numeric index constant";
            var          positionalParams = PositionalParams;

            if (positionalParams.Length != 2)
            {
                throw new ExprValidationException(message);
            }

            ExprNode first  = positionalParams[0];
            ExprNode second = positionalParams[1];

            if (!second.IsConstantResult)
            {
                throw new ExprValidationException(message);
            }

            var num  = second.ExprEvaluator.Evaluate(new EvaluateParams(null, true, validationContext.ExprEvaluatorContext));
            var size = num.AsInt();

            var optionalFilter = OptionalFilter;

            if (optionalFilter != null)
            {
                PositionalParams = ExprNodeUtility.AddExpression(positionalParams, optionalFilter);
            }


            return(validationContext.EngineImportService.AggregationFactoryFactory.MakeNth(validationContext.StatementExtensionSvcContext, this, first.ExprEvaluator.ReturnType, size));
        }
        private LinearAggregationFactoryDesc HandleNonIntoTable(
            ExprNode[] childNodes,
            AggregationStateType stateType,
            ExprValidationContext validationContext)
        {
            var streamTypeService = validationContext.StreamTypeService;
            int streamNum;
            Type resultType;
            ExprEvaluator evaluator;
            ExprNode evaluatorIndex = null;
            bool istreamOnly;
            EventType containedType;
            Type scalarCollectionComponentType = null;

            // validate wildcard use
            var isWildcard = childNodes.Length == 0 || childNodes.Length > 0 && childNodes[0] is ExprWildcard;
            if (isWildcard)
            {
                ExprAggMultiFunctionUtil.ValidateWildcardStreamNumbers(
                    validationContext.StreamTypeService, stateType.ToString().ToLowerInvariant());
                streamNum = 0;
                containedType = streamTypeService.EventTypes[0];
                resultType = containedType.UnderlyingType;
                var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(containedType);
                evaluator = ExprNodeUtility.MakeUnderlyingEvaluator(0, resultType, tableMetadata);
                istreamOnly = GetIstreamOnly(streamTypeService, 0);
                if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams)
                    throw MakeUnboundValidationEx(stateType);
            }
            else if (childNodes.Length > 0 && childNodes[0] is ExprStreamUnderlyingNode)
            {
                // validate "stream.*"
                streamNum = ExprAggMultiFunctionUtil.ValidateStreamWildcardGetStreamNum(childNodes[0]);
                istreamOnly = GetIstreamOnly(streamTypeService, streamNum);
                if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams)
                    throw MakeUnboundValidationEx(stateType);
                var type = streamTypeService.EventTypes[streamNum];
                containedType = type;
                resultType = type.UnderlyingType;
                var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(type);
                evaluator = ExprNodeUtility.MakeUnderlyingEvaluator(streamNum, resultType, tableMetadata);
            }
            else
            {
                // validate when neither wildcard nor "stream.*"
                var child = childNodes[0];
                var streams = ExprNodeUtility.GetIdentStreamNumbers(child);
                if (streams.IsEmpty() || streams.Count > 1)
                    throw new ExprValidationException(GetErrorPrefix(stateType) +
                                                      " requires that any child expressions evaluate properties of the same stream; Use 'firstever' or 'lastever' or 'nth' instead");
                streamNum = streams.First();
                istreamOnly = GetIstreamOnly(streamTypeService, streamNum);
                if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams)
                    throw MakeUnboundValidationEx(stateType);
                resultType = childNodes[0].ExprEvaluator.ReturnType;
                evaluator = childNodes[0].ExprEvaluator;
                if (streamNum >= streamTypeService.EventTypes.Length)
                    containedType = streamTypeService.EventTypes[0];
                else
                    containedType = streamTypeService.EventTypes[streamNum];
                scalarCollectionComponentType = resultType;
            }

            if (childNodes.Length > 1)
            {
                if (stateType == AggregationStateType.WINDOW)
                    throw new ExprValidationException(GetErrorPrefix(stateType) +
                                                      " does not accept an index expression; Use 'first' or 'last' instead");
                evaluatorIndex = childNodes[1];
                if (!evaluatorIndex.ExprEvaluator.ReturnType.IsInt32()) {
                    throw new ExprValidationException(
                        GetErrorPrefix(stateType) +
                        " requires an index expression that returns an integer value");
                }
            }

            // determine accessor
            AggregationAccessor accessor;
            if (evaluatorIndex != null)
            {
                var isFirst = stateType == AggregationStateType.FIRST;
                var constant = -1;
                if (evaluatorIndex.IsConstantResult)
                    constant = evaluatorIndex.ExprEvaluator.Evaluate(EvaluateParams.EmptyTrue).AsInt();
                accessor = new AggregationAccessorFirstLastIndexWEval(streamNum, evaluator,
                    evaluatorIndex.ExprEvaluator, constant, isFirst);
            }
            else
            {
                if (stateType == AggregationStateType.FIRST)
                    accessor = new AggregationAccessorFirstWEval(streamNum, evaluator);
                else if (stateType == AggregationStateType.LAST)
                    accessor = new AggregationAccessorLastWEval(streamNum, evaluator);
                else if (stateType == AggregationStateType.WINDOW)
                    accessor = new AggregationAccessorWindowWEval(streamNum, evaluator, resultType);
                else
                    throw new IllegalStateException("Access type is undefined or not known as code '" + stateType +
                                                    "'");
            }

            var accessorResultType = resultType;
            if (stateType == AggregationStateType.WINDOW) accessorResultType = TypeHelper.GetArrayType(resultType);

            var isFafWindow = streamTypeService.IsOnDemandStreams && stateType == AggregationStateType.WINDOW;
            var tableMetadataX = validationContext.TableService.GetTableMetadataFromEventType(containedType);

            var optionalFilter = OptionalFilter;

            if (tableMetadataX == null && !isFafWindow && (istreamOnly || streamTypeService.IsOnDemandStreams))
            {
                if (optionalFilter != null)
                    PositionalParams = ExprNodeUtility.AddExpression(PositionalParams, optionalFilter);
                var factory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinearUnbounded(
                    validationContext.StatementExtensionSvcContext, this, containedType, accessorResultType, streamNum,
                    optionalFilter != null);
                return new LinearAggregationFactoryDesc(factory, containedType, scalarCollectionComponentType);
            }

            var stateKey = new AggregationStateKeyWStream(
                streamNum, containedType,
                AggregationStateTypeWStream.DATAWINDOWACCESS_LINEAR, 
                new ExprNode[0], optionalFilter);

            var optionalFilterEval = optionalFilter?.ExprEvaluator;
            var stateFactory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinear(
                validationContext.StatementExtensionSvcContext, this, streamNum, optionalFilterEval);
            var factoryX = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, accessorResultType,
                containedType,
                stateKey, stateFactory, AggregationAgentDefault.INSTANCE);
            var enumerationType = scalarCollectionComponentType == null ? containedType : null;
            return new LinearAggregationFactoryDesc(factoryX, enumerationType, scalarCollectionComponentType);
        }
Example #3
0
        protected override AggregationMethodFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            var positionalParams = PositionalParams;
            var parameterTypes   = new Type[positionalParams.Length];
            var constant         = new object[positionalParams.Length];
            var isConstant       = new bool[positionalParams.Length];
            var expressions      = new ExprNode[positionalParams.Length];

            var count          = 0;
            var hasDataWindows = true;
            var evaluateParams = new EvaluateParams(null, true, validationContext.ExprEvaluatorContext);

            foreach (var child in positionalParams)
            {
                if (child.IsConstantResult)
                {
                    isConstant[count] = true;
                    constant[count]   = child.ExprEvaluator.Evaluate(evaluateParams);
                }
                parameterTypes[count] = child.ExprEvaluator.ReturnType;
                expressions[count]    = child;

                if (!ExprNodeUtility.HasRemoveStreamForAggregations(child, validationContext.StreamTypeService, validationContext.IsResettingAggregations))
                {
                    hasDataWindows = false;
                }

                if (child is ExprWildcard)
                {
                    ExprAggMultiFunctionUtil.CheckWildcardNotJoinOrSubquery(validationContext.StreamTypeService, _functionName);
                    parameterTypes[count] = validationContext.StreamTypeService.EventTypes[0].UnderlyingType;
                    isConstant[count]     = false;
                    constant[count]       = null;
                }

                count++;
            }

            IDictionary <string, IList <ExprNode> > namedParameters = null;

            if (OptionalFilter != null)
            {
                namedParameters = new Dictionary <string, IList <ExprNode> >();
                namedParameters.Put("filter", Collections.SingletonList(OptionalFilter));
                positionalParams = ExprNodeUtility.AddExpression(positionalParams, OptionalFilter);
            }

            var context = new AggregationValidationContext(parameterTypes, isConstant, constant, base.IsDistinct, hasDataWindows, expressions, namedParameters);

            try
            {
                // the aggregation function factory is transient, obtain if not provided
                if (_aggregationFunctionFactory == null)
                {
                    _aggregationFunctionFactory = validationContext.EngineImportService.ResolveAggregationFactory(_functionName);
                }

                _aggregationFunctionFactory.Validate(context);
            }
            catch (Exception ex)
            {
                throw new ExprValidationException("Plug-in aggregation function '" + _functionName + "' failed validation: " + ex.Message, ex);
            }

            Type childType = null;

            if (positionalParams.Length > 0)
            {
                childType = positionalParams[0].ExprEvaluator.ReturnType;
            }

            return(validationContext.EngineImportService.AggregationFactoryFactory.MakePlugInMethod(validationContext.StatementExtensionSvcContext, this, _aggregationFunctionFactory, childType));
        }