示例#1
0
        private AggregationForgeFactoryAccessSorted HandleNonTable(ExprValidationContext validationContext)
        {
            if (positionalParams.Length == 0) {
                throw new ExprValidationException("Missing the sort criteria expression");
            }

            // validate that the streams referenced in the criteria are a single stream's
            var streams = ExprNodeUtilityQuery.GetIdentStreamNumbers(positionalParams[0]);
            if (streams.Count > 1 || streams.IsEmpty()) {
                throw new ExprValidationException(
                    ErrorPrefix + " requires that any parameter expressions evaluate properties of the same stream");
            }

            var streamNum = streams.First();

            // validate that there is a remove stream, use "ever" if not
            if (!ever &&
                ExprAggMultiFunctionLinearAccessNode.GetIstreamOnly(
                    validationContext.StreamTypeService,
                    streamNum)) {
                if (sortedwin) {
                    throw new ExprValidationException(
                        ErrorPrefix + " requires that a data window is declared for the stream");
                }
            }

            // determine typing and evaluation
            containedType = validationContext.StreamTypeService.EventTypes[streamNum];

            var componentType = containedType.UnderlyingType;
            var accessorResultType = componentType;
            AggregationAccessorForge accessor;
            var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(containedType);
            if (!sortedwin) {
                if (tableMetadata != null) {
                    accessor = new AggregationAccessorMinMaxByTable(IsMax, tableMetadata);
                }
                else {
                    accessor = new AggregationAccessorMinMaxByNonTable(IsMax);
                }
            }
            else {
                if (tableMetadata != null) {
                    accessor = new AggregationAccessorSortedTable(IsMax, componentType, tableMetadata);
                }
                else {
                    accessor = new AggregationAccessorSortedNonTable(IsMax, componentType);
                }

                accessorResultType = TypeHelper.GetArrayType(accessorResultType);
            }

            var criteriaExpressions = CriteriaExpressions;

            AggregationStateTypeWStream type;
            if (ever) {
                type = IsMax ? AggregationStateTypeWStream.MAXEVER : AggregationStateTypeWStream.MINEVER;
            }
            else {
                type = AggregationStateTypeWStream.SORTED;
            }

            var stateKey = new AggregationStateKeyWStream(
                streamNum,
                containedType,
                type,
                criteriaExpressions.First,
                optionalFilter);

            var optionalFilterForge = optionalFilter == null ? null : optionalFilter.Forge;
            var streamEventType = validationContext.StreamTypeService.EventTypes[streamNum];
            var criteriaTypes = ExprNodeUtilityQuery.GetExprResultTypes(criteriaExpressions.First);
            var sortedDesc = new
                SortedAggregationStateDesc(
                    IsMax,
                    validationContext.ImportService,
                    criteriaExpressions.First,
                    criteriaTypes,
                    criteriaExpressions.Second,
                    ever,
                    streamNum,
                    this,
                    optionalFilterForge,
                    streamEventType);

            return new AggregationForgeFactoryAccessSorted(
                this,
                accessor,
                accessorResultType,
                containedType,
                stateKey,
                sortedDesc,
                AggregationAgentDefault.INSTANCE);
        }
        private ExprAggMultiFunctionSortedMinMaxByNodeFactory HandleNonTable(ExprValidationContext validationContext)

        {
            if (PositionalParams.Length == 0)
            {
                throw new ExprValidationException("Missing the sort criteria expression");
            }

            // validate that the streams referenced in the criteria are a single stream's
            var streams = ExprNodeUtility.GetIdentStreamNumbers(PositionalParams[0]);

            if (streams.Count > 1 || streams.IsEmpty())
            {
                throw new ExprValidationException(ErrorPrefix + " requires that any parameter expressions evaluate properties of the same stream");
            }
            int streamNum = streams.First();

            // validate that there is a remove stream, use "ever" if not
            var forceEver = false;

            if (!_ever && ExprAggMultiFunctionLinearAccessNode.GetIstreamOnly(validationContext.StreamTypeService, streamNum))
            {
                if (_sortedwin)
                {
                    throw new ExprValidationException(ErrorPrefix + " requires that a data window is declared for the stream");
                }
                forceEver = true;
            }

            // determine typing and evaluation
            _containedType = validationContext.StreamTypeService.EventTypes[streamNum];

            var componentType      = _containedType.UnderlyingType;
            var accessorResultType = componentType;
            AggregationAccessor accessor;
            TableMetadata       tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(_containedType);

            if (!_sortedwin)
            {
                if (tableMetadata != null)
                {
                    accessor = new AggregationAccessorMinMaxByTable(_max, tableMetadata);
                }
                else
                {
                    accessor = new AggregationAccessorMinMaxByNonTable(_max);
                }
            }
            else
            {
                if (tableMetadata != null)
                {
                    accessor = new AggregationAccessorSortedTable(_max, componentType, tableMetadata);
                }
                else
                {
                    accessor = new AggregationAccessorSortedNonTable(_max, componentType);
                }
                accessorResultType = TypeHelper.GetArrayType(accessorResultType);
            }

            Pair <ExprNode[], bool[]> criteriaExpressions = CriteriaExpressions;

            AggregationStateTypeWStream type;

            if (_ever)
            {
                type = _max ? AggregationStateTypeWStream.MAXEVER : AggregationStateTypeWStream.MINEVER;
            }
            else
            {
                type = AggregationStateTypeWStream.SORTED;
            }
            var stateKey = new AggregationStateKeyWStream(streamNum, _containedType, type, criteriaExpressions.First);

            var stateFactoryFactory = new
                                      SortedAggregationStateFactoryFactory(validationContext.MethodResolutionService,
                                                                           ExprNodeUtility.GetEvaluators(criteriaExpressions.First),
                                                                           criteriaExpressions.Second, _ever, streamNum, this);

            return(new ExprAggMultiFunctionSortedMinMaxByNodeFactory(this, accessor, accessorResultType, _containedType, stateKey, stateFactoryFactory, AggregationAgentDefault.INSTANCE));
        }
        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);
        }
示例#4
0
        private ExprAggMultiFunctionSortedMinMaxByNodeFactory HandleNonTable(ExprValidationContext validationContext)
        {
            var positionalParams = PositionalParams;
            if (positionalParams.Length == 0)
                throw new ExprValidationException("Missing the sort criteria expression");

            // validate that the streams referenced in the criteria are a single stream's
            var streams = ExprNodeUtility.GetIdentStreamNumbers(positionalParams[0]);
            if (streams.Count > 1 || streams.IsEmpty())
                throw new ExprValidationException(
                    GetErrorPrefix() + " requires that any parameter expressions evaluate properties of the same stream");
            var streamNum = streams.First();

            // validate that there is a remove stream, use "ever" if not
            if (!_ever && ExprAggMultiFunctionLinearAccessNode.GetIstreamOnly(validationContext.StreamTypeService,
                    streamNum))
                if (_sortedwin)
                    throw new ExprValidationException(
                        GetErrorPrefix() + " requires that a data window is declared for the stream");

            // determine typing and evaluation
            _containedType = validationContext.StreamTypeService.EventTypes[streamNum];

            var componentType = _containedType.UnderlyingType;
            var accessorResultType = componentType;
            AggregationAccessor accessor;
            var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(_containedType);
            if (!_sortedwin)
            {
                if (tableMetadata != null)
                    accessor = new AggregationAccessorMinMaxByTable(IsMax, tableMetadata);
                else
                    accessor = new AggregationAccessorMinMaxByNonTable(IsMax);
            }
            else
            {
                if (tableMetadata != null)
                    accessor = new AggregationAccessorSortedTable(IsMax, componentType, tableMetadata);
                else
                    accessor = new AggregationAccessorSortedNonTable(IsMax, componentType);
                accessorResultType = TypeHelper.GetArrayType(accessorResultType);
            }

            var criteriaExpressions = CriteriaExpressions;

            AggregationStateTypeWStream type;
            if (_ever)
                type = IsMax ? AggregationStateTypeWStream.MAXEVER : AggregationStateTypeWStream.MINEVER;
            else
                type = AggregationStateTypeWStream.SORTED;

            var optionalFilter = OptionalFilter;
            var stateKey = new AggregationStateKeyWStream(
                streamNum, _containedType, type, criteriaExpressions.First, optionalFilter);

            var optionalFilterEval = optionalFilter?.ExprEvaluator;
            var stateFactoryFactory = new
                SortedAggregationStateFactoryFactory(validationContext.EngineImportService,
                    validationContext.StatementExtensionSvcContext,
                    ExprNodeUtility.GetEvaluators(criteriaExpressions.First),
                    criteriaExpressions.Second, _ever, streamNum, this, optionalFilterEval);

            return new ExprAggMultiFunctionSortedMinMaxByNodeFactory(this, accessor, accessorResultType, _containedType,
                stateKey, stateFactoryFactory, AggregationAgentDefault.INSTANCE);
        }
        private AggregationForgeFactoryAccessSorted HandleNonTable(ExprValidationContext validationContext)
        {
            if (positionalParams.Length == 0)
            {
                throw new ExprValidationException("Missing the sort criteria expression");
            }

            // validate that the streams referenced in the criteria are a single stream's
            ISet <int> streams = ExprNodeUtilityQuery.GetIdentStreamNumbers(positionalParams[0]);

            if (streams.Count > 1 || streams.IsEmpty())
            {
                throw new ExprValidationException(ErrorPrefix + " requires that any parameter expressions evaluate properties of the same stream");
            }

            int streamNum = streams.First();

            // validate that there is a remove stream, use "ever" if not
            if (!_ever && ExprAggMultiFunctionLinearAccessNode.GetIstreamOnly(validationContext.StreamTypeService, streamNum))
            {
                if (_sortedwin)
                {
                    throw new ExprValidationException(ErrorPrefix + " requires that a data window is declared for the stream");
                }
            }

            // determine typing and evaluation
            _containedType = validationContext.StreamTypeService.EventTypes[streamNum];

            Type componentType      = _containedType.UnderlyingType;
            Type accessorResultType = componentType;
            AggregationAccessorForge accessor;
            TableMetaData            tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(_containedType);

            if (!_sortedwin)
            {
                if (tableMetadata != null)
                {
                    accessor = new AggregationAccessorMinMaxByTable(_max, tableMetadata);
                }
                else
                {
                    accessor = new AggregationAccessorMinMaxByNonTable(_max);
                }
            }
            else
            {
                if (tableMetadata != null)
                {
                    accessor = new AggregationAccessorSortedTable(_max, componentType, tableMetadata);
                }
                else
                {
                    accessor = new AggregationAccessorSortedNonTable(_max, componentType);
                }

                accessorResultType = TypeHelper.GetArrayType(accessorResultType);
            }

            Pair <ExprNode[], bool[]> criteriaExpressions = CriteriaExpressions;

            AggregationStateTypeWStream type;

            if (_ever)
            {
                type = _max ? AggregationStateTypeWStream.MAXEVER : AggregationStateTypeWStream.MINEVER;
            }
            else
            {
                type = AggregationStateTypeWStream.SORTED;
            }

            AggregationStateKeyWStream stateKey = new AggregationStateKeyWStream(streamNum, _containedType, type, criteriaExpressions.First, optionalFilter);

            ExprForge optionalFilterForge = optionalFilter == null ? null : optionalFilter.Forge;
            EventType streamEventType     = validationContext.StreamTypeService.EventTypes[streamNum];

            Type[] criteriaTypes = ExprNodeUtilityQuery.GetExprResultTypes(criteriaExpressions.First);
            DataInputOutputSerdeForge[] criteriaSerdes = new DataInputOutputSerdeForge[criteriaTypes.Length];
            for (int i = 0; i < criteriaTypes.Length; i++)
            {
                criteriaSerdes[i] = validationContext.SerdeResolver.SerdeForAggregation(criteriaTypes[i], validationContext.StatementRawInfo);
            }

            SortedAggregationStateDesc sortedDesc = new
                                                    SortedAggregationStateDesc(
                _max,
                validationContext.ImportService,
                criteriaExpressions.First,
                criteriaTypes,
                criteriaSerdes,
                criteriaExpressions.Second,
                _ever,
                streamNum,
                this,
                optionalFilterForge,
                streamEventType);

            IList <StmtClassForgeableFactory> serdeForgables = SerdeEventTypeUtility.Plan(
                _containedType,
                validationContext.StatementRawInfo,
                validationContext.SerdeEventTypeRegistry,
                validationContext.SerdeResolver);

            validationContext.AdditionalForgeables.AddAll(serdeForgables);

            return(new AggregationForgeFactoryAccessSorted(
                       this,
                       accessor,
                       accessorResultType,
                       _containedType,
                       stateKey,
                       sortedDesc,
                       AggregationAgentDefault.INSTANCE));
        }
        private AggregationLinearFactoryDesc HandleNonIntoTable(
            ExprNode[] childNodes,
            AggregationAccessorLinearType?stateType,
            ExprValidationContext validationContext)
        {
            var       streamTypeService = validationContext.StreamTypeService;
            int       streamNum;
            Type      resultType;
            ExprForge forge;
            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?.GetNameInvariant());
                streamNum     = 0;
                containedType = streamTypeService.EventTypes[0];
                resultType    = containedType.UnderlyingType;
                var tableMetadataX = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(containedType);
                forge       = ExprNodeUtilityMake.MakeUnderlyingForge(0, resultType, tableMetadataX);
                istreamOnly = GetIstreamOnly(streamTypeService, 0);
                if ((stateType == AggregationAccessorLinearType.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 == AggregationAccessorLinearType.WINDOW) && istreamOnly && !streamTypeService.IsOnDemandStreams)
                {
                    throw MakeUnboundValidationEx(stateType);
                }

                var type = streamTypeService.EventTypes[streamNum];
                containedType = type;
                resultType    = type.UnderlyingType;
                var tableMetadataX = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(type);
                forge = ExprNodeUtilityMake.MakeUnderlyingForge(streamNum, resultType, tableMetadataX);
            }
            else
            {
                // validate when neither wildcard nor "stream.*"
                var child   = childNodes[0];
                var streams = ExprNodeUtilityQuery.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 == AggregationAccessorLinearType.WINDOW) && istreamOnly && !streamTypeService.IsOnDemandStreams)
                {
                    throw MakeUnboundValidationEx(stateType);
                }

                resultType = childNodes[0].Forge.EvaluationType;
                forge      = childNodes[0].Forge;
                if (streamNum >= streamTypeService.EventTypes.Length)
                {
                    containedType = streamTypeService.EventTypes[0];
                }
                else
                {
                    containedType = streamTypeService.EventTypes[streamNum];
                }

                scalarCollectionComponentType = resultType;
            }

            if (childNodes.Length > 1)
            {
                if (stateType == AggregationAccessorLinearType.WINDOW)
                {
                    throw new ExprValidationException(GetErrorPrefix(stateType) + " does not accept an index expression; Use 'first' or 'last' instead");
                }

                evaluatorIndex = childNodes[1];
                var indexResultType = evaluatorIndex.Forge.EvaluationType;
                if (indexResultType != typeof(int?) && indexResultType != typeof(int))
                {
                    throw new ExprValidationException(GetErrorPrefix(stateType) + " requires an index expression that returns an integer value");
                }
            }

            // determine accessor
            AggregationAccessorForge accessor;

            if (evaluatorIndex != null)
            {
                var       isFirst  = stateType == AggregationAccessorLinearType.FIRST;
                var       constant = -1;
                ExprForge forgeIndex;
                if (evaluatorIndex.Forge.ForgeConstantType.IsCompileTimeConstant)
                {
                    constant   = evaluatorIndex.Forge.ExprEvaluator.Evaluate(null, true, null).AsInt32();
                    forgeIndex = null;
                }
                else
                {
                    forgeIndex = evaluatorIndex.Forge;
                }

                accessor = new AggregationAccessorFirstLastIndexWEvalForge(streamNum, forge, forgeIndex, constant, isFirst);
            }
            else
            {
                if (stateType == AggregationAccessorLinearType.FIRST)
                {
                    accessor = new AggregationAccessorFirstWEvalForge(streamNum, forge);
                }
                else if (stateType == AggregationAccessorLinearType.LAST)
                {
                    accessor = new AggregationAccessorLastWEvalForge(streamNum, forge);
                }
                else if (stateType == AggregationAccessorLinearType.WINDOW)
                {
                    accessor = new AggregationAccessorWindowWEvalForge(streamNum, forge, resultType);
                }
                else
                {
                    throw new IllegalStateException("Access type is undefined or not known as code '" + stateType + "'");
                }
            }

            var accessorResultType = resultType;

            if (stateType == AggregationAccessorLinearType.WINDOW)
            {
                accessorResultType = TypeHelper.GetArrayType(resultType);
            }

            var isFafWindow   = streamTypeService.IsOnDemandStreams && stateType == AggregationAccessorLinearType.WINDOW;
            var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(containedType);

            if (tableMetadata == null && !isFafWindow && (istreamOnly || streamTypeService.IsOnDemandStreams))
            {
                if (optionalFilter != null)
                {
                    positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
                }

                var serde = validationContext.SerdeResolver.SerdeForAggregation(accessorResultType, validationContext.StatementRawInfo);
                AggregationForgeFactory factoryX = new AggregationForgeFactoryFirstLastUnbound(this, accessorResultType, optionalFilter != null, serde);
                return(new AggregationLinearFactoryDesc(factoryX, containedType, scalarCollectionComponentType, streamNum));
            }

            var stateKey = new AggregationStateKeyWStream(
                streamNum,
                containedType,
                AggregationStateTypeWStream.DATAWINDOWACCESS_LINEAR,
                ExprNodeUtilityQuery.EMPTY_EXPR_ARRAY,
                optionalFilter);

            var optionalFilterForge = optionalFilter == null ? null : optionalFilter.Forge;
            AggregationStateFactoryForge stateFactory = new AggregationStateLinearForge(this, streamNum, optionalFilterForge);

            var factory = new AggregationForgeFactoryAccessLinear(
                this,
                accessor,
                accessorResultType,
                stateKey,
                stateFactory,
                AggregationAgentDefault.INSTANCE,
                containedType);
            var enumerationType = scalarCollectionComponentType == null ? containedType : null;

            var serdeForgables = SerdeEventTypeUtility.Plan(
                containedType,
                validationContext.StatementRawInfo,
                validationContext.SerdeEventTypeRegistry,
                validationContext.SerdeResolver);

            validationContext.AdditionalForgeables.AddAll(serdeForgables);

            return(new AggregationLinearFactoryDesc(factory, enumerationType, scalarCollectionComponentType, streamNum));
        }
示例#7
0
        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().ToLower());
                streamNum     = 0;
                containedType = streamTypeService.EventTypes[0];
                resultType    = containedType.UnderlyingType;
                TableMetadata 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);
                }
            }
            // validate "stream.*"
            else if (childNodes.Length > 0 && childNodes[0] is ExprStreamUnderlyingNode)
            {
                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;
                TableMetadata tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(type);
                evaluator = ExprNodeUtility.MakeUnderlyingEvaluator(streamNum, resultType, tableMetadata);
            }
            // validate when neither wildcard nor "stream.*"
            else
            {
                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 != typeof(int?))
                {
                    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(new EvaluateParams(null, true, null)).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;
            TableMetadata tableMetadataX = validationContext.TableService.GetTableMetadataFromEventType(containedType);

            if (tableMetadataX == null && !isFafWindow && (istreamOnly || streamTypeService.IsOnDemandStreams))
            {
                var factoryX = new ExprAggMultiFunctionLinearAccessNodeFactoryMethod(this, containedType, accessorResultType, streamNum);
                return(new LinearAggregationFactoryDesc(factoryX, containedType, scalarCollectionComponentType));
            }

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

            ExprNode me           = this;
            var      theStreamNum = streamNum;
            AggregationStateFactory stateFactory = new ProxyAggregationStateFactory
            {
                ProcCreateAccess = (methodResolutionService, agentInstanceId, groupId, aggregationId, join, groupKey, passThru) =>
                {
                    if (join)
                    {
                        return(methodResolutionService.MakeAccessAggLinearJoin(agentInstanceId, groupId, aggregationId, theStreamNum, passThru));
                    }
                    return(methodResolutionService.MakeAccessAggLinearNonJoin(agentInstanceId, groupId, aggregationId, theStreamNum, passThru));
                },

                ProcAggregationExpression = () => me
            };

            var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, accessorResultType, containedType,
                                                                                stateKey, stateFactory, AggregationAgentDefault.INSTANCE);
            var enumerationType = scalarCollectionComponentType == null ? containedType : null;

            return(new LinearAggregationFactoryDesc(factory, enumerationType, scalarCollectionComponentType));
        }