public ExprAggMultiFunctionLinearAccessNodeFactoryAccess(ExprAggMultiFunctionLinearAccessNode parent, AggregationAccessor accessor, Type accessorResultType, EventType containedEventType, AggregationStateKey optionalStateKey, AggregationStateFactory optionalStateFactory, AggregationAgent optionalAgent) { _parent = parent; _accessor = accessor; _accessorResultType = accessorResultType; _containedEventType = containedEventType; _optionalStateKey = optionalStateKey; _optionalStateFactory = optionalStateFactory; _optionalAgent = optionalAgent; }
// Obtain those method and state factories for each level private static AggregationLocalGroupByLevel GetLevel( int levelNumber, AggregationGroupByLocalGroupLevel level, ExprEvaluator[] methodEvaluatorsAll, AggregationMethodFactory[] methodFactoriesAll, AggregationStateFactory[] stateFactoriesAll, AggregationLocalGroupByColumn[] columns, bool defaultLevel, AggregationAccessorSlotPair[] accessors) { ExprNode[] partitionExpr = level.PartitionExpr; ExprEvaluator[] partitionEvaluators = ExprNodeUtility.GetEvaluators(partitionExpr); IList<ExprEvaluator> methodEvaluators = new List<ExprEvaluator>(); IList<AggregationMethodFactory> methodFactories = new List<AggregationMethodFactory>(); IList<AggregationStateFactory> stateFactories = new List<AggregationStateFactory>(); foreach (AggregationServiceAggExpressionDesc expr in level.Expressions) { int column = expr.ColumnNum.Value; int methodOffset = -1; bool methodAgg = true; AggregationAccessorSlotPair pair = null; if (column < methodEvaluatorsAll.Length) { methodEvaluators.Add(methodEvaluatorsAll[column]); methodFactories.Add(methodFactoriesAll[column]); methodOffset = methodFactories.Count - 1; } else { // slot gives us the number of the state factory int absoluteSlot = accessors[column - methodEvaluatorsAll.Length].Slot; AggregationAccessor accessor = accessors[column - methodEvaluatorsAll.Length].Accessor; AggregationStateFactory factory = stateFactoriesAll[absoluteSlot]; int relativeSlot = stateFactories.IndexOf(factory); if (relativeSlot == -1) { stateFactories.Add(factory); relativeSlot = stateFactories.Count - 1; } methodAgg = false; pair = new AggregationAccessorSlotPair(relativeSlot, accessor); } columns[column] = new AggregationLocalGroupByColumn( defaultLevel, partitionEvaluators, methodOffset, methodAgg, pair, levelNumber); } return new AggregationLocalGroupByLevel( methodEvaluators.ToArray(), methodFactories.ToArray(), stateFactories.ToArray(), partitionEvaluators, defaultLevel); }
// handle accessor aggregation (direct data window by-group access to properties) public static AggregationMultiFunctionAnalysisResult AnalyzeAccessAggregations(IList <AggregationServiceAggExpressionDesc> aggregations) { var currentSlot = 0; var accessProviderSlots = new ArrayDeque <AggregationMFIdentifier>(); var accessorPairs = new List <AggregationAccessorSlotPair>(); var stateFactories = new List <AggregationStateFactory>(); foreach (var aggregation in aggregations) { var aggregateNode = aggregation.AggregationNode; if (!aggregateNode.Factory.IsAccessAggregation) { continue; } var providerKey = aggregateNode.Factory.GetAggregationStateKey(false); var existing = FindExisting(accessProviderSlots, providerKey, aggregateNode.OptionalLocalGroupBy); int slot; if (existing == null) { accessProviderSlots.Add(new AggregationMFIdentifier(providerKey, aggregateNode.OptionalLocalGroupBy, currentSlot)); slot = currentSlot++; AggregationStateFactory providerFactory = aggregateNode.Factory.GetAggregationStateFactory(false); stateFactories.Add(providerFactory); } else { slot = existing.Slot; } var accessor = aggregateNode.Factory.Accessor; accessorPairs.Add(new AggregationAccessorSlotPair(slot, accessor)); } var pairs = accessorPairs.ToArray(); var accessAggregations = stateFactories.ToArray(); return(new AggregationMultiFunctionAnalysisResult(pairs, accessAggregations)); }
private LinearAggregationFactoryDesc HandleCreateTable(ExprNode[] childNodes, AggregationStateType stateType, ExprValidationContext validationContext) { var message = "For tables columns, the " + stateType.GetName().ToLower() + " aggregation function requires the 'window(*)' declaration"; if (stateType != AggregationStateType.WINDOW) { throw new ExprValidationException(message); } if (childNodes.Length == 0 || childNodes.Length > 1 || !(childNodes[0] is ExprWildcard)) { throw new ExprValidationException(message); } if (validationContext.StreamTypeService.StreamNames.Length == 0) { throw new ExprValidationException(GetErrorPrefix(stateType) + " requires that the event type is provided"); } var containedType = validationContext.StreamTypeService.EventTypes[0]; var componentType = containedType.UnderlyingType; AggregationAccessor accessor = new AggregationAccessorWindowNoEval(componentType); AggregationStateFactory stateFactory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinear(validationContext.StatementExtensionSvcContext, this, 0); var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, TypeHelper.GetArrayType(componentType), containedType, null, stateFactory, null); return(new LinearAggregationFactoryDesc(factory, factory.ContainedEventType, null)); }
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]); AggregationStateFactory stateFactory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinear( validationContext.StatementExtensionSvcContext, this, streamNum); var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, accessorResultType, containedType, stateKey, stateFactory, AggregationAgentDefault.INSTANCE); var enumerationType = scalarCollectionComponentType == null ? containedType : null; return(new LinearAggregationFactoryDesc(factory, enumerationType, scalarCollectionComponentType)); }
private TableAccessAnalysisResult AnalyzePlanAggregations( string tableName, StatementContext statementContext, IList <TableColumnDesc> columns, EPServicesContext services, string internalTypeName, string publicTypeName) { // once upfront: obtains aggregation factories for each aggregation // we do this once as a factory may be a heavier object IDictionary <TableColumnDesc, AggregationMethodFactory> aggregationFactories = new Dictionary <TableColumnDesc, AggregationMethodFactory>(); foreach (var column in columns) { if (column is TableColumnDescAgg) { var agg = (TableColumnDescAgg)column; var factory = agg.Aggregation.Factory; aggregationFactories.Put(column, factory); } } // sort into these categories: // plain / method-agg / access-agg // compile all-column public types IList <TableColumnDescTyped> plainColumns = new List <TableColumnDescTyped>(); IList <TableColumnDescAgg> methodAggColumns = new List <TableColumnDescAgg>(); IList <TableColumnDescAgg> accessAggColumns = new List <TableColumnDescAgg>(); IDictionary <string, object> allColumnsPublicTypes = new LinkedHashMap <string, object>(); foreach (var column in columns) { // handle plain types if (column is TableColumnDescTyped) { var typed = (TableColumnDescTyped)column; plainColumns.Add(typed); allColumnsPublicTypes.Put(column.ColumnName, typed.UnresolvedType); continue; } // handle aggs var agg = (TableColumnDescAgg)column; var aggFactory = aggregationFactories.Get(agg); if (aggFactory.IsAccessAggregation) { accessAggColumns.Add(agg); } else { methodAggColumns.Add(agg); } allColumnsPublicTypes.Put(column.ColumnName, agg.Aggregation.ReturnType); } // determine column metadata // IDictionary <string, TableMetadataColumn> columnMetadata = new LinkedHashMap <string, TableMetadataColumn>(); // handle typed columns IDictionary <string, object> allColumnsInternalTypes = new LinkedHashMap <string, object>(); allColumnsInternalTypes.Put(TableServiceConstants.INTERNAL_RESERVED_PROPERTY, typeof(object)); var indexPlain = 1; IList <int> groupKeyIndexes = new List <int>(); var assignPairsPlain = new TableMetadataColumnPairPlainCol[plainColumns.Count]; foreach (var typedColumn in plainColumns) { allColumnsInternalTypes.Put(typedColumn.ColumnName, typedColumn.UnresolvedType); columnMetadata.Put(typedColumn.ColumnName, new TableMetadataColumnPlain(typedColumn.ColumnName, typedColumn.IsKey, indexPlain)); if (typedColumn.IsKey) { groupKeyIndexes.Add(indexPlain); } assignPairsPlain[indexPlain - 1] = new TableMetadataColumnPairPlainCol(typedColumn.PositionInDeclaration, indexPlain); indexPlain++; } // determine internally-used event type // for use by indexes and lookups ObjectArrayEventType internalEventType; ObjectArrayEventType publicEventType; try { internalEventType = (ObjectArrayEventType)services.EventAdapterService.AddNestableObjectArrayType(internalTypeName, allColumnsInternalTypes, null, false, false, false, false, false, true, tableName); publicEventType = (ObjectArrayEventType)services.EventAdapterService.AddNestableObjectArrayType(publicTypeName, allColumnsPublicTypes, null, false, false, false, false, false, false, null); } catch (EPException ex) { throw new ExprValidationException("Invalid type information: " + ex.Message, ex); } services.StatementEventTypeRefService.AddReferences(statementContext.StatementName, new string[] { internalTypeName, publicTypeName }); // handle aggregation-methods single-func first. var methodFactories = new AggregationMethodFactory[methodAggColumns.Count]; var index = 0; var assignPairsMethod = new TableMetadataColumnPairAggMethod[methodAggColumns.Count]; foreach (var column in methodAggColumns) { var factory = aggregationFactories.Get(column); var optionalEnumerationType = EPTypeHelper.OptionalFromEnumerationExpr(statementContext.StatementId, statementContext.EventAdapterService, column.Aggregation); methodFactories[index] = factory; columnMetadata.Put(column.ColumnName, new TableMetadataColumnAggregation(column.ColumnName, factory, index, null, optionalEnumerationType, column.OptionalAssociatedType)); assignPairsMethod[index] = new TableMetadataColumnPairAggMethod(column.PositionInDeclaration); index++; } // handle access-aggregation (sharable, multi-value) aggregations var stateFactories = new AggregationStateFactory[accessAggColumns.Count]; var assignPairsAccess = new TableMetadataColumnPairAggAccess[accessAggColumns.Count]; index = 0; foreach (var column in accessAggColumns) { var factory = aggregationFactories.Get(column); stateFactories[index] = factory.GetAggregationStateFactory(false); var pair = new AggregationAccessorSlotPair(index, factory.Accessor); var optionalEnumerationType = EPTypeHelper.OptionalFromEnumerationExpr(statementContext.StatementId, statementContext.EventAdapterService, column.Aggregation); columnMetadata.Put(column.ColumnName, new TableMetadataColumnAggregation(column.ColumnName, factory, -1, pair, optionalEnumerationType, column.OptionalAssociatedType)); assignPairsAccess[index] = new TableMetadataColumnPairAggAccess(column.PositionInDeclaration, factory.Accessor); index++; } // create state factory var groupKeyIndexesArr = CollectionUtil.IntArray(groupKeyIndexes); var stateRowFactory = new TableStateRowFactory( internalEventType, statementContext.EngineImportService, methodFactories, stateFactories, groupKeyIndexesArr, services.EventAdapterService); // create public event provision var eventToPublic = new TableMetadataInternalEventToPublic(publicEventType, assignPairsPlain, assignPairsMethod, assignPairsAccess, services.EventAdapterService); return(new TableAccessAnalysisResult(stateRowFactory, columnMetadata, methodAggColumns.Count, internalEventType, publicEventType, eventToPublic)); }