private static List<StmtClassForgeableFactory> PlanMultikeys(
            QueryPlanIndexForge[] indexSpecs,
            StatementRawInfo raw,
            StatementCompileTimeServices compileTimeServices)
        {
            List<StmtClassForgeableFactory> multiKeyForgeables = new List<StmtClassForgeableFactory>();
            foreach (QueryPlanIndexForge spec in indexSpecs) {
                if (spec == null) {
                    continue;
                }
                foreach (var entry in spec.Items) {
                    QueryPlanIndexItemForge forge = entry.Value;

                    MultiKeyPlan plan = MultiKeyPlanner.PlanMultiKey(
                        forge.HashTypes, false, raw, compileTimeServices.SerdeResolver);
                    multiKeyForgeables.AddAll(plan.MultiKeyForgeables);
                    forge.HashMultiKeyClasses = plan.ClassRef;

                    DataInputOutputSerdeForge[] rangeSerdes = new DataInputOutputSerdeForge[forge.RangeTypes.Length];
                    for (int i = 0; i < forge.RangeTypes.Length; i++) {
                        rangeSerdes[i] = compileTimeServices.SerdeResolver.SerdeForIndexBtree(forge.RangeTypes[i], raw);
                    }
                    forge.RangeSerdes = rangeSerdes;
                }
            }
            return multiKeyForgeables;
        }
Exemplo n.º 2
0
        public override CodegenExpression Codegen(
            EnumForgeCodegenParams args,
            CodegenMethodScope codegenMethodScope,
            CodegenClassScope codegenClassScope)
        {
            var method = codegenMethodScope
                         .MakeChild(typeof(ICollection <object>), typeof(EnumDistinctOfScalarNoParams), codegenClassScope)
                         .AddParam(EnumForgeCodegenNames.PARAMS);

            method.Block
            .IfCondition(Relational(ExprDotName(EnumForgeCodegenNames.REF_ENUMCOLL, "Count"), LE, Constant(1)))
            .BlockReturn(EnumForgeCodegenNames.REF_ENUMCOLL);

            if (_fieldType == null || !_fieldType.IsArray)
            {
                method.Block
                .IfCondition(InstanceOf(Ref("enumcoll"), typeof(ISet <object>)))
                .BlockReturn(EnumForgeCodegenNames.REF_ENUMCOLL)
                .MethodReturn(NewInstance(typeof(LinkedHashSet <object>), EnumForgeCodegenNames.REF_ENUMCOLL));
            }
            else
            {
                var arrayMK = MultiKeyPlanner.GetMKClassForComponentType(_fieldType.GetElementType());
                method.Block.DeclareVar <IDictionary <object, object> >("distinct", NewInstance(typeof(LinkedHashMap <object, object>)));

                var loop = method.Block.ForEach(typeof(object), "next", EnumForgeCodegenNames.REF_ENUMCOLL);
                loop.DeclareVar(arrayMK, "comparable", NewInstance(arrayMK, Cast(_fieldType, Ref("next"))))
                .Expression(ExprDotMethod(Ref("distinct"), "Put", Ref("comparable"), Ref("next")));

                method.Block.MethodReturn(ExprDotName(Ref("distinct"), "Values"));
            }

            return(LocalMethod(method, args.Expressions));
        }
        protected CodegenExpression ToDistinctValueKey(CodegenExpression distinctValue)
        {
            if (!optionalDistinctValueType.IsArray) {
                return distinctValue;
            }

            var mktype = MultiKeyPlanner.GetMKClassForComponentType(optionalDistinctValueType.GetElementType());
            return NewInstance(mktype, Cast(optionalDistinctValueType, distinctValue));
        }
Exemplo n.º 4
0
 private static FilterValueSetParam GetFilterMayEqualOrNull(
     ExprFilterSpecLookupable lookupable,
     object keyValue)
 {
     if (keyValue != null && keyValue.GetType().IsArray) {
         keyValue = MultiKeyPlanner.ToMultiKey(keyValue);
     }
     return new FilterValueSetParamImpl(lookupable, FilterOperator.IS, keyValue);
 }
Exemplo n.º 5
0
 public override IList<StmtClassForgeableFactory> InitAdditionalForgeables(ViewForgeEnv viewForgeEnv)
 {
     var desc = MultiKeyPlanner.PlanMultiKey(
         _criteriaExpressions,
         false,
         viewForgeEnv.StatementRawInfo,
         viewForgeEnv.SerdeResolver);
     _multiKeyClassNames = desc.ClassRef;
     return desc.MultiKeyForgeables;
 }
        public override IList<StmtClassForgeableFactory> Validate(
            StreamTypeService typeService,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            int count = 0;
            ExprValidationContext validationContext =
                new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services)
                    .WithAllowBindingConsumption(true)
                    .Build();
            ExprNode[] inputParamNodes = new ExprNode[inputParameters.Length];
            foreach (string inputParam in inputParameters) {
                ExprNode raw = FindSQLExpressionNode(StreamNum, count, @base.StatementSpec.Raw.SqlParameters);
                if (raw == null) {
                    throw new ExprValidationException(
                        "Internal error find expression for historical stream parameter " +
                        count +
                        " stream " +
                        StreamNum);
                }

                ExprNode evaluator = ExprNodeUtilityValidate.GetValidatedSubtree(
                    ExprNodeOrigin.DATABASEPOLL,
                    raw,
                    validationContext);
                inputParamNodes[count++] = evaluator;

                ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor();
                visitor.Visit(evaluator);
                foreach (ExprIdentNode identNode in visitor.ExprProperties) {
                    if (identNode.StreamId == StreamNum) {
                        throw new ExprValidationException(
                            "Invalid expression '" + inputParam + "' resolves to the historical data itself");
                    }

                    SubordinateStreams.Add(identNode.StreamId);
                }
            }

            InputParamEvaluators = ExprNodeUtilityQuery.GetForges(inputParamNodes);
            
            
            // plan multikey
            MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver);
            MultiKeyClassRef = multiKeyPlan.ClassRef;

            return multiKeyPlan.MultiKeyForgeables;
        }
        public static CodegenMethod Codegen(
            ExprEqualsNodeForgeNC forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope,
            ExprForge lhs,
            ExprForge rhs)
        {
            var lhsType = lhs.EvaluationType;
            var rhsType = rhs.EvaluationType;

            var methodNode = codegenMethodScope.MakeChild(typeof(bool?), typeof(ExprEqualsNodeForgeNCForgeEquals), codegenClassScope);
            var block = methodNode.Block
                .DeclareVar(lhsType, "left", lhs.EvaluateCodegen(lhsType, methodNode, exprSymbol, codegenClassScope))
                .DeclareVar(rhsType, "right", rhs.EvaluateCodegen(rhsType, methodNode, exprSymbol, codegenClassScope));

            if (!lhsType.IsPrimitive) {
                block.IfRefNullReturnNull("left");
            }

            if (!rhsType.IsPrimitive) {
                block.IfRefNullReturnNull("right");
            }

            CodegenExpression compare;
            if (!lhsType.IsArray) {
                compare = CodegenEqualsNonNullNoCoerce(Ref("left"), lhsType, Ref("right"), rhsType);
            }
            else {
                if (!MultiKeyPlanner.RequiresDeepEquals(lhsType.GetElementType())) {
                    compare = StaticMethod(typeof(Arrays), "AreEqual", Ref("left"), Ref("right"));
                }
                else {
                    compare = StaticMethod(typeof(Arrays), "DeepEquals", Ref("left"), Ref("right"));
                }
            }

            if (!forge.ForgeRenderable.IsNotEquals) {
                block.MethodReturn(compare);
            }
            else {
                block.MethodReturn(Not(compare));
            }

            return methodNode;
        }
Exemplo n.º 8
0
        public static void ForEachBlock(
            CodegenBlock block,
            CodegenExpression eval,
            Type innerType)
        {
            if (!innerType.IsArray)
            {
                block.DeclareVar(innerType, "comparable", eval);
            }
            else
            {
                Type arrayMK = MultiKeyPlanner.GetMKClassForComponentType(innerType.GetElementType());
                block.DeclareVar(arrayMK, "comparable", NewInstance(arrayMK, eval));
            }

            block.IfCondition(Not(ExprDotMethod(Ref("distinct"), "ContainsKey", Ref("comparable"))))
            .Expression(ExprDotMethod(Ref("distinct"), "Put", Ref("comparable"), Ref("next")))
            .BlockEnd();
        }
Exemplo n.º 9
0
        private static SubordinateQueryIndexPlan PlanIndex(
            bool unique,
            IList<IndexedPropDesc> hashProps,
            IList<IndexedPropDesc> btreeProps,
            EventType eventTypeIndexed,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // not resolved as full match and not resolved as unique index match, allocate
            var indexPropKey = new IndexMultiKey(unique, hashProps, btreeProps, null);

            var indexedPropDescs = hashProps.ToArray();
            var indexProps = IndexedPropDesc.GetIndexProperties(indexedPropDescs);
            var indexCoercionTypes = IndexedPropDesc.GetCoercionTypes(indexedPropDescs);

            var rangePropDescs = btreeProps.ToArray();
            var rangeProps = IndexedPropDesc.GetIndexProperties(rangePropDescs);
            var rangeCoercionTypes = IndexedPropDesc.GetCoercionTypes(rangePropDescs);

            var indexItem = new QueryPlanIndexItemForge(
                indexProps,
                indexCoercionTypes,
                rangeProps,
                rangeCoercionTypes,
                unique,
                null,
                eventTypeIndexed);
            
            
            var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(indexCoercionTypes, true, raw, services.SerdeResolver);
            indexItem.HashMultiKeyClasses = multiKeyPlan.ClassRef;

            var rangeSerdes = new DataInputOutputSerdeForge[rangeCoercionTypes.Length];
            for (var i = 0; i < rangeCoercionTypes.Length; i++) {
                rangeSerdes[i] = services.SerdeResolver.SerdeForIndexBtree(rangeCoercionTypes[i], raw);
            }
            indexItem.RangeSerdes = rangeSerdes;

            return new SubordinateQueryIndexPlan(indexItem, indexPropKey, multiKeyPlan.MultiKeyForgeables);
        }
Exemplo n.º 10
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);
        }
Exemplo n.º 11
0
        public static RowRecogPlan ValidateAndPlan(
            IContainer container,
            EventType parentEventType,
            bool unbound,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            var statementRawInfo = @base.StatementRawInfo;
            var matchRecognizeSpec = @base.StatementSpec.Raw.MatchRecognizeSpec;
            var annotations = statementRawInfo.Annotations;
            var iterateOnly = HintEnum.ITERATE_ONLY.GetHint(annotations) != null;
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            // Expanded pattern already there
            RowRecogExprNode expandedPatternNode = matchRecognizeSpec.Pattern;

            // Determine single-row and multiple-row variables
            var variablesSingle = new LinkedHashSet<string>();
            var variablesMultiple = new LinkedHashSet<string>();
            RowRecogHelper.RecursiveInspectVariables(expandedPatternNode, false, variablesSingle, variablesMultiple);

            // each variable gets associated with a stream number (multiple-row variables as well to hold the current event for the expression).
            var streamNum = 0;
            var variableStreams = new LinkedHashMap<string, Pair<int, bool>>();
            foreach (var variableSingle in variablesSingle) {
                variableStreams.Put(variableSingle, new Pair<int, bool>(streamNum, false));
                streamNum++;
            }

            foreach (var variableMultiple in variablesMultiple) {
                variableStreams.Put(variableMultiple, new Pair<int, bool>(streamNum, true));
                streamNum++;
            }

            // mapping of stream to variable
            var streamVariables = new OrderedListDictionary<int, string>();
            foreach (var entry in variableStreams) {
                streamVariables.Put(entry.Value.First, entry.Key);
            }

            // determine visibility rules
            var visibility = RowRecogHelper.DetermineVisibility(expandedPatternNode);

            // assemble all single-row variables for expression validation
            var allStreamNames = new string[variableStreams.Count];
            var allTypes = new EventType[variableStreams.Count];

            streamNum = 0;
            foreach (var variableSingle in variablesSingle) {
                allStreamNames[streamNum] = variableSingle;
                allTypes[streamNum] = parentEventType;
                streamNum++;
            }

            foreach (var variableMultiple in variablesMultiple) {
                allStreamNames[streamNum] = variableMultiple;
                allTypes[streamNum] = parentEventType;
                streamNum++;
            }

            // determine type service for use with DEFINE
            // validate each DEFINE clause expression
            ISet<string> definedVariables = new HashSet<string>();
            IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>();
            var isExprRequiresMultimatchState = new bool[variableStreams.Count];
            var previousNodes = new OrderedListDictionary<int, IList<ExprPreviousMatchRecognizeNode>>();

            for (var defineIndex = 0; defineIndex < matchRecognizeSpec.Defines.Count; defineIndex++) {
                MatchRecognizeDefineItem defineItem = matchRecognizeSpec.Defines[defineIndex];
                if (definedVariables.Contains(defineItem.Identifier)) {
                    throw new ExprValidationException(
                        "Variable '" + defineItem.Identifier + "' has already been defined");
                }

                definedVariables.Add(defineItem.Identifier);

                // stream-type visibilities handled here
                var typeServiceDefines = BuildDefineStreamTypeServiceDefine(
                    defineIndex,
                    variableStreams,
                    defineItem,
                    visibility,
                    parentEventType,
                    statementRawInfo,
                    services);

                var exprNodeResult = HandlePreviousFunctions(defineItem.Expression, previousNodes);
                var validationContext = new ExprValidationContextBuilder(typeServiceDefines, statementRawInfo, services)
                    .WithAllowBindingConsumption(true)
                    .WithDisablePropertyExpressionEventCollCache(true)
                    .Build();

                ExprNode validated;
                try {
                    // validate
                    validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.MATCHRECOGDEFINE,
                        exprNodeResult,
                        validationContext);

                    // check aggregates
                    defineItem.Expression = validated;
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(validated, aggregateNodes);
                    if (!aggregateNodes.IsEmpty()) {
                        throw new ExprValidationException("An aggregate function may not appear in a DEFINE clause");
                    }
                }
                catch (ExprValidationException ex) {
                    throw new ExprValidationException(
                        "Failed to validate condition expression for variable '" +
                        defineItem.Identifier +
                        "': " +
                        ex.Message,
                        ex);
                }

                // determine access to event properties from multi-matches
                var visitor = new ExprNodeStreamRequiredVisitor();
                validated.Accept(visitor);
                var streamsRequired = visitor.StreamsRequired;
                foreach (var streamRequired in streamsRequired) {
                    if (streamRequired >= variableStreams.Count) {
                        var streamNumIdent = variableStreams.Get(defineItem.Identifier).First;
                        isExprRequiresMultimatchState[streamNumIdent] = true;
                        break;
                    }
                }
            }

            var defineAsksMultimatches = CollectionUtil.IsAnySet(isExprRequiresMultimatchState);

            // determine type service for use with MEASURE
            IDictionary<string, object> measureTypeDef = new LinkedHashMap<string, object>();
            foreach (var variableSingle in variablesSingle) {
                measureTypeDef.Put(variableSingle, parentEventType);
            }

            foreach (var variableMultiple in variablesMultiple) {
                measureTypeDef.Put(variableMultiple, new[] {parentEventType});
            }

            var compositeTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogCompositeName;
            var compositeTypeMetadata = new EventTypeMetadata(
                compositeTypeName,
                @base.ModuleName,
                EventTypeTypeClass.MATCHRECOGDERIVED,
                EventTypeApplicationType.OBJECTARR,
                NameAccessModifier.TRANSIENT,
                EventTypeBusModifier.NONBUS,
                false,
                EventTypeIdPair.Unassigned());
            var compositeEventType = BaseNestableEventUtil.MakeOATypeCompileTime(
                compositeTypeMetadata,
                measureTypeDef,
                null,
                null,
                null,
                null,
                services.BeanEventTypeFactoryPrivate,
                services.EventTypeCompileTimeResolver);
            services.EventTypeCompileTimeRegistry.NewType(compositeEventType);
            StreamTypeService compositeTypeServiceMeasure =
                new StreamTypeServiceImpl(compositeEventType, "MATCH_RECOGNIZE", true);

            // find MEASURE clause aggregations
            var measureReferencesMultivar = false;
            IList<ExprAggregateNode> measureAggregateExprNodes = new List<ExprAggregateNode>();
            foreach (var measureItem in matchRecognizeSpec.Measures) {
                ExprAggregateNodeUtil.GetAggregatesBottomUp(measureItem.Expr, measureAggregateExprNodes);
            }

            AggregationServiceForgeDesc[] aggregationServices = null;
            if (!measureAggregateExprNodes.IsEmpty()) {
                aggregationServices = PlanAggregations(
                    measureAggregateExprNodes,
                    compositeTypeServiceMeasure,
                    allStreamNames,
                    allTypes,
                    streamVariables,
                    variablesMultiple,
                    @base,
                    services);
                foreach (AggregationServiceForgeDesc svc in aggregationServices) {
                    if (svc != null) {
                        additionalForgeables.AddAll(svc.AdditionalForgeables);
                    }
                }
            }

            // validate each MEASURE clause expression
            IDictionary<string, object> rowTypeDef = new LinkedHashMap<string, object>();
            var streamRefVisitor = new ExprNodeStreamUseCollectVisitor();
            foreach (var measureItem in matchRecognizeSpec.Measures) {
                if (measureItem.Name == null) {
                    throw new ExprValidationException(
                        "The measures clause requires that each expression utilizes the AS keyword to assign a column name");
                }

                var validated = ValidateMeasureClause(
                    measureItem.Expr,
                    compositeTypeServiceMeasure,
                    variablesMultiple,
                    variablesSingle,
                    statementRawInfo,
                    services);
                measureItem.Expr = validated;
                rowTypeDef.Put(measureItem.Name, validated.Forge.EvaluationType);
                validated.Accept(streamRefVisitor);
            }

            // Determine if any of the multi-var streams are referenced in the measures (non-aggregated only)
            foreach (var @ref in streamRefVisitor.Referenced) {
                var rootPropName = @ref.RootPropertyNameIfAny;
                if (rootPropName != null) {
                    if (variablesMultiple.Contains(rootPropName)) {
                        measureReferencesMultivar = true;
                        break;
                    }
                }

                var streamRequired = @ref.StreamReferencedIfAny;
                if (streamRequired != null) {
                    var streamVariable = streamVariables.Get(streamRequired.Value);
                    if (streamVariable != null) {
                        var def = variableStreams.Get(streamVariable);
                        if (def != null && def.Second) {
                            measureReferencesMultivar = true;
                            break;
                        }
                    }
                }
            }

            var collectMultimatches = measureReferencesMultivar || defineAsksMultimatches;

            // create rowevent type
            var rowTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogRowName;
            var rowTypeMetadata = new EventTypeMetadata(
                rowTypeName,
                @base.ModuleName,
                EventTypeTypeClass.MATCHRECOGDERIVED,
                EventTypeApplicationType.MAP,
                NameAccessModifier.TRANSIENT,
                EventTypeBusModifier.NONBUS,
                false,
                EventTypeIdPair.Unassigned());
            var rowEventType = BaseNestableEventUtil.MakeMapTypeCompileTime(
                rowTypeMetadata,
                rowTypeDef,
                null,
                null,
                null,
                null,
                services.BeanEventTypeFactoryPrivate,
                services.EventTypeCompileTimeResolver);
            services.EventTypeCompileTimeRegistry.NewType(rowEventType);

            // validate partition-by expressions, if any
            ExprNode[] partitionBy;
            MultiKeyClassRef partitionMultiKey;
            if (!matchRecognizeSpec.PartitionByExpressions.IsEmpty()) {
                StreamTypeService typeServicePartition = new StreamTypeServiceImpl(
                    parentEventType,
                    "MATCH_RECOGNIZE_PARTITION",
                    true);
                IList<ExprNode> validated = new List<ExprNode>();
                var validationContext =
                    new ExprValidationContextBuilder(typeServicePartition, statementRawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                foreach (var partitionExpr in matchRecognizeSpec.PartitionByExpressions) {
                    validated.Add(
                        ExprNodeUtilityValidate.GetValidatedSubtree(
                            ExprNodeOrigin.MATCHRECOGPARTITION,
                            partitionExpr,
                            validationContext));
                }

                matchRecognizeSpec.PartitionByExpressions = validated;
                partitionBy = ExprNodeUtilityQuery.ToArray(validated);
                MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(partitionBy, false, @base.StatementRawInfo, services.SerdeResolver);
                partitionMultiKey = multiKeyPlan.ClassRef;
                additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
            }
            else {
                partitionBy = null;
                partitionMultiKey = null;
            }

            // validate interval if present
            if (matchRecognizeSpec.Interval != null) {
                var validationContext =
                    new ExprValidationContextBuilder(new StreamTypeServiceImpl(false), statementRawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                var validated = (ExprTimePeriod) ExprNodeUtilityValidate.GetValidatedSubtree(
                    ExprNodeOrigin.MATCHRECOGINTERVAL,
                    matchRecognizeSpec.Interval.TimePeriodExpr,
                    validationContext);
                matchRecognizeSpec.Interval.TimePeriodExpr = validated;
            }

            // compile variable definition expressions
            IDictionary<string, ExprNode> variableDefinitions = new Dictionary<string, ExprNode>();
            foreach (var defineItem in matchRecognizeSpec.Defines) {
                variableDefinitions.Put(defineItem.Identifier, defineItem.Expression);
            }

            // create evaluators
            var columnNames = new string[matchRecognizeSpec.Measures.Count];
            var columnForges = new ExprNode[matchRecognizeSpec.Measures.Count];
            var count = 0;
            foreach (var measureItem in matchRecognizeSpec.Measures) {
                columnNames[count] = measureItem.Name;
                columnForges[count] = measureItem.Expr;
                count++;
            }

            // build states
            var strand = RowRecogHelper.BuildStartStates(
                expandedPatternNode,
                variableDefinitions,
                variableStreams,
                isExprRequiresMultimatchState);
            var startStates = strand.StartStates.ToArray();
            RowRecogNFAStateForge[] allStates = strand.AllStates.ToArray();

            if (Log.IsInfoEnabled) {
                Log.Info("NFA tree:\n" + RowRecogNFAViewUtil.Print(startStates));
            }

            // determine names of multimatching variables
            string[] multimatchVariablesArray;
            int[] multimatchStreamNumToVariable;
            int[] multimatchVariableToStreamNum;
            if (variablesSingle.Count == variableStreams.Count) {
                multimatchVariablesArray = new string[0];
                multimatchStreamNumToVariable = new int[0];
                multimatchVariableToStreamNum = new int[0];
            }
            else {
                multimatchVariablesArray = new string[variableStreams.Count - variablesSingle.Count];
                multimatchVariableToStreamNum = new int[multimatchVariablesArray.Length];
                multimatchStreamNumToVariable = new int[variableStreams.Count];
                CompatExtensions.Fill(multimatchStreamNumToVariable, -1);
                count = 0;
                foreach (var entry in variableStreams) {
                    if (entry.Value.Second) {
                        var index = count;
                        multimatchVariablesArray[index] = entry.Key;
                        multimatchVariableToStreamNum[index] = entry.Value.First;
                        multimatchStreamNumToVariable[entry.Value.First] = index;
                        count++;
                    }
                }
            }

            var numEventsEventsPerStreamDefine =
                defineAsksMultimatches ? variableStreams.Count + 1 : variableStreams.Count;

            // determine interval-or-terminated
            var orTerminated = matchRecognizeSpec.Interval != null && matchRecognizeSpec.Interval.IsOrTerminated;
            TimePeriodComputeForge intervalCompute = null;
            if (matchRecognizeSpec.Interval != null) {
                intervalCompute = matchRecognizeSpec.Interval.TimePeriodExpr.TimePeriodComputeForge;
            }

            EventType multimatchEventType = null;
            if (defineAsksMultimatches) {
                multimatchEventType = GetDefineMultimatchEventType(variableStreams, parentEventType, @base, services);
            }

            // determine previous-access indexes and assign "prev" node indexes
            // Since an expression such as "prior(2, price), prior(8, price)" translates into {2, 8} the relative index is {0, 1}.
            // Map the expression-supplied index to a relative index
            int[] previousRandomAccessIndexes = null;
            if (!previousNodes.IsEmpty()) {
                previousRandomAccessIndexes = new int[previousNodes.Count];
                var countPrev = 0;
                foreach (var entry in previousNodes) {
                    previousRandomAccessIndexes[countPrev] = entry.Key;
                    foreach (var callback in entry.Value) {
                        callback.AssignedIndex = countPrev;
                    }

                    countPrev++;
                }
            }

            RowRecogDescForge forge = new RowRecogDescForge(
                parentEventType,
                rowEventType,
                compositeEventType,
                multimatchEventType,
                multimatchStreamNumToVariable,
                multimatchVariableToStreamNum,
                partitionBy,
                partitionMultiKey,
                variableStreams,
                matchRecognizeSpec.Interval != null,
                iterateOnly,
                unbound,
                orTerminated,
                collectMultimatches,
                defineAsksMultimatches,
                numEventsEventsPerStreamDefine,
                multimatchVariablesArray,
                startStates,
                allStates,
                matchRecognizeSpec.IsAllMatches,
                matchRecognizeSpec.Skip.Skip,
                columnForges,
                columnNames,
                intervalCompute,
                previousRandomAccessIndexes,
                aggregationServices);
            
            return new RowRecogPlan(forge, additionalForgeables);
        }
Exemplo n.º 12
0
        private IList<StmtClassForgeableFactory> ValidateContextDetail(
            ContextSpec contextSpec,
            int nestingLevel,
            CreateContextValidationEnv validationEnv)
        {
            ISet<string> eventTypesReferenced = new HashSet<string>();
            IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>();
            
            if (contextSpec is ContextSpecKeyed) {
                var segmented = (ContextSpecKeyed) contextSpec;
                IDictionary<string, EventType> asNames = new Dictionary<string, EventType>();
                var partitionHasNameAssignment = false;
                Type[] getterTypes = null;
                foreach (var partition in segmented.Items) {
                    Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> pair = CompilePartitionedFilterSpec(
                        partition.FilterSpecRaw, eventTypesReferenced, validationEnv);
                    FilterSpecCompiled filterSpecCompiled = pair.First;
                    additionalForgeables.AddAll(pair.Second);
                   
                    partition.FilterSpecCompiled = filterSpecCompiled;

                    var getters = new EventPropertyGetterSPI[partition.PropertyNames.Count];
                    var serdes = new DataInputOutputSerdeForge[partition.PropertyNames.Count];
                    var eventType = (EventTypeSPI) filterSpecCompiled.FilterForEventType;
                    getterTypes = new Type[partition.PropertyNames.Count];
                    
                    for (var i = 0; i < partition.PropertyNames.Count; i++) {
                        var propertyName = partition.PropertyNames[i];
                        var getter = eventType.GetGetterSPI(propertyName);
                        if (getter == null) {
                            throw new ExprValidationException(
                                "For context '" + validationEnv.ContextName + "' property name '" + propertyName + "' not found on type " + eventType.Name);
                        }
                        getters[i] = getter;
                        getterTypes[i] = eventType.GetPropertyType(propertyName);
                        serdes[i] = validationEnv.Services.SerdeResolver.SerdeForFilter(
                            getterTypes[i], validationEnv.StatementRawInfo);
                    }

                    partition.Getters = getters;
                    partition.LookupableSerdes = serdes;

                    if (partition.AliasName != null) {
                        partitionHasNameAssignment = true;
                        ValidateAsName(asNames, partition.AliasName, filterSpecCompiled.FilterForEventType);
                    }
                }

                // plan multi-key, make sure we use the same multikey for all items
                MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(
                    getterTypes, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver);
                additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
                foreach (ContextSpecKeyedItem partition in segmented.Items) {
                    partition.KeyMultiKey = multiKeyPlan.ClassRef;
                }
                segmented.MultiKeyClassRef = multiKeyPlan.ClassRef;
                
                if (segmented.OptionalInit != null) {
                    asNames.Clear();
                    foreach (var initCondition in segmented.OptionalInit) {
                        ContextDetailMatchPair pair = ValidateRewriteContextCondition(
                            true,
                            nestingLevel,
                            initCondition,
                            eventTypesReferenced,
                            new MatchEventSpec(),
                            new EmptySet<string>(),
                            validationEnv);
                        additionalForgeables.AddAll(pair.AdditionalForgeables);

                        var filterForType = initCondition.FilterSpecCompiled.FilterForEventType;
                        var found = false;
                        foreach (var partition in segmented.Items) {
                            if (partition.FilterSpecCompiled.FilterForEventType == filterForType) {
                                found = true;
                                break;
                            }
                        }

                        if (!found) {
                            throw new ExprValidationException(
                                "Segmented context '" +
                                validationEnv.ContextName +
                                "' requires that all of the event types that are listed in the initialized-by also appear in the partition-by, type '" +
                                filterForType.Name +
                                "' is not one of the types listed in partition-by");
                        }

                        if (initCondition.OptionalFilterAsName != null) {
                            if (partitionHasNameAssignment) {
                                throw new ExprValidationException(
                                    "Segmented context '" +
                                    validationEnv.ContextName +
                                    "' requires that either partition-by or initialized-by assign stream names, but not both");
                            }

                            ValidateAsName(asNames, initCondition.OptionalFilterAsName, filterForType);
                        }
                    }
                }

                if (segmented.OptionalTermination != null) {
                    var matchEventSpec = new MatchEventSpec();
                    var allTags = new LinkedHashSet<string>();
                    foreach (var partition in segmented.Items) {
                        if (partition.AliasName != null) {
                            allTags.Add(partition.AliasName);
                            var eventType = partition.FilterSpecCompiled.FilterForEventType;
                            matchEventSpec.TaggedEventTypes[partition.AliasName] = new Pair<EventType,string>(
                                eventType, partition.FilterSpecRaw.EventTypeName);
                            var serdeForgeables = SerdeEventTypeUtility.Plan(
                                eventType,
                                validationEnv.StatementRawInfo,
                                validationEnv.Services.SerdeEventTypeRegistry,
                                validationEnv.Services.SerdeResolver);
                            additionalForgeables.AddAll(serdeForgeables);
                        }
                    }

                    if (segmented.OptionalInit != null) {
                        foreach (var initCondition in segmented.OptionalInit) {
                            if (initCondition.OptionalFilterAsName != null) {
                                allTags.Add(initCondition.OptionalFilterAsName);
                                matchEventSpec.TaggedEventTypes.Put(
                                    initCondition.OptionalFilterAsName,
                                    new Pair<EventType, string>(
                                        initCondition.FilterSpecCompiled.FilterForEventType,
                                        initCondition.FilterSpecRaw.EventTypeName));
                            }
                        }
                    }

                    var endCondition = ValidateRewriteContextCondition(
                        false,
                        nestingLevel,
                        segmented.OptionalTermination,
                        eventTypesReferenced,
                        matchEventSpec,
                        allTags,
                        validationEnv);
                    additionalForgeables.AddAll(endCondition.AdditionalForgeables);

                    segmented.OptionalTermination = endCondition.Condition;
                }
            }
            else if (contextSpec is ContextSpecCategory) {
                // compile filter
                var category = (ContextSpecCategory) contextSpec;
                ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services);
                var raw = new FilterStreamSpecRaw(
                    category.FilterSpecRaw,
                    ViewSpec.EMPTY_VIEWSPEC_ARRAY,
                    null,
                    StreamSpecOptions.DEFAULT);

                var compiledDesc = StreamSpecCompiler.CompileFilter(
                    raw,
                    false,
                    false,
                    true,
                    false,
                    null,
                    validationEnv.StatementRawInfo,
                    validationEnv.Services);
                var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled;
                additionalForgeables.AddAll(compiledDesc.AdditionalForgeables);
                
                category.FilterSpecCompiled = result.FilterSpecCompiled;
                validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled);

                // compile expressions
                foreach (var item in category.Items) {
                    ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services);
                    var filterSpecRaw = new FilterSpecRaw(
                        category.FilterSpecRaw.EventTypeName,
                        Collections.SingletonList(item.Expression),
                        null);
                    var rawExpr = new FilterStreamSpecRaw(
                        filterSpecRaw,
                        ViewSpec.EMPTY_VIEWSPEC_ARRAY,
                        null,
                        StreamSpecOptions.DEFAULT);
                    var compiledDescItems = StreamSpecCompiler.CompileFilter(
                        rawExpr,
                        false,
                        false,
                        true,
                        false,
                        null,
                        validationEnv.StatementRawInfo,
                        validationEnv.Services);
                    var compiled = (FilterStreamSpecCompiled) compiledDescItems.StreamSpecCompiled;
                    additionalForgeables.AddAll(compiledDescItems.AdditionalForgeables);
                    compiled.FilterSpecCompiled.TraverseFilterBooleanExpr(
                        node => validationEnv.FilterBooleanExpressions.Add(node));
                    item.FilterPlan = compiled.FilterSpecCompiled.Parameters;
                }
            }
            else if (contextSpec is ContextSpecHash) {
                var hashed = (ContextSpecHash) contextSpec;
                foreach (var hashItem in hashed.Items) {
                    var raw = new FilterStreamSpecRaw(
                        hashItem.FilterSpecRaw,
                        ViewSpec.EMPTY_VIEWSPEC_ARRAY,
                        null,
                        StreamSpecOptions.DEFAULT);
                    ValidateNotTable(hashItem.FilterSpecRaw.EventTypeName, validationEnv.Services);

                    var compiledDesc = StreamSpecCompiler.Compile(
                        raw,
                        eventTypesReferenced,
                        false,
                        false,
                        true,
                        false,
                        null,
                        0,
                        validationEnv.StatementRawInfo,
                        validationEnv.Services);
                    additionalForgeables.AddAll(compiledDesc.AdditionalForgeables);
                    var result = (FilterStreamSpecCompiled)  compiledDesc.StreamSpecCompiled;

                    validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled);
                    hashItem.FilterSpecCompiled = result.FilterSpecCompiled;

                    // validate parameters
                    var streamTypes = new StreamTypeServiceImpl(
                        result.FilterSpecCompiled.FilterForEventType,
                        null,
                        true);
                    var validationContext =
                        new ExprValidationContextBuilder(
                                streamTypes,
                                validationEnv.StatementRawInfo,
                                validationEnv.Services)
                            .WithIsFilterExpression(true)
                            .Build();
                    ExprNodeUtilityValidate.Validate(
                        ExprNodeOrigin.CONTEXT,
                        Collections.SingletonList(hashItem.Function),
                        validationContext);
                }
            }
            else if (contextSpec is ContextSpecInitiatedTerminated) {
                var def = (ContextSpecInitiatedTerminated) contextSpec;
                var startCondition = ValidateRewriteContextCondition(
                    true,
                    nestingLevel,
                    def.StartCondition,
                    eventTypesReferenced,
                    new MatchEventSpec(),
                    new LinkedHashSet<string>(),
                    validationEnv);
                additionalForgeables.AddAll(startCondition.AdditionalForgeables);

                var endCondition = ValidateRewriteContextCondition(
                    false,
                    nestingLevel,
                    def.EndCondition,
                    eventTypesReferenced,
                    startCondition.Matches,
                    startCondition.AllTags,
                    validationEnv);
                additionalForgeables.AddAll(endCondition.AdditionalForgeables);
                
                def.StartCondition = startCondition.Condition;
                def.EndCondition = endCondition.Condition;

                if (def.DistinctExpressions != null) {
                    if (!(startCondition.Condition is ContextSpecConditionFilter)) {
                        throw new ExprValidationException(
                            "Distinct-expressions require a stream as the initiated-by condition");
                    }

                    var distinctExpressions = def.DistinctExpressions;
                    if (distinctExpressions.Length == 0) {
                        throw new ExprValidationException("Distinct-expressions have not been provided");
                    }

                    var filter = (ContextSpecConditionFilter) startCondition.Condition;
                    if (filter.OptionalFilterAsName == null) {
                        throw new ExprValidationException(
                            "Distinct-expressions require that a stream name is assigned to the stream using 'as'");
                    }

                    var types = new StreamTypeServiceImpl(
                        filter.FilterSpecCompiled.FilterForEventType,
                        filter.OptionalFilterAsName,
                        true);
                    var validationContext =
                        new ExprValidationContextBuilder(types, validationEnv.StatementRawInfo, validationEnv.Services)
                            .WithAllowBindingConsumption(true)
                            .Build();
                    for (var i = 0; i < distinctExpressions.Length; i++) {
                        ExprNodeUtilityValidate.ValidatePlainExpression(
                            ExprNodeOrigin.CONTEXTDISTINCT,
                            distinctExpressions[i]);
                        distinctExpressions[i] = ExprNodeUtilityValidate.GetValidatedSubtree(
                            ExprNodeOrigin.CONTEXTDISTINCT,
                            distinctExpressions[i],
                            validationContext);
                    }

                    var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(
                        distinctExpressions,
                        false,
                        @base.StatementRawInfo,
                        validationEnv.Services.SerdeResolver);
                    def.DistinctMultiKey = multiKeyPlan.ClassRef;
                    additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
                }
            }
            else if (contextSpec is ContextNested) {
                var nested = (ContextNested) contextSpec;
                var level = 0;
                ISet<string> namesUsed = new HashSet<string>();
                namesUsed.Add(validationEnv.ContextName);
                foreach (var nestedContext in nested.Contexts) {
                    if (namesUsed.Contains(nestedContext.ContextName)) {
                        throw new ExprValidationException(
                            "Context by name '" +
                            nestedContext.ContextName +
                            "' has already been declared within nested context '" +
                            validationEnv.ContextName +
                            "'");
                    }

                    namesUsed.Add(nestedContext.ContextName);

                    var forgeables = ValidateContextDetail(nestedContext.ContextDetail, level, validationEnv);
                    additionalForgeables.AddAll(forgeables);
                    level++;
                }
            }
            else {
                throw new IllegalStateException("Unrecognized context detail " + contextSpec);
            }

            return additionalForgeables;
        }
        // Obtain those method and state factories for each level
        private static AggregationGroupByLocalGroupLevelDesc GetLevel(
            int levelNumber,
            AggregationGroupByLocalGroupLevel level,
            ExprForge[][] methodForgesAll,
            AggregationForgeFactory[] methodFactoriesAll,
            AggregationStateFactoryForge[] accessForges,
            AggregationLocalGroupByColumnForge[] columns,
            bool defaultLevel,
            AggregationAccessorSlotPairForge[] accessors,
            ExprNode[] groupByExpressions,
            MultiKeyClassRef optionalGroupByMultiKey,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var partitionExpr = level.PartitionExpr;
            MultiKeyPlan multiKeyPlan;
            if (defaultLevel && optionalGroupByMultiKey != null) { // use default multi-key that is already generated
                multiKeyPlan = new MultiKeyPlan(EmptyList<StmtClassForgeableFactory>.Instance, optionalGroupByMultiKey);
                partitionExpr = groupByExpressions;
            } else {
                multiKeyPlan = MultiKeyPlanner.PlanMultiKey(partitionExpr, false, raw, serdeResolver);
            }

            IList<ExprForge[]> methodForges = new List<ExprForge[]>();
            IList<AggregationForgeFactory> methodFactories = new List<AggregationForgeFactory>();
            IList<AggregationStateFactoryForge> stateFactories = new List<AggregationStateFactoryForge>();

            foreach (var expr in level.Expressions) {
                int column = expr.AggregationNode.Column;
                var methodOffset = -1;
                var methodAgg = true;
                AggregationAccessorSlotPairForge pair = null;

                if (column < methodForgesAll.Length) {
                    methodForges.Add(methodForgesAll[column]);
                    methodFactories.Add(methodFactoriesAll[column]);
                    methodOffset = methodFactories.Count - 1;
                }
                else {
                    // slot gives us the number of the state factory
                    int absoluteSlot = accessors[column - methodForgesAll.Length].Slot;
                    AggregationAccessorForge accessor = accessors[column - methodForgesAll.Length].AccessorForge;
                    var factory = accessForges[absoluteSlot];
                    var relativeSlot = stateFactories.IndexOf(factory);
                    if (relativeSlot == -1) {
                        stateFactories.Add(factory);
                        relativeSlot = stateFactories.Count - 1;
                    }

                    methodAgg = false;
                    pair = new AggregationAccessorSlotPairForge(relativeSlot, accessor);
                }

                columns[column] = new AggregationLocalGroupByColumnForge(
                    defaultLevel,
                    partitionExpr,
                    methodOffset,
                    methodAgg,
                    pair,
                    levelNumber);
            }

            var forge = new AggregationLocalGroupByLevelForge(
                methodForges.ToArray(),
                methodFactories.ToArray(),
                stateFactories.ToArray(),
                partitionExpr,
                multiKeyPlan.ClassRef,
                defaultLevel);

            // NOTE: The original code tests for multiKeyPlan being null, but if it was null it would have caused
            // a null pointer exception on the previous statement since it dereferences ClassRef.
            var additionalForgeables = multiKeyPlan?.MultiKeyForgeables ?? EmptyList<StmtClassForgeableFactory>.Instance;
            
            return new AggregationGroupByLocalGroupLevelDesc(forge, additionalForgeables);
        }
Exemplo n.º 14
0
        /// <summary>
        ///     Create the table lookup plan for a from-stream to look up in an indexed stream
        ///     using the columns supplied in the query graph and looking at the actual indexes available
        ///     and their index number.
        /// </summary>
        /// <param name="queryGraph">contains properties joining the 2 streams</param>
        /// <param name="currentLookupStream">stream to use key values from</param>
        /// <param name="indexedStream">stream to look up in</param>
        /// <param name="indexSpecs">index specification defining indexes to be created for stream</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <param name="indexedStreamTableMeta">table info</param>
        /// <param name="indexedStreamIsVDW">vdw indicators</param>
        /// <param name="raw">raw statement information</param>
        /// <param name="serdeResolver">serde resolver</param>
        /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns>
        public static TableLookupPlanDesc CreateLookupPlan(
            QueryGraphForge queryGraph,
            int currentLookupStream,
            int indexedStream,
            bool indexedStreamIsVDW,
            QueryPlanIndexForge indexSpecs,
            EventType[] typesPerStream,
            TableMetaData indexedStreamTableMeta,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream);
            var hashKeyProps = queryGraphValue.HashKeyProps;
            var hashPropsKeys = hashKeyProps.Keys;
            var hashIndexProps = hashKeyProps.Indexed;

            var rangeProps = queryGraphValue.RangeProps;
            var rangePropsKeys = rangeProps.Keys;
            var rangeIndexProps = rangeProps.Indexed;

            var pairIndexHashRewrite =
                indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps);
            var indexNum = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First;

            // handle index redirection towards unique index
            if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null) {
                var indexes = pairIndexHashRewrite.Second;
                var newHashIndexProps = new string[indexes.Length];
                IList<QueryGraphValueEntryHashKeyedForge> newHashKeys = new List<QueryGraphValueEntryHashKeyedForge>();
                for (var i = 0; i < indexes.Length; i++) {
                    newHashIndexProps[i] = hashIndexProps[indexes[i]];
                    newHashKeys.Add(hashPropsKeys[indexes[i]]);
                }

                hashIndexProps = newHashIndexProps;
                hashPropsKeys = newHashKeys;
                rangeIndexProps = new string[0];
                rangePropsKeys = Collections.GetEmptyList<QueryGraphValueEntryRangeForge>();
            }

            // no direct hash or range lookups
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) {
                // handle single-direction 'in' keyword
                var singles = queryGraphValue.InKeywordSingles;
                if (!singles.Key.IsEmpty()) {
                    QueryGraphValueEntryInKeywordSingleIdxForge single = null;
                    indexNum = null;
                    if (indexedStreamTableMeta != null) {
                        var indexes = singles.Indexed;
                        var count = 0;
                        foreach (var index in indexes) {
                            var indexPairFound =
                                EventTableIndexUtil.FindIndexBestAvailable(
                                    indexedStreamTableMeta.IndexMetadata.Indexes,
                                    Collections.SingletonSet(index),
                                    Collections.GetEmptySet<string>(),
                                    null);
                            if (indexPairFound != null) {
                                indexNum = new TableLookupIndexReqKey(
                                    indexPairFound.Second.OptionalIndexName,
                                    indexPairFound.Second.OptionalIndexModuleName,
                                    indexedStreamTableMeta.TableName);
                                single = singles.Key[count];
                            }

                            count++;
                        }
                    }
                    else {
                        single = singles.Key[0];
                        var pairIndex = indexSpecs.GetIndexNum(
                            new[] {singles.Indexed[0]},
                            new string[0]);
                        indexNum = pairIndex.First;
                    }

                    if (indexNum != null) {
                        var forge = new InKeywordTableLookupPlanSingleIdxForge(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexNum,
                            single.KeyExprs);
                        return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                    }
                }

                // handle multi-direction 'in' keyword
                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty()) {
                    if (indexedStreamTableMeta != null) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }

                    var multi = multis[0];
                    var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length];
                    var foundAll = true;
                    for (var i = 0; i < multi.Indexed.Length; i++) {
                        var identNode = (ExprIdentNode) multi.Indexed[i];
                        var pairIndex = indexSpecs.GetIndexNum(
                            new[] {identNode.ResolvedPropertyName},
                            new string[0]);
                        if (pairIndex == null) {
                            foundAll = false;
                        }
                        else {
                            indexNameArray[i] = pairIndex.First;
                        }
                    }

                    if (foundAll) {
                        var forge = new InKeywordTableLookupPlanMultiIdxForge(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexNameArray,
                            multi.Key.KeyExpr);
                        return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                    }
                }

                // We don't use a keyed index but use the full stream set as the stream does not have any indexes

                // If no such full set index exists yet, add to specs
                if (indexedStreamTableMeta != null) {
                    return GetFullTableScanTable(
                        currentLookupStream,
                        indexedStream,
                        indexedStreamIsVDW,
                        typesPerStream,
                        indexedStreamTableMeta);
                }

                if (indexNum == null) {
                    indexNum = new TableLookupIndexReqKey(
                        indexSpecs.AddIndex(new string[0], new Type[0], typesPerStream[indexedStream]),
                        null);
                }

                var forgeX = new FullTableScanLookupPlanForge(currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum);
                return new TableLookupPlanDesc(forgeX, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            if (indexNum == null) {
                throw new IllegalStateException(
                    "Failed to query plan as index for " +
                    hashIndexProps.RenderAny() +
                    " and " +
                    rangeIndexProps.RenderAny() +
                    " in the index specification");
            }

            if (indexedStreamTableMeta != null) {
                var indexPairFound =
                    EventTableIndexUtil.FindIndexBestAvailable(
                        indexedStreamTableMeta.IndexMetadata.Indexes,
                        ToSet(hashIndexProps),
                        ToSet(rangeIndexProps),
                        null);
                if (indexPairFound != null) {
                    var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(
                        indexPairFound.First,
                        hashIndexProps,
                        GetHashKeyFuncsAsSubProp(hashPropsKeys),
                        rangeIndexProps,
                        GetRangeFuncsAsSubProp(rangePropsKeys));
                    if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce ||
                        indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }

                    hashPropsKeys = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc);
                    hashIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps);
                    rangePropsKeys = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc);
                    rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps);
                    indexNum = new TableLookupIndexReqKey(
                        indexPairFound.Second.OptionalIndexName,
                        indexPairFound.Second.OptionalIndexModuleName,
                        indexedStreamTableMeta.TableName);
                    // the plan will be created below
                    if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }
                }
                else {
                    return GetFullTableScanTable(
                        currentLookupStream,
                        indexedStream,
                        indexedStreamIsVDW,
                        typesPerStream,
                        indexedStreamTableMeta);
                }
            }

            // straight keyed-index lookup
            if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0) {
                // Determine coercion required
                var coercionTypes = CoercionUtil.GetCoercionTypesHash(
                    typesPerStream,
                    currentLookupStream,
                    indexedStream,
                    hashPropsKeys,
                    hashIndexProps);
                if (coercionTypes.IsCoerce) {
                    // check if there already are coercion types for this index
                    var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps);
                    if (existCoercionTypes != null) {
                        for (var i = 0; i < existCoercionTypes.Length; i++) {
                            coercionTypes.CoercionTypes[i] = existCoercionTypes[i]
                                .GetCompareToCoercionType(coercionTypes.CoercionTypes[i]);
                        }
                    }

                    if (!indexSpecs.Items.IsEmpty()) {
                        indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes);
                    }
                }

                var coercionTypesArray = coercionTypes.CoercionTypes;
                MultiKeyClassRef tableLookupMultiKey = null;
                IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance;
                if (indexNum.TableName != null) {
                    var tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesArray, true, raw, serdeResolver);
                    tableLookupMultiKey = tableMultiKeyPlan.ClassRef;
                    additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables;
                }

                var forge = new IndexedTableLookupPlanHashedOnlyForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    hashPropsKeys.ToArray(),
                    indexSpecs,
                    coercionTypesArray,
                    tableLookupMultiKey);
                return new TableLookupPlanDesc(forge, additionalForgeables);
            }

            // sorted index lookup
            var coercionTypesRange = CoercionUtil.GetCoercionTypesRange(
                typesPerStream,
                indexedStream,
                rangeIndexProps,
                rangePropsKeys);
            var coercionTypesHash = CoercionUtil.GetCoercionTypesHash(
                typesPerStream,
                currentLookupStream,
                indexedStream,
                hashPropsKeys,
                hashIndexProps);
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1) {
                var range = rangePropsKeys[0];
                Type coercionType = null;
                if (coercionTypesRange.IsCoerce) {
                    coercionType = coercionTypesRange.CoercionTypes[0];
                }

                SortedTableLookupPlanForge forge = new SortedTableLookupPlanForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    range,
                    coercionType);
                return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
            }
            else {
                MultiKeyClassRef tableLookupMultiKey = null;
                IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance;
                if (indexNum.TableName != null) {
                    MultiKeyPlan tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesHash.CoercionTypes, true, raw, serdeResolver);
                    tableLookupMultiKey = tableMultiKeyPlan.ClassRef;
                    additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables;
                }

                // composite range and index lookup
                CompositeTableLookupPlanForge forge = new CompositeTableLookupPlanForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    hashPropsKeys,
                    coercionTypesHash.CoercionTypes,
                    rangePropsKeys,
                    coercionTypesRange.CoercionTypes,
                    indexSpecs,
                    tableLookupMultiKey);
                return new TableLookupPlanDesc(forge, additionalForgeables);
            }
        }
Exemplo n.º 15
0
        public static OutputProcessViewFactoryForgeDesc Make(
            EventType[] typesPerStream,
            EventType resultEventType,
            ResultSetProcessorType resultSetProcessorType,
            StatementSpecCompiled statementSpec,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            InsertIntoDesc insertIntoDesc = statementSpec.Raw.InsertIntoDesc;
            SelectClauseStreamSelectorEnum selectStreamSelector = statementSpec.Raw.SelectStreamSelectorEnum;
            OutputLimitSpec outputLimitSpec = statementSpec.Raw.OutputLimitSpec;
            int streamCount = statementSpec.StreamSpecs.Length;
            bool isDistinct = statementSpec.Raw.SelectClauseSpec.IsDistinct;
            bool isGrouped = statementSpec.GroupByExpressions != null &&
                             statementSpec.GroupByExpressions.GroupByNodes.Length > 0;
            List<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>();

            // determine routing
            bool isRouted = false;
            bool routeToFront = false;
            if (insertIntoDesc != null) {
                isRouted = true;
                routeToFront = services.NamedWindowCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName) != null;
            }

            OutputStrategyPostProcessForge outputStrategyPostProcessForge = null;
            if ((insertIntoDesc != null) || (selectStreamSelector == SelectClauseStreamSelectorEnum.RSTREAM_ONLY)) {
                SelectClauseStreamSelectorEnum? insertIntoStreamSelector = null;
                TableMetaData table = null;

                if (insertIntoDesc != null) {
                    insertIntoStreamSelector = insertIntoDesc.StreamSelector;
                    table = services.TableCompileTimeResolver.Resolve(statementSpec.Raw.InsertIntoDesc.EventTypeName);
                    if (table != null) {
                        EPLValidationUtil.ValidateContextName(
                            true,
                            table.TableName,
                            table.OptionalContextName,
                            statementSpec.Raw.OptionalContextName,
                            true);
                    }
                }

                bool audit = AuditEnum.INSERT.GetAudit(statementSpec.Annotations) != null;
                outputStrategyPostProcessForge = new OutputStrategyPostProcessForge(
                    isRouted,
                    insertIntoStreamSelector,
                    selectStreamSelector,
                    routeToFront,
                    table,
                    audit);
            }

            MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct(
                isDistinct,
                resultEventType,
                statementRawInfo,
                SerdeCompileTimeResolverNonHA.INSTANCE);
            MultiKeyClassRef distinctMultiKey = multiKeyPlan.ClassRef;
            additionalForgeables.AddRange(multiKeyPlan.MultiKeyForgeables);

            OutputProcessViewFactoryForge outputProcessViewFactoryForge;
            if (outputLimitSpec == null) {
                if (!isDistinct) {
                    if (outputStrategyPostProcessForge == null || !outputStrategyPostProcessForge.HasTable) {
                        // without table we have a shortcut implementation
                        outputProcessViewFactoryForge =
                            new OutputProcessViewDirectSimpleForge(outputStrategyPostProcessForge);
                    }
                    else {
                        outputProcessViewFactoryForge =
                            new OutputProcessViewDirectForge(outputStrategyPostProcessForge);
                    }
                }
                else {
                    outputProcessViewFactoryForge = new OutputProcessViewDirectDistinctOrAfterFactoryForge(
                        outputStrategyPostProcessForge,
                        isDistinct,
                        distinctMultiKey,
                        null,
                        null,
                        resultEventType);
                }
            }
            else if (outputLimitSpec.RateType == OutputLimitRateType.AFTER) {
                outputProcessViewFactoryForge = new OutputProcessViewDirectDistinctOrAfterFactoryForge(
                    outputStrategyPostProcessForge,
                    isDistinct,
                    distinctMultiKey,
                    outputLimitSpec.AfterTimePeriodExpr,
                    outputLimitSpec.AfterNumberOfEvents,
                    resultEventType);
            }
            else {
                try {
                    bool isWithHavingClause = statementSpec.Raw.HavingClause != null;
                    bool isStartConditionOnCreation = HasOnlyTables(statementSpec.StreamSpecs);
                    OutputConditionFactoryForge outputConditionFactoryForge =
                        OutputConditionFactoryFactory.CreateCondition(
                            outputLimitSpec,
                            isGrouped,
                            isWithHavingClause,
                            isStartConditionOnCreation,
                            statementRawInfo,
                            services);
                    bool hasOrderBy = statementSpec.Raw.OrderByList != null && statementSpec.Raw.OrderByList.Count > 0;
                    bool hasAfter = outputLimitSpec.AfterNumberOfEvents != null ||
                                    outputLimitSpec.AfterTimePeriodExpr != null;

                    // hint checking with order-by
                    bool hasOptHint = ResultSetProcessorOutputConditionTypeExtensions
                        .GetOutputLimitOpt(statementSpec.Annotations, services.Configuration, hasOrderBy);
                    ResultSetProcessorOutputConditionType conditionType =
                        ResultSetProcessorOutputConditionTypeExtensions
                            .GetConditionType(
                                outputLimitSpec.DisplayLimit,
                                resultSetProcessorType.IsAggregated(),
                                hasOrderBy,
                                hasOptHint,
                                resultSetProcessorType.IsGrouped());

                    // plan serdes
                    foreach (EventType eventType in typesPerStream) {
                        IList<StmtClassForgeableFactory> serdeForgeables = SerdeEventTypeUtility.Plan(
                            eventType,
                            statementRawInfo,
                            services.SerdeEventTypeRegistry,
                            services.SerdeResolver);
                        additionalForgeables.AddRange(serdeForgeables);
                    }
                    
                    bool terminable = outputLimitSpec.RateType == OutputLimitRateType.TERM ||
                                      outputLimitSpec.IsAndAfterTerminate;
                    outputProcessViewFactoryForge = new OutputProcessViewConditionForge(
                        outputStrategyPostProcessForge,
                        isDistinct,
                        distinctMultiKey,
                        outputLimitSpec.AfterTimePeriodExpr,
                        outputLimitSpec.AfterNumberOfEvents,
                        outputConditionFactoryForge,
                        streamCount,
                        conditionType,
                        terminable,
                        hasAfter,
                        resultSetProcessorType.IsUnaggregatedUngrouped(),
                        selectStreamSelector,
                        typesPerStream,
                        resultEventType);
                }
                catch (Exception ex) {
                    throw new ExprValidationException("Failed to validate the output rate limiting clause: " + ex.Message, ex);
                }
            }
            
            return new OutputProcessViewFactoryForgeDesc(outputProcessViewFactoryForge, additionalForgeables);
        }
Exemplo n.º 16
0
        private static void RecursiveCompile(
            EvalForgeNode evalNode,
            MatchEventSpec tags,
            Stack<EvalForgeNode> parentNodeStack,
            ISet<string> allTagNamesOrdered,
            int streamNum,
            IList<StmtClassForgeableFactory> additionalForgeables,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            parentNodeStack.Push(evalNode);
            foreach (var child in evalNode.ChildNodes) {
                RecursiveCompile(
                    child,
                    tags,
                    parentNodeStack,
                    allTagNamesOrdered,
                    streamNum,
                    additionalForgeables,
                    statementRawInfo,
                    services);
            }

            parentNodeStack.Pop();

            IDictionary<string, Pair<EventType, string>> newTaggedEventTypes = null;
            IDictionary<string, Pair<EventType, string>> newArrayEventTypes = null;

            if (evalNode is EvalFilterForgeNode) {
                var filterNode = (EvalFilterForgeNode) evalNode;
                var eventName = filterNode.RawFilterSpec.EventTypeName;
                if (services.TableCompileTimeResolver.Resolve(eventName) != null) {
                    throw new ExprValidationException("Tables cannot be used in pattern filter atoms");
                }

                var resolvedEventType = ResolveTypeName(eventName, services.EventTypeCompileTimeResolver);
                var finalEventType = resolvedEventType;
                var optionalTag = filterNode.EventAsName;
                var isPropertyEvaluation = false;
                var isParentMatchUntil = IsParentMatchUntil(evalNode, parentNodeStack);

                // obtain property event type, if final event type is properties
                if (filterNode.RawFilterSpec.OptionalPropertyEvalSpec != null) {
                    var optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                        filterNode.RawFilterSpec.OptionalPropertyEvalSpec,
                        resolvedEventType,
                        filterNode.EventAsName,
                        statementRawInfo,
                        services);
                    finalEventType = optionalPropertyEvaluator.FragmentEventType;
                    isPropertyEvaluation = true;
                }

                // If a tag was supplied for the type, the tags must stay with this type, i.e. a=BeanA -> b=BeanA -> a=BeanB is a no
                if (optionalTag != null) {
                    var pair = tags.TaggedEventTypes.Get(optionalTag);
                    EventType existingType = null;
                    if (pair != null) {
                        existingType = pair.First;
                    }

                    if (existingType == null) {
                        pair = tags.ArrayEventTypes.Get(optionalTag);
                        if (pair != null) {
                            throw new ExprValidationException(
                                "Tag '" +
                                optionalTag +
                                "' for event '" +
                                eventName +
                                "' used in the repeat-until operator cannot also appear in other filter expressions");
                        }
                    }

                    if (existingType != null && existingType != finalEventType) {
                        throw new ExprValidationException(
                            "Tag '" +
                            optionalTag +
                            "' for event '" +
                            eventName +
                            "' has already been declared for events of type " +
                            existingType.UnderlyingType.Name);
                    }

                    pair = new Pair<EventType, string>(finalEventType, eventName);

                    // add tagged type
                    if (isPropertyEvaluation || isParentMatchUntil) {
                        newArrayEventTypes = new LinkedHashMap<string, Pair<EventType, string>>();
                        newArrayEventTypes.Put(optionalTag, pair);
                    }
                    else {
                        newTaggedEventTypes = new LinkedHashMap<string, Pair<EventType, string>>();
                        newTaggedEventTypes.Put(optionalTag, pair);
                    }

                    var forgeables = SerdeEventTypeUtility.Plan(
                        pair.First,
                        statementRawInfo,
                        services.SerdeEventTypeRegistry,
                        services.SerdeResolver);
                    additionalForgeables.AddAll(forgeables);
                }

                // For this filter, filter types are all known tags at this time,
                // and additionally stream 0 (self) is our event type.
                // Stream type service allows resolution by property name event if that name appears in other tags.
                // by defaulting to stream zero.
                // Stream zero is always the current event type, all others follow the order of the map (stream 1 to N).
                var selfStreamName = optionalTag;
                if (selfStreamName == null) {
                    selfStreamName = "s_" + UuidGenerator.Generate();
                }

                var filterTypes = new LinkedHashMap<string, Pair<EventType, string>>();
                var typePair = new Pair<EventType, string>(finalEventType, eventName);
                filterTypes.Put(selfStreamName, typePair);
                filterTypes.PutAll(tags.TaggedEventTypes);

                // for the filter, specify all tags used
                var filterTaggedEventTypes = new LinkedHashMap<string, Pair<EventType, string>>(tags.TaggedEventTypes);
                filterTaggedEventTypes.Remove(optionalTag);

                // handle array tags (match-until clause)
                IDictionary<string, Pair<EventType, string>> arrayCompositeEventTypes = null;
                if (tags.ArrayEventTypes != null && !tags.ArrayEventTypes.IsEmpty()) {
                    arrayCompositeEventTypes = new LinkedHashMap<string, Pair<EventType, string>>();

                    foreach (var entry in tags.ArrayEventTypes) {
                        var specificArrayType = new LinkedHashMap<string, Pair<EventType, string>>();
                        specificArrayType.Put(entry.Key, entry.Value);

                        var eventTypeName = services.EventTypeNameGeneratorStatement.GetAnonymousPatternNameWTag(
                            streamNum,
                            evalNode.FactoryNodeId,
                            entry.Key);
                        var mapProps = GetMapProperties(
                            Collections.GetEmptyMap<string, Pair<EventType, string>>(),
                            specificArrayType);
                        var metadata = new EventTypeMetadata(
                            eventTypeName,
                            statementRawInfo.ModuleName,
                            EventTypeTypeClass.PATTERNDERIVED,
                            EventTypeApplicationType.MAP,
                            NameAccessModifier.TRANSIENT,
                            EventTypeBusModifier.NONBUS,
                            false,
                            EventTypeIdPair.Unassigned());
                        var mapEventType = BaseNestableEventUtil.MakeMapTypeCompileTime(
                            metadata,
                            mapProps,
                            null,
                            null,
                            null,
                            null,
                            services.BeanEventTypeFactoryPrivate,
                            services.EventTypeCompileTimeResolver);
                        services.EventTypeCompileTimeRegistry.NewType(mapEventType);

                        var tag = entry.Key;
                        if (!filterTypes.ContainsKey(tag)) {
                            var pair = new Pair<EventType, string>(mapEventType, tag);
                            filterTypes.Put(tag, pair);
                            arrayCompositeEventTypes.Put(tag, pair);
                        }

                        var forgeables = SerdeEventTypeUtility.Plan(
                            mapEventType,
                            statementRawInfo,
                            services.SerdeEventTypeRegistry,
                            services.SerdeResolver);
                        additionalForgeables.AddAll(forgeables);
                    }
                }

                StreamTypeService streamTypeService = new StreamTypeServiceImpl(filterTypes, true, false);
                var exprNodes = filterNode.RawFilterSpec.FilterExpressions;

                FilterSpecCompiledDesc compiled = FilterSpecCompiler.MakeFilterSpec(
                    resolvedEventType,
                    eventName,
                    exprNodes,
                    filterNode.RawFilterSpec.OptionalPropertyEvalSpec,
                    filterTaggedEventTypes,
                    arrayCompositeEventTypes,
                    allTagNamesOrdered,
                    streamTypeService,
                    null,
                    statementRawInfo,
                    services);
                
                filterNode.FilterSpec = compiled.FilterSpecCompiled;
                additionalForgeables.AddAll(compiled.AdditionalForgeables);
            }
            else if (evalNode is EvalObserverForgeNode) {
                var observerNode = (EvalObserverForgeNode) evalNode;
                try {
                    var observerForge =
                        services.PatternResolutionService.Create(observerNode.PatternObserverSpec);

                    var streamTypeService = GetStreamTypeService(
                        tags.TaggedEventTypes,
                        tags.ArrayEventTypes,
                        observerNode,
                        streamNum,
                        statementRawInfo,
                        services);
                    var validationContext = new ExprValidationContextBuilder(
                        streamTypeService,
                        statementRawInfo,
                        services).Build();
                    var validated = ValidateExpressions(
                        ExprNodeOrigin.PATTERNOBSERVER,
                        observerNode.PatternObserverSpec.ObjectParameters,
                        validationContext);

                    var convertor = new MatchedEventConvertorForge(
                        tags.TaggedEventTypes,
                        tags.ArrayEventTypes,
                        allTagNamesOrdered,
                        null,
                        false);

                    observerNode.ObserverFactory = observerForge;
                    observerForge.SetObserverParameters(validated, convertor, validationContext);
                }
                catch (ObserverParameterException e) {
                    throw new ExprValidationException(
                        "Invalid parameter for pattern observer '" +
                        observerNode.ToPrecedenceFreeEPL() +
                        "': " +
                        e.Message,
                        e);
                }
                catch (PatternObjectException e) {
                    throw new ExprValidationException(
                        "Failed to resolve pattern observer '" + observerNode.ToPrecedenceFreeEPL() + "': " + e.Message,
                        e);
                }
            }
            else if (evalNode is EvalGuardForgeNode) {
                var guardNode = (EvalGuardForgeNode) evalNode;
                try {
                    var guardForge = services.PatternResolutionService.Create(guardNode.PatternGuardSpec);

                    var streamTypeService = GetStreamTypeService(
                        tags.TaggedEventTypes,
                        tags.ArrayEventTypes,
                        guardNode,
                        streamNum,
                        statementRawInfo,
                        services);
                    var validationContext = new ExprValidationContextBuilder(
                        streamTypeService,
                        statementRawInfo,
                        services).Build();
                    var validated = ValidateExpressions(
                        ExprNodeOrigin.PATTERNGUARD,
                        guardNode.PatternGuardSpec.ObjectParameters,
                        validationContext);

                    var convertor = new MatchedEventConvertorForge(
                        tags.TaggedEventTypes,
                        tags.ArrayEventTypes,
                        allTagNamesOrdered,
                        null,
                        false);

                    guardNode.GuardForge = guardForge;
                    guardForge.SetGuardParameters(validated, convertor, services);
                }
                catch (GuardParameterException e) {
                    throw new ExprValidationException(
                        "Invalid parameter for pattern guard '" + guardNode.ToPrecedenceFreeEPL() + "': " + e.Message,
                        e);
                }
                catch (PatternObjectException e) {
                    throw new ExprValidationException(
                        "Failed to resolve pattern guard '" + guardNode.ToPrecedenceFreeEPL() + "': " + e.Message,
                        e);
                }
            }
            else if (evalNode is EvalEveryDistinctForgeNode) {
                var distinctNode = (EvalEveryDistinctForgeNode) evalNode;
                var matchEventFromChildNodes = AnalyzeMatchEvent(distinctNode);
                var streamTypeService = GetStreamTypeService(
                    matchEventFromChildNodes.TaggedEventTypes,
                    matchEventFromChildNodes.ArrayEventTypes,
                    distinctNode,
                    streamNum,
                    statementRawInfo,
                    services);
                var validationContext =
                    new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build();
                IList<ExprNode> validated;
                try {
                    validated = ValidateExpressions(
                        ExprNodeOrigin.PATTERNEVERYDISTINCT,
                        distinctNode.Expressions,
                        validationContext);
                }
                catch (ExprValidationPropertyException ex) {
                    throw new ExprValidationPropertyException(
                        ex.Message +
                        ", every-distinct requires that all properties resolve from sub-expressions to the every-distinct",
                        ex.InnerException);
                }

                var convertor = new MatchedEventConvertorForge(
                    matchEventFromChildNodes.TaggedEventTypes,
                    matchEventFromChildNodes.ArrayEventTypes,
                    allTagNamesOrdered,
                    null,
                    false);

                distinctNode.Convertor = convertor;

                // Determine whether some expressions are constants or time period
                IList<ExprNode> distinctExpressions = new List<ExprNode>();
                TimePeriodComputeForge timePeriodComputeForge = null;
                ExprNode expiryTimeExp = null;
                var count = -1;
                var last = validated.Count - 1;
                foreach (var expr in validated) {
                    count++;
                    if (count == last && expr is ExprTimePeriod) {
                        expiryTimeExp = expr;
                        var timePeriodExpr = (ExprTimePeriod) expiryTimeExp;
                        timePeriodComputeForge = timePeriodExpr.TimePeriodComputeForge;
                    }
                    else if (expr.Forge.ForgeConstantType.IsCompileTimeConstant) {
                        if (count == last) {
                            var value = expr.Forge.ExprEvaluator.Evaluate(null, true, null);
                            if (!value.IsNumber()) {
                                throw new ExprValidationException(
                                    "Invalid parameter for every-distinct, expected number of seconds constant (constant not considered for distinct)");
                            }

                            var secondsExpire = expr.Forge.ExprEvaluator.Evaluate(null, true, null);
                            var timeExpire = secondsExpire == null
                                ? (long?) null
                                : (long?) services.ImportServiceCompileTime.TimeAbacus.DeltaForSecondsNumber(
                                    secondsExpire);
                            if (timeExpire != null && timeExpire > 0) {
                                timePeriodComputeForge = new TimePeriodComputeConstGivenDeltaForge(timeExpire.Value);
                                expiryTimeExp = expr;
                            }
                            else {
                                Log.Warn(
                                    "Invalid seconds-expire " +
                                    timeExpire +
                                    " for " +
                                    ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expr));
                            }
                        }
                        else {
                            Log.Warn(
                                "Every-distinct node utilizes an expression returning a constant value, please check expression '" +
                                ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expr) +
                                "', not adding expression to distinct-value expression list");
                        }
                    }
                    else {
                        distinctExpressions.Add(expr);
                    }
                }

                if (distinctExpressions.IsEmpty()) {
                    throw new ExprValidationException(
                        "Every-distinct node requires one or more distinct-value expressions that each return non-constant result values");
                }

                var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(distinctExpressions.ToArray(), false, statementRawInfo, services.SerdeResolver);
                distinctNode.SetDistinctExpressions(distinctExpressions, multiKeyPlan.ClassRef, timePeriodComputeForge, expiryTimeExp);
                additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
            }
            else if (evalNode is EvalMatchUntilForgeNode) {
                var matchUntilNode = (EvalMatchUntilForgeNode) evalNode;

                // compile bounds expressions, if any
                var untilMatchEventSpec = new MatchEventSpec(tags.TaggedEventTypes, tags.ArrayEventTypes);
                var streamTypeService = GetStreamTypeService(
                    untilMatchEventSpec.TaggedEventTypes,
                    untilMatchEventSpec.ArrayEventTypes,
                    matchUntilNode,
                    streamNum,
                    statementRawInfo,
                    services);
                var validationContext =
                    new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build();

                var lower = ValidateBounds(matchUntilNode.LowerBounds, validationContext);
                matchUntilNode.LowerBounds = lower;

                var upper = ValidateBounds(matchUntilNode.UpperBounds, validationContext);
                matchUntilNode.UpperBounds = upper;

                var single = ValidateBounds(matchUntilNode.SingleBound, validationContext);
                matchUntilNode.SingleBound = single;

                bool tightlyBound;
                if (matchUntilNode.SingleBound != null) {
                    ValidateMatchUntil(matchUntilNode.SingleBound, matchUntilNode.SingleBound, false);
                    tightlyBound = true;
                }
                else {
                    var allowZeroLowerBounds = matchUntilNode.LowerBounds != null && matchUntilNode.UpperBounds != null;
                    tightlyBound = ValidateMatchUntil(
                        matchUntilNode.LowerBounds,
                        matchUntilNode.UpperBounds,
                        allowZeroLowerBounds);
                }

                if (matchUntilNode.SingleBound == null && !tightlyBound && matchUntilNode.ChildNodes.Count < 2) {
                    throw new ExprValidationException("Variable bounds repeat operator requires an until-expression");
                }

                var convertor = new MatchedEventConvertorForge(
                    untilMatchEventSpec.TaggedEventTypes,
                    untilMatchEventSpec.ArrayEventTypes,
                    allTagNamesOrdered,
                    null,
                    false);

                matchUntilNode.Convertor = convertor;

                // compile new tag lists
                ISet<string> arrayTags = null;
                var matchUntilAnalysisResult = EvalNodeUtil.RecursiveAnalyzeChildNodes(matchUntilNode.ChildNodes[0]);
                foreach (var filterNode in matchUntilAnalysisResult.FilterNodes) {
                    var optionalTag = filterNode.EventAsName;
                    if (optionalTag != null) {
                        if (arrayTags == null) {
                            arrayTags = new HashSet<string>();
                        }

                        arrayTags.Add(optionalTag);
                    }
                }

                if (arrayTags != null) {
                    foreach (var arrayTag in arrayTags) {
                        if (!tags.ArrayEventTypes.ContainsKey(arrayTag)) {
                            tags.ArrayEventTypes.Put(arrayTag, tags.TaggedEventTypes.Get(arrayTag));
                            tags.TaggedEventTypes.Remove(arrayTag);
                        }
                    }
                }

                matchUntilNode.TagsArrayedSet = GetIndexesForTags(allTagNamesOrdered, arrayTags);
            }
            else if (evalNode is EvalFollowedByForgeNode) {
                var followedByNode = (EvalFollowedByForgeNode) evalNode;
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(false);
                var validationContext =
                    new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build();

                if (followedByNode.OptionalMaxExpressions != null) {
                    IList<ExprNode> validated = new List<ExprNode>();
                    foreach (var maxExpr in followedByNode.OptionalMaxExpressions) {
                        if (maxExpr == null) {
                            validated.Add(null);
                        }
                        else {
                            var visitor = new ExprNodeSummaryVisitor();
                            maxExpr.Accept(visitor);
                            if (!visitor.IsPlain) {
                                var errorMessage = "Invalid maximum expression in followed-by, " +
                                                   visitor.Message +
                                                   " are not allowed within the expression";
                                Log.Error(errorMessage);
                                throw new ExprValidationException(errorMessage);
                            }

                            var validatedExpr = ExprNodeUtilityValidate.GetValidatedSubtree(
                                ExprNodeOrigin.FOLLOWEDBYMAX,
                                maxExpr,
                                validationContext);
                            validated.Add(validatedExpr);
                            var returnType = validatedExpr.Forge.EvaluationType;
                            if (returnType == null || !returnType.IsNumeric()) {
                                var message =
                                    "Invalid maximum expression in followed-by, the expression must return an integer value";
                                throw new ExprValidationException(message);
                            }
                        }
                    }

                    followedByNode.OptionalMaxExpressions = validated;
                }
            }

            if (newTaggedEventTypes != null) {
                tags.TaggedEventTypes.PutAll(newTaggedEventTypes);
            }

            if (newArrayEventTypes != null) {
                tags.ArrayEventTypes.PutAll(newArrayEventTypes);
            }
        }
Exemplo n.º 17
0
        public static SelectExprProcessorDescriptor GetProcessor(
            SelectProcessorArgs args,
            InsertIntoDesc insertIntoDesc,
            bool withSubscriber)
        {
            IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>();

            SelectExprProcessorWInsertTarget synthetic = GetProcessorInternal(args, insertIntoDesc);
            additionalForgeables.AddAll(synthetic.AdditionalForgeables);

            // plan serdes for variant event types
            if (synthetic.InsertIntoTargetType is VariantEventType ||
                synthetic.InsertIntoTargetType is WrapperEventType && 
                (((WrapperEventType) synthetic.InsertIntoTargetType).UnderlyingEventType is VariantEventType)) {
                var serdeForgeables = SerdeEventTypeUtility.Plan(
                    synthetic.Forge.ResultEventType,
                    args.StatementRawInfo,
                    args.CompileTimeServices.SerdeEventTypeRegistry,
                    args.CompileTimeServices.SerdeResolver);
                additionalForgeables.AddAll(serdeForgeables);
                foreach (EventType eventType in args.TypeService.EventTypes) {
                    serdeForgeables = SerdeEventTypeUtility.Plan(
                        eventType,
                        args.StatementRawInfo,
                        args.CompileTimeServices.SerdeEventTypeRegistry,
                        args.CompileTimeServices.SerdeResolver);
                    additionalForgeables.AddAll(serdeForgeables);
                }
            }

            if (args.IsFireAndForget || !withSubscriber) {
                return new SelectExprProcessorDescriptor(new SelectSubscriberDescriptor(), synthetic.Forge, additionalForgeables);
            }

            // Handle for-clause delivery contract checking
            ExprNode[] groupedDeliveryExpr = null;
            MultiKeyClassRef groupedDeliveryMultiKey = null;

            var forDelivery = false;
            if (args.ForClauseSpec != null) {
                foreach (var item in args.ForClauseSpec.Clauses) {
                    if (item.Keyword == null) {
                        throw new ExprValidationException(
                            "Expected any of the " +
                            EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() +
                            " for-clause keywords after reserved keyword 'for'");
                    }

                    try {
                        var keyword = EnumHelper.Parse<ForClauseKeyword>(item.Keyword);
                        if (keyword == ForClauseKeyword.GROUPED_DELIVERY && item.Expressions.IsEmpty()) {
                            throw new ExprValidationException(
                                "The for-clause with the " +
                                ForClauseKeyword.GROUPED_DELIVERY.GetName() +
                                " keyword requires one or more grouping expressions");
                        }

                        if (keyword == ForClauseKeyword.DISCRETE_DELIVERY && !item.Expressions.IsEmpty()) {
                            throw new ExprValidationException(
                                "The for-clause with the " +
                                ForClauseKeyword.DISCRETE_DELIVERY.GetName() +
                                " keyword does not allow grouping expressions");
                        }

                        if (forDelivery) {
                            throw new ExprValidationException(
                                "The for-clause with delivery keywords may only occur once in a statement");
                        }
                    }
                    catch (ExprValidationException) {
                        throw;
                    }
                    catch (EPException) {
                        throw;
                    }
                    catch (Exception) {
                        throw new ExprValidationException(
                            "Expected any of the " +
                            EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() +
                            " for-clause keywords after reserved keyword 'for'");
                    }

                    StreamTypeService type = new StreamTypeServiceImpl(synthetic.Forge.ResultEventType, null, false);
                    groupedDeliveryExpr = new ExprNode[item.Expressions.Count];
                    var validationContext = new ExprValidationContextBuilder(
                            type,
                            args.StatementRawInfo,
                            args.CompileTimeServices)
                        .WithAllowBindingConsumption(true)
                        .Build();
                    for (var i = 0; i < item.Expressions.Count; i++) {
                        groupedDeliveryExpr[i] = ExprNodeUtilityValidate.GetValidatedSubtree(
                            ExprNodeOrigin.FORCLAUSE,
                            item.Expressions[i],
                            validationContext);
                    }

                    forDelivery = true;
                    
                    MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(
                        groupedDeliveryExpr, false, args.StatementRawInfo, args.SerdeResolver);
                    groupedDeliveryMultiKey = multiKeyPlan.ClassRef;
                    additionalForgeables = multiKeyPlan.MultiKeyForgeables;
                }

                if (groupedDeliveryExpr != null && groupedDeliveryExpr.Length == 0) {
                    groupedDeliveryExpr = null;
                }
            }

            var allowSubscriber = args.CompileTimeServices.Configuration.Compiler.ByteCode.IsAllowSubscriber;
            SelectSubscriberDescriptor descriptor;
            SelectExprProcessorForge forge;

            if (allowSubscriber) {
                BindProcessorForge bindProcessor = new BindProcessorForge(
                    synthetic.Forge,
                    args.SelectionList,
                    args.TypeService.EventTypes,
                    args.TypeService.StreamNames,
                    args.TableCompileTimeResolver);
                descriptor = new SelectSubscriberDescriptor(
                    bindProcessor.ExpressionTypes,
                    bindProcessor.ColumnNamesAssigned,
                    forDelivery,
                    groupedDeliveryExpr,
                    groupedDeliveryMultiKey);
                forge = new BindSelectExprProcessorForge(synthetic.Forge, bindProcessor);
            } else {
                descriptor = new SelectSubscriberDescriptor();
                forge = new ListenerOnlySelectExprProcessorForge(synthetic.Forge);
            }

            return new SelectExprProcessorDescriptor(descriptor, forge, additionalForgeables);
        }
Exemplo n.º 18
0
        public FAFQueryMethodSelectDesc(
            StatementSpecCompiled statementSpec,
            Compilable compilable,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            Annotations = statementSpec.Annotations;
            ContextName = statementSpec.Raw.OptionalContextName;

            var queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;
            if (queryPlanLogging) {
                QUERY_PLAN_LOG.Info("Query plans for Fire-and-forget query '" + compilable.ToEPL() + "'");
            }

            HasTableAccess = statementSpec.TableAccessNodes != null && statementSpec.TableAccessNodes.Count > 0;
            foreach (var streamSpec in statementSpec.StreamSpecs) {
                HasTableAccess |= streamSpec is TableQueryStreamSpec;
            }

            HasTableAccess |= StatementLifecycleSvcUtil.IsSubqueryWithTable(
                statementSpec.SubselectNodes, services.TableCompileTimeResolver);
            IsDistinct = statementSpec.SelectClauseCompiled.IsDistinct;

            FAFQueryMethodHelper.ValidateFAFQuery(statementSpec);

            var numStreams = statementSpec.StreamSpecs.Length;
            var typesPerStream = new EventType[numStreams];
            var namesPerStream = new string[numStreams];
            var eventTypeNames = new string[numStreams];
            Processors = new FireAndForgetProcessorForge[numStreams];
            ConsumerFilters = new ExprNode[numStreams];

            // check context partition use
            if (statementSpec.Raw.OptionalContextName != null) {
                if (numStreams > 1) {
                    throw new ExprValidationException(
                        "Joins in runtime queries for context partitions are not supported");
                }
            }

            // resolve types and processors
            for (var i = 0; i < numStreams; i++) {
                var streamSpec = statementSpec.StreamSpecs[i];
                Processors[i] = FireAndForgetProcessorForgeFactory.ValidateResolveProcessor(streamSpec);
                if (numStreams > 1 && Processors[i].ContextName != null) {
                    throw new ExprValidationException(
                        "Joins against named windows that are under context are not supported");
                }

                var streamName = Processors[i].NamedWindowOrTableName;
                if (streamSpec.OptionalStreamName != null) {
                    streamName = streamSpec.OptionalStreamName;
                }

                namesPerStream[i] = streamName;
                typesPerStream[i] = Processors[i].EventTypeRspInputEvents;
                eventTypeNames[i] = typesPerStream[i].Name;

                IList<ExprNode> consumerFilterExprs;
                if (streamSpec is NamedWindowConsumerStreamSpec) {
                    var namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
                    consumerFilterExprs = namedSpec.FilterExpressions;
                }
                else {
                    var tableSpec = (TableQueryStreamSpec) streamSpec;
                    consumerFilterExprs = tableSpec.FilterExpressions;
                }

                ConsumerFilters[i] = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(consumerFilterExprs);
            }

            // compile filter to optimize access to named window
            var optionalStreamsIfAny = OuterJoinAnalyzer.OptionalStreamsIfAny(statementSpec.Raw.OuterJoinDescList);
            var types = new StreamTypeServiceImpl(
                typesPerStream,
                namesPerStream,
                new bool[numStreams],
                false,
                optionalStreamsIfAny);
            var excludePlanHint = ExcludePlanHint.GetHint(types.StreamNames, statementRawInfo, services);
            QueryGraph = new QueryGraphForge(numStreams, excludePlanHint, false);
            if (statementSpec.Raw.WhereClause != null) {
                for (var i = 0; i < numStreams; i++) {
                    try {
                        var validationContext = new ExprValidationContextBuilder(types, statementRawInfo, services)
                            .WithAllowBindingConsumption(true)
                            .WithIsFilterExpression(true)
                            .Build();
                        var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                            ExprNodeOrigin.FILTER,
                            statementSpec.Raw.WhereClause,
                            validationContext);
                        FilterExprAnalyzer.Analyze(validated, QueryGraph, false);
                    }
                    catch (Exception ex) {
                        Log.Warn("Unexpected exception analyzing filter paths: " + ex.Message, ex);
                    }
                }
            }
            
            // handle subselects
            // first we create streams for subselects, if there are any
            var @base = new StatementBaseInfo(compilable, statementSpec, null, statementRawInfo, null);
            var subqueryNamedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
            SubSelectActivationDesc subSelectActivationDesc = SubSelectHelperActivations.CreateSubSelectActivation(
                EmptyList<FilterSpecCompiled>.Instance, subqueryNamedWindowConsumers, @base, services);
            IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation = subSelectActivationDesc.Subselects;
            AdditionalForgeables.AddAll(subSelectActivationDesc.AdditionalForgeables);

            SubSelectHelperForgePlan subSelectForgePlan = SubSelectHelperForgePlanner.PlanSubSelect(
                @base, subselectActivation, namesPerStream, typesPerStream, eventTypeNames, services);
            SubselectForges = subSelectForgePlan.Subselects;
            AdditionalForgeables.AddAll(subSelectForgePlan.AdditionalForgeables);

            // obtain result set processor
            var isIStreamOnly = new bool[namesPerStream.Length];
            isIStreamOnly.Fill(true);
            StreamTypeService typeService = new StreamTypeServiceImpl(
                typesPerStream,
                namesPerStream,
                isIStreamOnly,
                true,
                optionalStreamsIfAny);
            WhereClause = EPStatementStartMethodHelperValidate.ValidateNodes(
                statementSpec.Raw,
                typeService,
                null,
                statementRawInfo,
                services);

            var resultSetSpec = new ResultSetSpec(statementSpec);
            ResultSetProcessor = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                resultSetSpec,
                typeService,
                null,
                new bool[0],
                true,
                null,
                true,
                false,
                statementRawInfo,
                services);
            AdditionalForgeables.AddAll(ResultSetProcessor.AdditionalForgeables);

            // plan table access
            TableAccessForges = ExprTableEvalHelperPlan.PlanTableAccess(statementSpec.Raw.TableExpressions);

            // plan joins or simple queries
            if (numStreams > 1) {
                var streamJoinAnalysisResult = new StreamJoinAnalysisResultCompileTime(numStreams);
                CompatExtensions.Fill(streamJoinAnalysisResult.NamedWindowsPerStream, (NamedWindowMetaData) null);
                for (var i = 0; i < numStreams; i++) {
                    var uniqueIndexes = Processors[i].UniqueIndexes;
                    streamJoinAnalysisResult.UniqueKeys[i] = uniqueIndexes;
                }

                var hasAggregations = ResultSetProcessor.ResultSetProcessorType.IsAggregated();
                var desc = JoinSetComposerPrototypeForgeFactory.MakeComposerPrototype(
                    statementSpec,
                    streamJoinAnalysisResult,
                    types,
                    new HistoricalViewableDesc(numStreams),
                    true,
                    hasAggregations,
                    statementRawInfo,
                    services);
                AdditionalForgeables.AddAll(desc.AdditionalForgeables);
                Joins = desc.Forge;
            }
            else {
                Joins = null;
            }
            
            var multiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct(
                IsDistinct, ResultSetProcessor.ResultEventType, statementRawInfo, SerdeCompileTimeResolverNonHA.INSTANCE);
            AdditionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
            DistinctMultiKey = multiKeyPlan.ClassRef;
        }
Exemplo n.º 19
0
        public static OnTriggerPlan HandleContextFactoryOnTrigger(
            string className,
            CodegenNamespaceScope namespaceScope,
            string classPostfix,
            NamedWindowMetaData namedWindow,
            TableMetaData table,
            OnTriggerWindowPlan planDesc,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            // validate context
            var infraName = planDesc.OnTriggerDesc.WindowName;
            var infraTitle = (namedWindow != null ? "Named window" : "Table") + " '" + infraName + "'";
            var infraContextName = namedWindow != null ? namedWindow.ContextName : table.OptionalContextName;
            var infraModuleName = namedWindow != null ? namedWindow.NamedWindowModuleName : table.TableModuleName;
            var infraEventType = namedWindow != null ? namedWindow.EventType : table.InternalEventType;
            var resultEventType = namedWindow != null ? namedWindow.EventType : table.PublicEventType;
            var infraVisibility = namedWindow != null
                ? namedWindow.EventType.Metadata.AccessModifier
                : table.TableVisibility;
            ValidateOnExpressionContext(planDesc.ContextName, infraContextName, infraTitle);

            List<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>();

            // validate expressions and plan subselects
            var validationResult = OnTriggerPlanValidator.ValidateOnTriggerPlan(
                infraEventType,
                planDesc.OnTriggerDesc,
                planDesc.StreamSpec,
                planDesc.ActivatorResult,
                planDesc.SubselectActivation,
                @base,
                services);
            additionalForgeables.AddAll(validationResult.AdditionalForgeables);

            var validatedJoin = validationResult.ValidatedJoin;
            var activatorResultEventType = planDesc.ActivatorResult.ActivatorResultEventType;

            var pair = IndexHintPair.GetIndexHintPair(
                planDesc.OnTriggerDesc,
                @base.StatementSpec.StreamSpecs[0].OptionalStreamName,
                @base.StatementRawInfo,
                services);
            var indexHint = pair.IndexHint;
            var excludePlanHint = pair.ExcludePlanHint;

            var enabledSubqueryIndexShare = namedWindow != null && namedWindow.IsEnableIndexShare;
            var isVirtualWindow = namedWindow != null && namedWindow.IsVirtualDataWindow;
            var indexMetadata = namedWindow != null ? namedWindow.IndexMetadata : table.IndexMetadata;
            var optionalUniqueKeySet = namedWindow != null ? namedWindow.UniquenessAsSet : table.UniquenessAsSet;

            // query plan
            var onlyUseExistingIndexes = table != null;
            SubordinateWMatchExprQueryPlanResult planResult = SubordinateQueryPlanner.PlanOnExpression(
                validatedJoin,
                activatorResultEventType,
                indexHint,
                enabledSubqueryIndexShare,
                -1,
                excludePlanHint,
                isVirtualWindow,
                indexMetadata,
                infraEventType,
                optionalUniqueKeySet,
                onlyUseExistingIndexes,
                @base.StatementRawInfo,
                services);
            SubordinateWMatchExprQueryPlanForge queryPlan = planResult.Forge;
            additionalForgeables.AddAll(planResult.AdditionalForgeables);
            
            // indicate index dependencies
            if (queryPlan.Indexes != null && infraVisibility == NameAccessModifier.PUBLIC) {
                foreach (var index in queryPlan.Indexes) {
                    services.ModuleDependenciesCompileTime.AddPathIndex(
                        namedWindow != null,
                        infraName,
                        infraModuleName,
                        index.IndexName,
                        index.IndexModuleName,
                        services.NamedWindowCompileTimeRegistry,
                        services.TableCompileTimeRegistry);
                }
            }

            var onTriggerType = planDesc.OnTriggerDesc.OnTriggerType;
            var activator = planDesc.ActivatorResult.Activator;
            var subselectForges = validationResult.SubselectForges;
            var tableAccessForges = validationResult.TableAccessForges;

            IList<StmtClassForgeable> forgeables = new List<StmtClassForgeable>(2);
            StatementAgentInstanceFactoryOnTriggerInfraBaseForge forge;
            var classNameRSP = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(ResultSetProcessorFactoryProvider),
                classPostfix);
            ResultSetProcessorDesc resultSetProcessor;

            if (onTriggerType == OnTriggerType.ON_SELECT) {
                resultSetProcessor = validationResult.ResultSetProcessorPrototype;
                var outputEventType = resultSetProcessor.ResultEventType;

                var insertInto = false;
                TableMetaData optionalInsertIntoTable = null;
                var insertIntoDesc = @base.StatementSpec.Raw.InsertIntoDesc;
                var addToFront = false;
                if (insertIntoDesc != null) {
                    insertInto = true;
                    optionalInsertIntoTable = services.TableCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName);
                    var optionalInsertIntoNamedWindow =
                        services.NamedWindowCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName);
                    addToFront = optionalInsertIntoNamedWindow != null || optionalInsertIntoTable != null;
                }

                var selectAndDelete = planDesc.OnTriggerDesc.IsDeleteAndSelect;
                var distinct = @base.StatementSpec.SelectClauseCompiled.IsDistinct;
                MultiKeyPlan distinctMultiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct(
                    distinct,
                    outputEventType,
                    @base.StatementRawInfo,
                    services.SerdeResolver);
                additionalForgeables.AddAll(distinctMultiKeyPlan.MultiKeyForgeables);
                forge = new StatementAgentInstanceFactoryOnTriggerInfraSelectForge(
                    activator,
                    outputEventType,
                    subselectForges,
                    tableAccessForges,
                    namedWindow,
                    table,
                    queryPlan,
                    classNameRSP,
                    insertInto,
                    addToFront,
                    optionalInsertIntoTable,
                    selectAndDelete,
                    distinct,
                    distinctMultiKeyPlan.ClassRef);
            }
            else {
                var defaultSelectAllSpec = new StatementSpecCompiled();
                defaultSelectAllSpec.SelectClauseCompiled.WithSelectExprList(new SelectClauseElementWildcard());
                defaultSelectAllSpec.Raw.SelectStreamDirEnum = SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH;
                StreamTypeService typeService = new StreamTypeServiceImpl(
                    new[] {resultEventType},
                    new[] {infraName},
                    new[] {false},
                    false,
                    false);
                resultSetProcessor = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                    new ResultSetSpec(defaultSelectAllSpec),
                    typeService,
                    null,
                    new bool[1],
                    false,
                    @base.ContextPropertyRegistry,
                    false,
                    false,
                    @base.StatementRawInfo,
                    services);

                if (onTriggerType == OnTriggerType.ON_DELETE) {
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraDeleteForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan);
                }
                else if (onTriggerType == OnTriggerType.ON_UPDATE) {
                    var updateDesc = (OnTriggerWindowUpdateDesc) planDesc.OnTriggerDesc;
                    EventBeanUpdateHelperForge updateHelper = EventBeanUpdateHelperForgeFactory.Make(
                        infraName,
                        (EventTypeSPI) infraEventType,
                        updateDesc.Assignments,
                        validationResult.ZeroStreamAliasName,
                        activatorResultEventType,
                        namedWindow != null,
                        @base.StatementName,
                        services.EventTypeAvroHandler);
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraUpdateForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan,
                        updateHelper);
                }
                else if (onTriggerType == OnTriggerType.ON_MERGE) {
                    var onMergeTriggerDesc = (OnTriggerMergeDesc) planDesc.OnTriggerDesc;
                    var onMergeHelper = new InfraOnMergeHelperForge(
                        onMergeTriggerDesc,
                        activatorResultEventType,
                        planDesc.StreamSpec.OptionalStreamName,
                        infraName,
                        (EventTypeSPI) infraEventType,
                        @base.StatementRawInfo,
                        services,
                        table);
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraMergeForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan,
                        onMergeHelper);
                }
                else {
                    throw new IllegalStateException("Unrecognized trigger type " + onTriggerType);
                }
            }

            forgeables.Add(
                new StmtClassForgeableRSPFactoryProvider(
                    classNameRSP,
                    resultSetProcessor,
                    namespaceScope,
                    @base.StatementRawInfo));

            var queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;
            SubordinateQueryPlannerUtil.QueryPlanLogOnExpr(
                queryPlanLogging,
                QUERY_PLAN_LOG,
                queryPlan,
                @base.StatementSpec.Annotations,
                services.ImportServiceCompileTime);

            StmtClassForgeableAIFactoryProviderOnTrigger onTrigger = new StmtClassForgeableAIFactoryProviderOnTrigger(className, namespaceScope, forge);
            return new OnTriggerPlan(onTrigger, forgeables, resultSetProcessor.SelectSubscriberDescriptor, additionalForgeables);
        }
        /// <summary>
        ///     Constructs indexing and lookup strategy for a given relationship that a historical stream may have with another
        ///     stream (historical or not) that looks up into results of a poll of a historical stream.
        ///     <para />
        ///     The term "polled" refers to the assumed-historical stream.
        /// </summary>
        /// <param name="queryGraph">relationship representation of where-clause filter and outer join on-expressions</param>
        /// <param name="polledViewType">the event type of the historical that is indexed</param>
        /// <param name="streamViewType">the event type of the stream looking up in indexes</param>
        /// <param name="polledViewStreamNum">the stream number of the historical that is indexed</param>
        /// <param name="streamViewStreamNum">the stream number of the historical that is looking up</param>
        /// <param name="raw"></param>
        /// <param name="serdeResolver"></param>
        /// <returns>indexing and lookup strategy pair</returns>
        public static JoinSetComposerPrototypeHistoricalDesc DetermineIndexing(
            QueryGraphForge queryGraph,
            EventType polledViewType,
            EventType streamViewType,
            int polledViewStreamNum,
            int streamViewStreamNum,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var queryGraphValue = queryGraph.GetGraphValue(streamViewStreamNum, polledViewStreamNum);
            var hashKeysAndIndes = queryGraphValue.HashKeyProps;
            var rangeKeysAndIndex = queryGraphValue.RangeProps;

            // index and key property names
            var hashKeys = hashKeysAndIndes.Keys;
            var hashIndexes = hashKeysAndIndes.Indexed;
            var rangeKeys = rangeKeysAndIndex.Keys;
            var rangeIndexes = rangeKeysAndIndex.Indexed;

            // If the analysis revealed no join columns, must use the brute-force full table scan
            if (hashKeys.IsEmpty() && rangeKeys.IsEmpty()) {
                var inKeywordSingles = queryGraphValue.InKeywordSingles;
                if (inKeywordSingles != null && inKeywordSingles.Indexed.Length != 0) {
                    var indexed = inKeywordSingles.Indexed[0];
                    var lookup = inKeywordSingles.Key[0];
                    var strategy =
                        new HistoricalIndexLookupStrategyInKeywordSingleForge(streamViewStreamNum, lookup.KeyExprs);
                    var indexing = new PollResultIndexingStrategyHashForge(
                        polledViewStreamNum,
                        polledViewType,
                        new string[]{ indexed },
                        null,
                        null);
                    return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
                }

                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty()) {
                    var multi = multis[0];
                    var strategy =
                        new HistoricalIndexLookupStrategyInKeywordMultiForge(streamViewStreamNum, multi.Key.KeyExpr);
                    var indexing =
                        new PollResultIndexingStrategyInKeywordMultiForge(
                            polledViewStreamNum,
                            polledViewType,
                            ExprNodeUtilityQuery.GetIdentResolvedPropertyNames(multi.Indexed));
                    return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
                }

                return new JoinSetComposerPrototypeHistoricalDesc(
                    HistoricalIndexLookupStrategyNoIndexForge.INSTANCE,
                    PollResultIndexingStrategyNoIndexForge.INSTANCE,
                    EmptyList<StmtClassForgeableFactory>.Instance);
            }

            CoercionDesc keyCoercionTypes = CoercionUtil.GetCoercionTypesHash(
                new[] {streamViewType, polledViewType},
                0,
                1,
                hashKeys,
                hashIndexes);

            if (rangeKeys.IsEmpty()) {
                var hashEvals = QueryGraphValueEntryHashKeyedForge.GetForges(hashKeys.ToArray());
                var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashEvals, false, raw, serdeResolver);
                var lookup = new HistoricalIndexLookupStrategyHashForge(
                    streamViewStreamNum, hashEvals, keyCoercionTypes.CoercionTypes, multiKeyPlan.ClassRef);
                var indexing = new PollResultIndexingStrategyHashForge(
                    polledViewStreamNum,
                    polledViewType,
                    hashIndexes,
                    keyCoercionTypes.CoercionTypes,
                    multiKeyPlan.ClassRef);
                return new JoinSetComposerPrototypeHistoricalDesc(lookup, indexing, multiKeyPlan.MultiKeyForgeables);
            }

            CoercionDesc rangeCoercionTypes = CoercionUtil.GetCoercionTypesRange(
                new[] {streamViewType, polledViewType},
                1,
                rangeIndexes,
                rangeKeys);

            if (rangeKeys.Count == 1 && hashKeys.Count == 0) {
                var rangeCoercionType = rangeCoercionTypes.CoercionTypes[0];
                var indexing = new PollResultIndexingStrategySortedForge(
                    polledViewStreamNum,
                    polledViewType,
                    rangeIndexes[0],
                    rangeCoercionType);
                var lookup = new HistoricalIndexLookupStrategySortedForge(
                    streamViewStreamNum,
                    rangeKeys[0],
                    rangeCoercionType);
                return new JoinSetComposerPrototypeHistoricalDesc(lookup, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
            }
            else {
                var hashEvals = QueryGraphValueEntryHashKeyedForge.GetForges(hashKeys.ToArray());
                var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashEvals, false, raw, serdeResolver);
                var strategy = new HistoricalIndexLookupStrategyCompositeForge(
                    streamViewStreamNum,
                    hashEvals,
                    multiKeyPlan.ClassRef,
                    rangeKeys.ToArray());
                var indexing = new PollResultIndexingStrategyCompositeForge(
                    polledViewStreamNum,
                    polledViewType,
                    hashIndexes,
                    keyCoercionTypes.CoercionTypes,
                    multiKeyPlan.ClassRef,
                    rangeIndexes,
                    rangeCoercionTypes.CoercionTypes);
                return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, multiKeyPlan.MultiKeyForgeables);
            }
        }
Exemplo n.º 21
0
        public static SubordinateQueryPlan PlanSubquery(
            EventType[] outerStreams,
            SubordPropPlan joinDesc,
            bool isNWOnTrigger,
            bool forceTableScan,
            IndexHint optionalIndexHint,
            bool indexShare,
            int subqueryNumber,
            bool isVirtualDataWindow,
            EventTableIndexMetadata indexMetadata,
            ISet<string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes,
            EventType eventTypeIndexed,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (isVirtualDataWindow) {
                var indexProps = GetIndexPropDesc(joinDesc.HashProps, joinDesc.RangeProps);
                var lookupStrategyFactoryX = new SubordTableLookupStrategyFactoryForgeVDW(
                    statementRawInfo.StatementName,
                    statementRawInfo.Annotations,
                    outerStreams,
                    indexProps.HashJoinedProps,
                    new CoercionDesc(false, indexProps.HashIndexCoercionType),
                    indexProps.RangeJoinedProps,
                    new CoercionDesc(false, indexProps.RangeIndexCoercionType),
                    isNWOnTrigger,
                    joinDesc,
                    forceTableScan,
                    indexProps.ListPair);
                var forge = new SubordinateQueryPlanDescForge(lookupStrategyFactoryX, null);
                return new SubordinateQueryPlan(forge, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            if (joinDesc.CustomIndexOps != null && !joinDesc.CustomIndexOps.IsEmpty()) {
                foreach (var op
                    in joinDesc.CustomIndexOps) {
                    foreach (var index in indexMetadata.Indexes) {
                        if (IsCustomIndexMatch(index, op)) {
                            var provisionDesc =
                                index.Value.OptionalQueryPlanIndexItem.AdvancedIndexProvisionDesc;
                            var lookupStrategyFactoryX =
                                provisionDesc.Factory.Forge.GetSubordinateLookupStrategy(
                                    op.Key.OperationName,
                                    op.Value.PositionalExpressions,
                                    isNWOnTrigger,
                                    outerStreams.Length);
                            var provisionCompileTime =
                                provisionDesc.ToCompileTime(eventTypeIndexed, statementRawInfo, services);
                            var indexItemForge = new QueryPlanIndexItemForge(
                                new string[0],
                                new Type[0],
                                new string[0],
                                new Type[0],
                                false,
                                provisionCompileTime,
                                eventTypeIndexed);
                            var indexDesc = new SubordinateQueryIndexDescForge(
                                null,
                                index.Value.OptionalIndexName,
                                index.Value.OptionalIndexModuleName,
                                index.Key,
                                indexItemForge);
                            var forge = new SubordinateQueryPlanDescForge(lookupStrategyFactoryX, new SubordinateQueryIndexDescForge[]{indexDesc});
                            return new SubordinateQueryPlan(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                        }
                    }
                }
            }

            var hashKeys = Collections.GetEmptyList<SubordPropHashKeyForge>();
            CoercionDesc hashKeyCoercionTypes = null;
            var rangeKeys = Collections.GetEmptyList<SubordPropRangeKeyForge>();
            CoercionDesc rangeKeyCoercionTypes = null;
            IList<ExprNode> inKeywordSingleIdxKeys = null;
            ExprNode inKeywordMultiIdxKey = null;

            SubordinateQueryIndexDescForge[] indexDescs;
            var additionalForgeables = new List<StmtClassForgeableFactory>();
            MultiKeyClassRef multiKeyClasses = null;
            if (joinDesc.InKeywordSingleIndex != null) {
                var single = joinDesc.InKeywordSingleIndex;
                var keyInfo = new SubordPropHashKeyForge(
                    new QueryGraphValueEntryHashKeyedForgeExpr(single.Expressions[0], false),
                    null,
                    single.CoercionType);
                var index = FindOrSuggestIndex(
                    Collections.SingletonMap(single.IndexedProp, keyInfo),
                    EmptyDictionary<string, SubordPropRangeKeyForge>.Instance,
                    optionalIndexHint,
                    indexShare,
                    subqueryNumber,
                    indexMetadata,
                    optionalUniqueKeyProps,
                    onlyUseExistingIndexes,
                    eventTypeIndexed,
                    statementRawInfo,
                    services);
                
                if (index == null) {
                    return null;
                }

                var indexDesc = index.Forge;
                var desc = new SubordinateQueryIndexDescForge(
                    indexDesc.OptionalIndexKeyInfo,
                    indexDesc.IndexName,
                    indexDesc.IndexModuleName,
                    indexDesc.IndexMultiKey,
                    indexDesc.OptionalQueryPlanIndexItem);
                indexDescs = new[] {desc};
                inKeywordSingleIdxKeys = single.Expressions;
                additionalForgeables.AddAll(index.MultiKeyForgeables);
            }
            else if (joinDesc.InKeywordMultiIndex != null) {
                var multi = joinDesc.InKeywordMultiIndex;

                indexDescs = new SubordinateQueryIndexDescForge[multi.IndexedProp.Length];
                for (var i = 0; i < multi.IndexedProp.Length; i++) {
                    var keyInfo = new SubordPropHashKeyForge(
                        new QueryGraphValueEntryHashKeyedForgeExpr(multi.Expression, false),
                        null,
                        multi.CoercionType);
                    var index = FindOrSuggestIndex(
                        Collections.SingletonMap(multi.IndexedProp[i], keyInfo),
                        EmptyDictionary<string, SubordPropRangeKeyForge>.Instance,
                        optionalIndexHint,
                        indexShare,
                        subqueryNumber,
                        indexMetadata,
                        optionalUniqueKeyProps,
                        onlyUseExistingIndexes,
                        eventTypeIndexed,
                        statementRawInfo,
                        services);
                    var indexDesc = index.Forge;
                    additionalForgeables.AddAll(index.MultiKeyForgeables);
                    if (indexDesc == null) {
                        return null;
                    }

                    indexDescs[i] = indexDesc;
                }

                inKeywordMultiIdxKey = multi.Expression;
            }
            else {
                var index = FindOrSuggestIndex(
                    joinDesc.HashProps,
                    joinDesc.RangeProps,
                    optionalIndexHint,
                    false,
                    subqueryNumber,
                    indexMetadata,
                    optionalUniqueKeyProps,
                    onlyUseExistingIndexes,
                    eventTypeIndexed,
                    statementRawInfo,
                    services);
                if (index == null) {
                    return null;
                }
                var indexDesc = index.Forge;
                additionalForgeables.AddRange(index.MultiKeyForgeables);
                var indexKeyInfo = indexDesc.OptionalIndexKeyInfo;

                hashKeys = indexKeyInfo.OrderedHashDesc;
                hashKeyCoercionTypes = indexKeyInfo.OrderedKeyCoercionTypes;
                rangeKeys = indexKeyInfo.OrderedRangeDesc;
                rangeKeyCoercionTypes = indexKeyInfo.OrderedRangeCoercionTypes;
                var desc = new SubordinateQueryIndexDescForge(
                    indexDesc.OptionalIndexKeyInfo,
                    indexDesc.IndexName,
                    indexDesc.IndexModuleName,
                    indexDesc.IndexMultiKey,
                    indexDesc.OptionalQueryPlanIndexItem);
                indexDescs = new[] {desc};
                
                if (indexDesc.OptionalQueryPlanIndexItem == null) {
                    var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashKeyCoercionTypes.CoercionTypes, true, statementRawInfo, services.SerdeResolver);
                    multiKeyClasses = multiKeyPlan.ClassRef;
                    additionalForgeables.AddRange(multiKeyPlan.MultiKeyForgeables);
                } else {
                    multiKeyClasses = indexDesc.OptionalQueryPlanIndexItem.HashMultiKeyClasses;
                }
            }

            if (forceTableScan) {
                return null;
            }

            var lookupStrategyFactory = SubordinateTableLookupStrategyUtil.GetLookupStrategy(
                outerStreams,
                hashKeys,
                hashKeyCoercionTypes,
                multiKeyClasses,
                rangeKeys,
                rangeKeyCoercionTypes,
                inKeywordSingleIdxKeys,
                inKeywordMultiIdxKey,
                isNWOnTrigger);
            var forgeX = new SubordinateQueryPlanDescForge(lookupStrategyFactory, indexDescs);
            return new SubordinateQueryPlan(forgeX, additionalForgeables);
        }
        public SubSelectStrategyFactoryIndexShareForge(
            int subqueryNumber,
            SubSelectActivationPlan subselectActivation,
            EventType[] outerEventTypesSelect,
            NamedWindowMetaData namedWindow,
            TableMetaData table,
            bool fullTableScan,
            IndexHint indexHint,
            SubordPropPlan joinedPropPlan,
            ExprForge filterExprEval,
            ExprNode[] groupKeys,
            AggregationServiceForgeDesc aggregationServiceForgeDesc,
            StatementBaseInfo statement,
            StatementCompileTimeServices services)
        {
            _subqueryNumber = subqueryNumber;
            _namedWindow    = namedWindow;
            _table          = table;
            _filterExprEval = filterExprEval;
            _groupKeys      = groupKeys;
            _aggregationServiceForgeDesc = aggregationServiceForgeDesc;

            bool queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;

            // We only use existing indexes in all cases. This means "create index" is required.
            SubordinateQueryPlan plan;

            if (table != null)
            {
                plan = SubordinateQueryPlanner.PlanSubquery(
                    outerEventTypesSelect,
                    joinedPropPlan,
                    false,
                    fullTableScan,
                    indexHint,
                    true,
                    subqueryNumber,
                    false,
                    table.IndexMetadata,
                    table.UniquenessAsSet,
                    true,
                    table.InternalEventType,
                    statement.StatementRawInfo,
                    services);
            }
            else
            {
                plan = SubordinateQueryPlanner.PlanSubquery(
                    outerEventTypesSelect,
                    joinedPropPlan,
                    false,
                    fullTableScan,
                    indexHint,
                    true,
                    subqueryNumber,
                    namedWindow.IsVirtualDataWindow,
                    namedWindow.IndexMetadata,
                    namedWindow.UniquenessAsSet,
                    true,
                    namedWindow.EventType,
                    statement.StatementRawInfo,
                    services);
            }

            _queryPlan = plan == null ? null : plan.Forge;
            if (plan != null)
            {
                _additionalForgeables.AddAll(plan.AdditionalForgeables);
            }

            if (_queryPlan != null && _queryPlan.IndexDescs != null)
            {
                for (int i = 0; i < _queryPlan.IndexDescs.Length; i++)
                {
                    SubordinateQueryIndexDescForge index = _queryPlan.IndexDescs[i];

                    if (table != null)
                    {
                        if (table.TableVisibility == NameAccessModifier.PUBLIC)
                        {
                            services.ModuleDependenciesCompileTime.AddPathIndex(
                                false,
                                table.TableName,
                                table.TableModuleName,
                                index.IndexName,
                                index.IndexModuleName,
                                services.NamedWindowCompileTimeRegistry,
                                services.TableCompileTimeRegistry);
                        }
                    }
                    else
                    {
                        if (namedWindow.EventType.Metadata.AccessModifier == NameAccessModifier.PUBLIC)
                        {
                            services.ModuleDependenciesCompileTime.AddPathIndex(
                                true,
                                namedWindow.EventType.Name,
                                namedWindow.NamedWindowModuleName,
                                index.IndexName,
                                index.IndexModuleName,
                                services.NamedWindowCompileTimeRegistry,
                                services.TableCompileTimeRegistry);
                        }
                    }
                }
            }

            SubordinateQueryPlannerUtil.QueryPlanLogOnSubq(
                queryPlanLogging,
                QUERY_PLAN_LOG,
                _queryPlan,
                subqueryNumber,
                statement.StatementRawInfo.Annotations,
                services.ImportServiceCompileTime);

            if (groupKeys == null || groupKeys.Length == 0)
            {
                _groupByMultiKey = null;
            }
            else
            {
                MultiKeyPlan mkplan = MultiKeyPlanner.PlanMultiKey(groupKeys, false, statement.StatementRawInfo, services.SerdeResolver);
                _additionalForgeables.AddAll(mkplan.MultiKeyForgeables);
                _groupByMultiKey = mkplan.ClassRef;
            }
        }
Exemplo n.º 23
0
        public static CodegenMethod Codegen(
            ExprEqualsNodeForgeNC forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope,
            ExprForge lhs,
            ExprForge rhs)
        {
            var lhsType = lhs.EvaluationType;
            var rhsType = rhs.EvaluationType;
            var methodNode = codegenMethodScope.MakeChild(typeof(bool), typeof(ExprEqualsNodeForgeNCForgeIs), codegenClassScope);

            CodegenExpression compare;
            if (rhsType != null && lhsType != null) {
                if (!lhsType.IsArray) {
                    methodNode.Block
                        .DeclareVar<object>("left", lhs.EvaluateCodegen(typeof(object), methodNode, exprSymbol, codegenClassScope))
                        .DeclareVar<object>("right", rhs.EvaluateCodegen(typeof(object), methodNode, exprSymbol, codegenClassScope));
                    compare = StaticMethod<object>("Equals", Ref("left"), Ref("right"));
                }
                else {
                    methodNode.Block
                        .DeclareVar(lhsType, "left", lhs.EvaluateCodegen(lhsType, methodNode, exprSymbol, codegenClassScope))
                        .DeclareVar(rhsType, "right", rhs.EvaluateCodegen(rhsType, methodNode, exprSymbol, codegenClassScope));
                    if (!MultiKeyPlanner.RequiresDeepEquals(lhsType.GetElementType())) {
                        compare = StaticMethod(typeof(Arrays), "AreEqual", Ref("left"), Ref("right"));
                    }
                    else {
                        compare = StaticMethod(typeof(Arrays), "DeepEquals", Ref("left"), Ref("right"));
                    }
                }

                methodNode.Block.DeclareVarNoInit(typeof(bool), "result")
                    .IfRefNull("left")
                    .AssignRef("result", EqualsNull(Ref("right")))
                    .IfElse()
                    .AssignRef("result", And(NotEqualsNull(Ref("right")), compare))
                    .BlockEnd();
            }
            else {
                if (lhsType == null && rhsType == null) {
                    methodNode.Block.DeclareVar<bool>("result", ConstantTrue());
                }
                else if (lhsType == null) {
                    methodNode.Block
                        .DeclareVar<object>("right", rhs.EvaluateCodegen(typeof(object), methodNode, exprSymbol, codegenClassScope))
                        .DeclareVar<bool>("result", EqualsNull(Ref("right")));
                }
                else {
                    methodNode.Block
                        .DeclareVar<object>("left", lhs.EvaluateCodegen(typeof(object), methodNode, exprSymbol, codegenClassScope))
                        .DeclareVar<bool>("result", EqualsNull(Ref("left")));
                }
            }

            if (!forge.ForgeRenderable.IsNotEquals) {
                methodNode.Block.MethodReturn(Ref("result"));
            }
            else {
                methodNode.Block.MethodReturn(Not(Ref("result")));
            }

            return methodNode;
        }
        public override IList<StmtClassForgeableFactory> Validate(
            StreamTypeService typeService,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            // validate and visit
            var validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services)
                .WithAllowBindingConsumption(true)
                .Build();

            var visitor = new ExprNodeIdentifierAndStreamRefVisitor(true);
            var validatedInputParameters = new List<ExprNode>();

            foreach (var exprNode in methodStreamSpec.Expressions) {
                var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                    ExprNodeOrigin.METHODINVJOIN,
                    exprNode,
                    validationContext);
                validatedInputParameters.Add(validated);
                validated.Accept(visitor);
            }

            // determine required streams
            foreach (ExprNodePropOrStreamDesc @ref in visitor.Refs) {
                SubordinateStreams.Add(@ref.StreamNum);
            }

            // class-based evaluation
            MethodInfo targetMethod = null;
            if (metadata.MethodProviderClass != null) {
                // resolve actual method to use
                ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler {
                    ProcHandle = e => {
                        if (methodStreamSpec.Expressions.Count == 0) {
                            return new ExprValidationException(
                                "Method footprint does not match the number or type of expression parameters, expecting no parameters in method: " +
                                e.Message);
                        }

                        var resultTypes = ExprNodeUtilityQuery.GetExprResultTypes(validatedInputParameters);
                        return new ExprValidationException(
                            "Method footprint does not match the number or type of expression parameters, expecting a method where parameters are typed '" +
                            TypeHelper.GetParameterAsString(resultTypes) +
                            "': " +
                            e.Message);
                    }
                };
                var desc = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream(
                    metadata.MethodProviderClass.FullName,
                    metadata.IsStaticMethod ? null : metadata.MethodProviderClass,
                    methodStreamSpec.MethodName,
                    validatedInputParameters,
                    false,
                    null,
                    handler,
                    methodStreamSpec.MethodName,
                    @base.StatementRawInfo,
                    services);
                InputParamEvaluators = desc.ChildForges;
                targetMethod = desc.ReflectionMethod;
            }
            else {
                // script-based evaluation
                InputParamEvaluators = ExprNodeUtilityQuery.GetForges(ExprNodeUtilityQuery.ToArray(validatedInputParameters));
            }
            
            // plan multikey
            MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver);
            MultiKeyClassRef = multiKeyPlan.ClassRef;

            Pair<MethodTargetStrategyForge, MethodConversionStrategyForge> strategies =
                PollExecStrategyPlanner.Plan(metadata, targetMethod, EventType);
            target = strategies.First;
            conversion = strategies.Second;
            
            return multiKeyPlan.MultiKeyForgeables;
        }
Exemplo n.º 25
0
        public StmtForgeMethodResult Make(
            string @namespace,
            string classPostfix,
            StatementCompileTimeServices services)
        {
            var spec = _base.StatementSpec.Raw.CreateIndexDesc;

            var infraName = spec.WindowName;
            var namedWindow = services.NamedWindowCompileTimeResolver.Resolve(infraName);
            var table = services.TableCompileTimeResolver.Resolve(infraName);
            if (namedWindow == null && table == null) {
                throw new ExprValidationException("A named window or table by name '" + infraName + "' does not exist");
            }

            if (namedWindow != null && table != null) {
                throw new ExprValidationException("A named window or table by name '" + infraName + "' are both found");
            }

            string infraModuleName;
            NameAccessModifier infraVisibility;
            EventType indexedEventType;
            string infraContextName;
            if (namedWindow != null) {
                infraModuleName = namedWindow.NamedWindowModuleName;
                infraVisibility = namedWindow.EventType.Metadata.AccessModifier;
                indexedEventType = namedWindow.EventType;
                infraContextName = namedWindow.ContextName;
            }
            else {
                infraModuleName = table.TableModuleName;
                infraVisibility = table.TableVisibility;
                indexedEventType = table.InternalEventType;
                infraContextName = table.OptionalContextName;

                if (!table.IsKeyed) {
                    throw new ExprValidationException(
                        "Tables without primary key column(s) do not allow creating an index");
                }
            }

            EPLValidationUtil.ValidateContextName(
                namedWindow == null,
                infraName,
                infraContextName,
                _base.StatementSpec.Raw.OptionalContextName,
                true);

            // validate index
            var explicitIndexDesc = EventTableIndexUtil.ValidateCompileExplicitIndex(
                spec.IndexName,
                spec.IsUnique,
                spec.Columns,
                indexedEventType,
                _base.StatementRawInfo,
                services);
            var advancedIndexDesc = explicitIndexDesc.AdvancedIndexProvisionDesc == null
                ? null
                : explicitIndexDesc.AdvancedIndexProvisionDesc.IndexDesc.AdvancedIndexDescRuntime;
            var imk = new IndexMultiKey(
                spec.IsUnique,
                explicitIndexDesc.HashPropsAsList,
                explicitIndexDesc.BtreePropsAsList,
                advancedIndexDesc);

            // add index as a new index to module-init
            var indexKey = new IndexCompileTimeKey(
                infraModuleName,
                infraName,
                infraVisibility,
                namedWindow != null,
                spec.IndexName,
                _base.ModuleName);
            services.IndexCompileTimeRegistry.NewIndex(indexKey, new IndexDetailForge(imk, explicitIndexDesc));

            // add index current named window information
            if (namedWindow != null) {
                namedWindow.AddIndex(spec.IndexName, _base.ModuleName, imk, explicitIndexDesc.ToRuntime());
            }
            else {
                table.AddIndex(spec.IndexName, _base.ModuleName, imk, explicitIndexDesc.ToRuntime());
            }

            // determine multikey plan
            MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(
                explicitIndexDesc.HashTypes, false, _base.StatementRawInfo, services.SerdeResolver);
            explicitIndexDesc.HashMultiKeyClasses = multiKeyPlan.ClassRef;
            DataInputOutputSerdeForge[] rangeSerdes = new DataInputOutputSerdeForge[explicitIndexDesc.RangeProps.Length];
            for (int i = 0; i < explicitIndexDesc.RangeProps.Length; i++) {
                rangeSerdes[i] = services.SerdeResolver.SerdeForIndexBtree(
                    explicitIndexDesc.RangeTypes[i], _base.StatementRawInfo);
            }
            explicitIndexDesc.RangeSerdes = rangeSerdes;

            
            var statementFieldsClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(StatementFields), classPostfix);
            var namespaceScope = new CodegenNamespaceScope(
                @namespace, statementFieldsClassName, services.IsInstrumented);
            var fieldsForgeable = new StmtClassForgeableStmtFields(statementFieldsClassName, namespaceScope, 0);

            var aiFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(StatementAIFactoryProvider),
                classPostfix);
            var forge = new StatementAgentInstanceFactoryCreateIndexForge(
                indexedEventType,
                spec.IndexName,
                _base.ModuleName,
                explicitIndexDesc,
                imk,
                namedWindow,
                table);
            var aiFactoryForgeable = new StmtClassForgeableAIFactoryProviderCreateIndex(
                aiFactoryProviderClassName,
                namespaceScope,
                forge);

            var selectSubscriberDescriptor = new SelectSubscriberDescriptor();
            var informationals = StatementInformationalsUtil.GetInformationals(
                _base,
                EmptyList<FilterSpecCompiled>.Instance,
                EmptyList<ScheduleHandleCallbackProvider>.Instance,
                EmptyList<NamedWindowConsumerStreamSpec>.Instance,
                true,
                selectSubscriberDescriptor,
                namespaceScope,
                services);
            informationals.Properties.Put(StatementProperty.CREATEOBJECTNAME, spec.IndexName);

            var statementProviderClassName =
                CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix);
            var stmtProvider = new StmtClassForgeableStmtProvider(
                aiFactoryProviderClassName,
                statementProviderClassName,
                informationals,
                namespaceScope);

            var forgeables = new List<StmtClassForgeable>();
            foreach (var additional in multiKeyPlan.MultiKeyForgeables) {
                forgeables.Add(additional.Make(namespaceScope, classPostfix));
            }
            forgeables.Add(fieldsForgeable);
            forgeables.Add(aiFactoryForgeable);
            forgeables.Add(stmtProvider);
            return new StmtForgeMethodResult(
                forgeables,
                EmptyList<FilterSpecCompiled>.Instance,
                EmptyList<ScheduleHandleCallbackProvider>.Instance,
                EmptyList<NamedWindowConsumerStreamSpec>.Instance,
                EmptyList<FilterSpecParamExprNodeForge>.Instance);
        }