Example #1
0
        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);
        }
Example #2
0
        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));
        }