private TableAccessAnalysisResult AnalyzePlanAggregations( string tableName, IList<TableColumnDesc> columns, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { // once upfront: obtains aggregation factories for each aggregation // we do this once as a factory may be a heavier object IDictionary<TableColumnDesc, AggregationForgeFactory> aggregationFactories = new Dictionary<TableColumnDesc, AggregationForgeFactory>(); 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>(); var 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.EvaluationType); } // determine column metadata // var columnMetadata = new LinkedHashMap<string, TableMetadataColumn>(); // handle typed columns var allColumnsInternalTypes = new LinkedHashMap<string, object>(); allColumnsInternalTypes.Put(INTERNAL_RESERVED_PROPERTY, typeof(object)); var indexPlain = 1; 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)); assignPairsPlain[indexPlain - 1] = new TableMetadataColumnPairPlainCol( typedColumn.PositionInDeclaration, indexPlain); indexPlain++; } // determine internally-used event type var visibility = services.ModuleVisibilityRules.GetAccessModifierTable(@base, tableName); var internalName = EventTypeNameUtil.GetTableInternalTypeName(tableName); var internalMetadata = new EventTypeMetadata( internalName, @base.ModuleName, EventTypeTypeClass.TABLE_INTERNAL, EventTypeApplicationType.OBJECTARR, visibility, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var internalEventType = BaseNestableEventUtil.MakeOATypeCompileTime( internalMetadata, allColumnsInternalTypes, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(internalEventType); // for use by indexes and lookups var publicName = EventTypeNameUtil.GetTablePublicTypeName(tableName); var publicMetadata = new EventTypeMetadata( publicName, @base.ModuleName, EventTypeTypeClass.TABLE_PUBLIC, EventTypeApplicationType.OBJECTARR, visibility, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var publicEventType = BaseNestableEventUtil.MakeOATypeCompileTime( publicMetadata, allColumnsPublicTypes, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(publicEventType); // handle aggregation-methods single-func first. var methodFactories = new AggregationForgeFactory[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( statementRawInfo, services, column.Aggregation); methodFactories[index] = factory; var bindingInfo = factory.AggregationPortableValidation; var expression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(factory.AggregationExpression); columnMetadata.Put( column.ColumnName, new TableMetadataColumnAggregation( column.ColumnName, false, index, bindingInfo, expression, true, optionalEnumerationType)); assignPairsMethod[index] = new TableMetadataColumnPairAggMethod(column.PositionInDeclaration); index++; } // handle access-aggregation (sharable, multi-value) aggregations var stateFactories = new AggregationStateFactoryForge[accessAggColumns.Count]; var accessAccessorForges = new AggregationAccessorSlotPairForge[accessAggColumns.Count]; var assignPairsAccess = new TableMetadataColumnPairAggAccess[accessAggColumns.Count]; var accessNum = 0; foreach (var column in accessAggColumns) { var factory = aggregationFactories.Get(column); var forge = factory.GetAggregationStateFactory(false); stateFactories[accessNum] = forge; var accessor = factory.AccessorForge; var bindingInfo = factory.AggregationPortableValidation; accessAccessorForges[accessNum] = new AggregationAccessorSlotPairForge(accessNum, accessor); var expression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(factory.AggregationExpression); var optionalEnumerationType = EPTypeHelper.OptionalFromEnumerationExpr( statementRawInfo, services, column.Aggregation); columnMetadata.Put( column.ColumnName, new TableMetadataColumnAggregation( column.ColumnName, false, index, bindingInfo, expression, false, optionalEnumerationType)); assignPairsAccess[accessNum] = new TableMetadataColumnPairAggAccess(column.PositionInDeclaration, accessor); index++; accessNum++; } // determine primary key index information var primaryKeyColumns = new List<string>(); var primaryKeyTypes = new List<Type>(); var primaryKeyGetters = new List<EventPropertyGetterSPI>(); var primaryKeyColNums = new List<int>(); var colNum = -1; foreach (var typedColumn in plainColumns) { colNum++; if (typedColumn.IsKey) { primaryKeyColumns.Add(typedColumn.ColumnName); primaryKeyTypes.Add(internalEventType.GetPropertyType(typedColumn.ColumnName)); primaryKeyGetters.Add(internalEventType.GetGetterSPI(typedColumn.ColumnName)); primaryKeyColNums.Add(colNum + 1); } } string[] primaryKeyColumnArray = null; Type[] primaryKeyTypeArray = null; EventPropertyGetterSPI[] primaryKeyGetterArray = null; int[] primaryKeyColNumsArray = null; if (!primaryKeyColumns.IsEmpty()) { primaryKeyColumnArray = primaryKeyColumns.ToArray(); primaryKeyTypeArray = primaryKeyTypes.ToArray(); primaryKeyGetterArray = primaryKeyGetters.ToArray(); primaryKeyColNumsArray = primaryKeyColNums.ToArray(); } var forgeDesc = new AggregationRowStateForgeDesc( methodFactories, null, stateFactories, accessAccessorForges, new AggregationUseFlags(false, false, false)); var multiKeyPlan = MultiKeyPlanner.PlanMultiKey( primaryKeyTypeArray, false, statementRawInfo, services.SerdeResolver); var propertyForges = new DataInputOutputSerdeForge[internalEventType.PropertyNames.Length - 1]; var additionalForgeables = new List<StmtClassForgeableFactory>(multiKeyPlan.MultiKeyForgeables); for (var i = 1; i < internalEventType.PropertyNames.Length; i++) { var propertyName = internalEventType.PropertyNames[i]; var propertyType = internalEventType.Types.Get(propertyName); var desc = SerdeEventPropertyUtility.ForgeForEventProperty( publicEventType, propertyName, propertyType, statementRawInfo, services.SerdeResolver); propertyForges[i - 1] = desc.Forge; // plan serdes for nested types foreach (var eventType in desc.NestedTypes) { var serdeForgeables = SerdeEventTypeUtility.Plan( eventType, statementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } return new TableAccessAnalysisResult( columnMetadata, internalEventType, propertyForges, publicEventType, assignPairsPlain, assignPairsMethod, assignPairsAccess, forgeDesc, primaryKeyColumnArray, primaryKeyGetterArray, primaryKeyTypeArray, primaryKeyColNumsArray, multiKeyPlan.ClassRef, additionalForgeables); }
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)); }