Beispiel #1
0
 public static FilterSpecCompiled MakeFilterSpec(
     EventType eventType,
     string eventTypeName,
     IList<ExprNode> filterExpessions,
     PropertyEvalSpec optionalPropertyEvalSpec,
     IDictionary<string, Pair<EventType, string>> taggedEventTypes,
     IDictionary<string, Pair<EventType, string>> arrayEventTypes,
     StreamTypeService streamTypeService,
     string optionalStreamName,
     StatementRawInfo statementRawInfo,
     StatementCompileTimeServices services)
 {
     // Validate all nodes, make sure each returns a boolean and types are good;
     // Also decompose all AND super nodes into individual expressions
     var validatedNodes = ValidateAllowSubquery(
         ExprNodeOrigin.FILTER,
         filterExpessions,
         streamTypeService,
         taggedEventTypes,
         arrayEventTypes,
         statementRawInfo,
         services);
     return Build(
         validatedNodes,
         eventType,
         eventTypeName,
         optionalPropertyEvalSpec,
         taggedEventTypes,
         arrayEventTypes,
         streamTypeService,
         optionalStreamName,
         statementRawInfo,
         services);
 }
        public static FilterSpecParamForge HandleRangeNode(
            ExprBetweenNode betweenNode,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            var left = betweenNode.ChildNodes[0];
            ExprFilterSpecLookupableForge lookupable = null;

            if (left is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) left;
                lookupable = filterOptimizableNode.FilterLookupable;
            }
            else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) &&
                     IsLimitedLookupableExpression(left)) {
                lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services);
            }

            if (lookupable == null) {
                return null;
            }

            FilterOperator op = FilterOperatorExtensions.ParseRangeOperator(
                betweenNode.IsLowEndpointIncluded,
                betweenNode.IsHighEndpointIncluded,
                betweenNode.IsNotBetween);

            var low = HandleRangeNodeEndpoint(betweenNode.ChildNodes[1], taggedEventTypes, arrayEventTypes, allTagNamesOrdered, statementName, raw, services);
            var high = HandleRangeNodeEndpoint(betweenNode.ChildNodes[2], taggedEventTypes, arrayEventTypes, allTagNamesOrdered, statementName, raw, services);
            return low == null || high == null ? null : new FilterSpecParamRangeForge(lookupable, op, low, high);
        }
Beispiel #3
0
        public static IList<ExprNode> ValidateAllowSubquery(
            ExprNodeOrigin exprNodeOrigin,
            IList<ExprNode> exprNodes,
            StreamTypeService streamTypeService,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            IList<ExprNode> validatedNodes = new List<ExprNode>();

            ExprValidationContext validationContext =
                new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services)
                    .WithAllowBindingConsumption(true)
                    .WithIsFilterExpression(true)
                    .Build();
            foreach (var node in exprNodes) {
                // Determine subselects
                var visitor = new ExprNodeSubselectDeclaredDotVisitor();
                node.Accept(visitor);

                // Compile subselects
                if (!visitor.Subselects.IsEmpty()) {
                    // The outer event type is the filtered-type itself
                    foreach (var subselect in visitor.Subselects) {
                        try {
                            SubSelectHelperFilters.HandleSubselectSelectClauses(
                                subselect,
                                streamTypeService.EventTypes[0],
                                streamTypeService.StreamNames[0],
                                streamTypeService.StreamNames[0],
                                taggedEventTypes,
                                arrayEventTypes,
                                statementRawInfo,
                                services);
                        }
                        catch (ExprValidationException ex) {
                            throw new ExprValidationException(
                                "Failed to validate " +
                                ExprNodeUtilityMake.GetSubqueryInfoText(subselect) +
                                ": " +
                                ex.Message,
                                ex);
                        }
                    }
                }

                var validated = ExprNodeUtilityValidate.GetValidatedSubtree(exprNodeOrigin, node, validationContext);
                validatedNodes.Add(validated);

                if (validated.Forge.EvaluationType != typeof(bool?) && validated.Forge.EvaluationType != typeof(bool)) {
                    throw new ExprValidationException(
                        "Filter expression not returning a boolean value: '" +
                        ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validated) +
                        "'");
                }
            }

            return validatedNodes;
        }
Beispiel #4
0
 public static FilterSpecCompiledDesc Build(
     FilterSpecValidatedDesc validatedDesc,
     EventType eventType,
     string eventTypeName,
     PropertyEvalSpec optionalPropertyEvalSpec,
     IDictionary<string, Pair<EventType, string>> taggedEventTypes,
     IDictionary<string, Pair<EventType, string>> arrayEventTypes,
     ISet<string> allTagNamesOrdered,
     StreamTypeService streamTypeService,
     string optionalStreamName,
     StatementRawInfo statementRawInfo,
     StatementCompileTimeServices compileTimeServices)
 {
     var compiled = BuildNoStmtCtx(
         validatedDesc.Expressions,
         eventType,
         eventTypeName,
         optionalStreamName,
         optionalPropertyEvalSpec,
         taggedEventTypes,
         arrayEventTypes,
         allTagNamesOrdered,
         streamTypeService,
         statementRawInfo,
         compileTimeServices);
     return new FilterSpecCompiledDesc(compiled, validatedDesc.AdditionalForgeables);
 }
Beispiel #5
0
        private static void LogFilterPlans(
            IList<ExprNode> validatedNodes,
            FilterSpecPlanForge plan,
            EventType eventType,
            string optionalStreamName,
            StatementRawInfo statementRawInfo)
        {
            var buf = new StringBuilder();
            buf
                .Append("Filter plan for statement '")
                .Append(statementRawInfo.StatementName)
                .Append("' filtering event type '")
                .Append(eventType.Name + "'");

            if (optionalStreamName != null) {
                buf.Append(" alias '" + optionalStreamName + "'");
            }
            if (validatedNodes.IsEmpty()) {
                buf.Append(" empty");
            } else {
                var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(validatedNodes);
                var expression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(andNode);
                buf
                    .Append(" expression '")
                    .Append(expression)
                    .Append("' for ")
                    .Append(plan.Paths.Length)
                    .Append(" paths");
            }
            buf.Append(Environment.NewLine);

            plan.AppendPlan(buf);

            Log.Info(buf.ToString());
        }
Beispiel #6
0
 public static PatternStreamSpecCompiled CompilePattern(
     PatternStreamSpecRaw streamSpecRaw,
     ISet<string> eventTypeReferences,
     bool isInsertInto,
     bool isJoin,
     bool isContextDeclaration,
     bool isOnTrigger,
     string optionalStreamName,
     int streamNum,
     StatementRawInfo statementRawInfo,
     StatementCompileTimeServices services)
 {
     return CompilePatternWTags(
         streamSpecRaw,
         eventTypeReferences,
         isInsertInto,
         null,
         null,
         isJoin,
         isContextDeclaration,
         isOnTrigger,
         streamNum,
         statementRawInfo,
         services);
 }
        private static FilterSpecPlanPathTripletForge HandleOrAlternateExpression(
            ExprOrNode orNode,
            bool performConditionPlanning,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            ISet <string> allTagNamesOrdered,
            string statementName,
            StreamTypeService streamTypeService,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            IList <ExprNode> valueExpressions = new List <ExprNode>(orNode.ChildNodes.Length);

            foreach (ExprNode child in orNode.ChildNodes)
            {
                FilterSpecExprNodeVisitorValueLimitedExpr visitor = new FilterSpecExprNodeVisitorValueLimitedExpr();
                child.Accept(visitor);
                if (visitor.IsLimited)
                {
                    valueExpressions.Add(child);
                }
            }

            // The or-node must have a single constituent and one or more value expressions
            if (orNode.ChildNodes.Length != valueExpressions.Count + 1)
            {
                return(null);
            }

            IList <ExprNode> constituents = new List <ExprNode>(orNode.ChildNodes);

            constituents.RemoveAll(valueExpressions);
            if (constituents.Count != 1)
            {
                throw new IllegalStateException("Found multiple constituents");
            }

            ExprNode constituent = constituents[0];

            FilterSpecPlanPathTripletForge triplet = MakeFilterParam(
                constituent,
                performConditionPlanning,
                taggedEventTypes,
                arrayEventTypes,
                allTagNamesOrdered,
                statementName,
                streamTypeService,
                raw,
                services);

            if (triplet == null)
            {
                return(null);
            }

            ExprNode controlConfirm = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(valueExpressions);

            return(new FilterSpecPlanPathTripletForge(triplet.Param, controlConfirm));
        }
Beispiel #8
0
        public static FilterSpecCompiled BuildNoStmtCtx(
            IList<ExprNode> validatedNodes,
            EventType eventType,
            string eventTypeName,
            string optionalStreamName,
            PropertyEvalSpec optionalPropertyEvalSpec,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            StreamTypeService streamTypeService,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            PropertyEvaluatorForge optionalPropertyEvaluator = null;
            if (optionalPropertyEvalSpec != null) {
                optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                    optionalPropertyEvalSpec,
                    eventType,
                    optionalStreamName,
                    statementRawInfo,
                    compileTimeServices);
            }

            // unwind "and" and "or"
            var unwound = FilterSpecCompilerIndexPlannerUnwindAndOr.UnwindAndOr(validatedNodes);

            var args = new FilterSpecCompilerArgs(
                taggedEventTypes,
                arrayEventTypes,
                allTagNamesOrdered,
                streamTypeService,
                null,
                statementRawInfo,
                compileTimeServices);
            var plan = FilterSpecCompilerIndexPlanner.PlanFilterParameters(unwound, args);

            var hook = (FilterSpecCompileHook) ImportUtil.GetAnnotationHook(
                statementRawInfo.Annotations,
                HookType.INTERNAL_FILTERSPEC,
                typeof(FilterSpecCompileHook),
                compileTimeServices.ImportServiceCompileTime);
            hook?.FilterIndexPlan(eventType, unwound, plan);

            if (compileTimeServices.Configuration.Compiler.Logging.IsEnableFilterPlan) {
                LogFilterPlans(unwound, plan, eventType, optionalStreamName, statementRawInfo);
            }

            if (Log.IsDebugEnabled) {
                Log.Debug(".makeFilterSpec spec=" + plan);
            }

            return new FilterSpecCompiled(eventType, eventTypeName, plan, optionalPropertyEvaluator);
        }
Beispiel #9
0
        public static StreamSpecCompiledDesc Compile(
            StreamSpecRaw spec,
            ISet<string> eventTypeReferences,
            bool isInsertInto,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            string optionalStreamName,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (spec is DBStatementStreamSpec dbStatementStreamSpec) {
                return new StreamSpecCompiledDesc(dbStatementStreamSpec, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            if (spec is FilterStreamSpecRaw filterStreamSpecRaw) {
                return CompileFilter(
                    filterStreamSpecRaw,
                    isInsertInto,
                    isJoin,
                    isContextDeclaration,
                    isOnTrigger,
                    optionalStreamName,
                    statementRawInfo,
                    services);
            }

            if (spec is PatternStreamSpecRaw patternStreamSpecRaw) {
                return CompilePattern(
                    patternStreamSpecRaw,
                    eventTypeReferences,
                    isInsertInto,
                    isJoin,
                    isContextDeclaration,
                    isOnTrigger,
                    optionalStreamName,
                    streamNum,
                    statementRawInfo,
                    services);
            }

            if (spec is MethodStreamSpec methodStreamSpec) {
                return new StreamSpecCompiledDesc(
                    CompileMethod(methodStreamSpec),
                    EmptyList<StmtClassForgeableFactory>.Instance);
            }

            throw new IllegalStateException("Unrecognized stream spec " + spec);
        }
Beispiel #10
0
        private static StreamTypeService GetStreamTypeService(
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            EvalForgeNode forge,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            var filterTypes = new LinkedHashMap<string, Pair<EventType, string>>();
            filterTypes.PutAll(taggedEventTypes);

            // handle array tags (match-until clause)
            if (arrayEventTypes != null) {
                var eventTypeName =
                    services.EventTypeNameGeneratorStatement.GetAnonymousPatternName(streamNum, forge.FactoryNodeId);
                var metadata = new EventTypeMetadata(
                    eventTypeName,
                    statementRawInfo.ModuleName,
                    EventTypeTypeClass.PATTERNDERIVED,
                    EventTypeApplicationType.MAP,
                    NameAccessModifier.TRANSIENT,
                    EventTypeBusModifier.NONBUS,
                    false,
                    EventTypeIdPair.Unassigned());
                var mapProperties = GetMapProperties(
                    new Dictionary<string, Pair<EventType, string>>(),
                    arrayEventTypes);
                var mapEventType = BaseNestableEventUtil.MakeMapTypeCompileTime(
                    metadata,
                    mapProperties,
                    null,
                    null,
                    null,
                    null,
                    services.BeanEventTypeFactoryPrivate,
                    services.EventTypeCompileTimeResolver);
                services.EventTypeCompileTimeRegistry.NewType(mapEventType);

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

            return new StreamTypeServiceImpl(filterTypes, true, false);
        }
Beispiel #11
0
        internal static ExprFilterSpecLookupableForge MakeLimitedLookupableForgeMayNull(
            ExprNode lookupable,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            if (!HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services)) {
                return null;
            }

            var lookupableType = lookupable.Forge.EvaluationType;
            var expression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(lookupable);
            var getterForge = new FilterSpecCompilerIndexLimitedLookupableGetterForge(lookupable);
            var serde = services.SerdeResolver.SerdeForFilter(lookupableType, raw);
            return new ExprFilterSpecLookupableForge(expression, getterForge, null, lookupableType, true, serde);
        }
Beispiel #12
0
 public FilterSpecCompilerArgs(
     IDictionary<string, Pair<EventType, string>> taggedEventTypes,
     IDictionary<string, Pair<EventType, string>> arrayEventTypes,
     StreamTypeService streamTypeService,
     ContextCompileTimeDescriptor contextDescriptor,
     StatementRawInfo statementRawInfo,
     StatementCompileTimeServices compileTimeServices)
 {
     this.taggedEventTypes = taggedEventTypes;
     this.arrayEventTypes = arrayEventTypes;
     this.streamTypeService = streamTypeService;
     this.contextDescriptor = contextDescriptor;
     this.statementRawInfo = statementRawInfo;
     this.compileTimeServices = compileTimeServices;
 }
Beispiel #13
0
        public static StreamSpecCompiled Compile(
            StreamSpecRaw spec,
            ISet<string> eventTypeReferences,
            bool isInsertInto,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            string optionalStreamName,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (spec is DBStatementStreamSpec) {
                return (DBStatementStreamSpec) spec;
            }

            if (spec is FilterStreamSpecRaw) {
                return CompileFilter(
                    (FilterStreamSpecRaw) spec,
                    isInsertInto,
                    isJoin,
                    isContextDeclaration,
                    isOnTrigger,
                    optionalStreamName,
                    statementRawInfo,
                    services);
            }

            if (spec is PatternStreamSpecRaw) {
                return CompilePattern(
                    (PatternStreamSpecRaw) spec,
                    eventTypeReferences,
                    isInsertInto,
                    isJoin,
                    isContextDeclaration,
                    isOnTrigger,
                    optionalStreamName,
                    streamNum,
                    statementRawInfo,
                    services);
            }

            if (spec is MethodStreamSpec) {
                return CompileMethod((MethodStreamSpec) spec);
            }

            throw new IllegalStateException("Unrecognized stream spec " + spec);
        }
        internal static FilterSpecParamForge HandleBooleanLimited(
            ExprNode constituent,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            StreamTypeService streamTypeService,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            if (!HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.BOOLCOMPOSITE, raw, services)) {
                return null;
            }

            // prequalify
            var prequalified = Prequalify(constituent);
            if (!prequalified) {
                return null;
            }

            // determine rewrite
            var desc = FindRewrite(constituent);
            if (desc == null) {
                return null;
            }

            // there is no value expression, i.e. "select * from SupportBean(theString = intPrimitive)"
            if (desc is RewriteDescriptorNoValueExpr) {
                var reboolExpression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedence(constituent, new ExprNodeRenderableFlags(false));
                var lookupable = new ExprFilterSpecLookupableForge(reboolExpression, null, constituent.Forge, null, true, null);
                return new FilterSpecParamValueNullForge(lookupable, FilterOperator.REBOOL);
            }

            // there is no value expression, i.e. "select * from SupportBean(theString regexp 'abc')"
            var withValueExpr = (RewriteDescriptorWithValueExpr) desc;
            ExprNode valueExpression = withValueExpr.ValueExpression;
            var valueExpressionType = valueExpression.Forge.EvaluationType;
            var replacement = new ExprFilterReboolValueNode(valueExpressionType);
            ExprNodeUtilityModify.ReplaceChildNode(withValueExpr.ValueExpressionParent, valueExpression, replacement);
            var validationContext = new ExprValidationContextBuilder(streamTypeService, raw, services).WithIsFilterExpression(true).Build();
            var rebool = ExprNodeUtilityValidate.GetValidatedSubtree(ExprNodeOrigin.FILTER, constituent, validationContext);
            DataInputOutputSerdeForge serde = services.SerdeResolver.SerdeForFilter(valueExpressionType, raw);
            var convertor = GetMatchEventConvertor(valueExpression, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);

            var reboolExpressionX = ExprNodeUtilityPrint.ToExpressionStringMinPrecedence(constituent, new ExprNodeRenderableFlags(false));
            var lookupableX = new ExprFilterSpecLookupableForge(reboolExpressionX, null, rebool.Forge, valueExpressionType, true, serde);
            return new FilterSpecParamValueLimitedExprForge(lookupableX, FilterOperator.REBOOL, valueExpression, convertor, null);
        }
        private static FilterSpecParamForge HandleLimitedExpr(
            FilterOperator op,
            ExprNode lookupable,
            ExprNode value,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            ExprFilterSpecLookupableForge lookupableForge;
            var lookupableType = lookupable.Forge.EvaluationType;
            var valueType = value.Forge.EvaluationType;
            if (lookupable is ExprIdentNode) {
                if (!FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services)) {
                    return null;
                }

                var identNode = (ExprIdentNode) lookupable;
                if (!identNode.FilterLookupEligible) {
                    return null;
                }

                lookupableForge = identNode.FilterLookupable;
            }
            else {
                if (!FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services)) {
                    return null;
                }

                lookupableForge = MakeLimitedLookupableForgeMayNull(lookupable, raw, services);
                if (lookupableForge == null) {
                    return null;
                }
            }

            var convertor = GetMatchEventConvertor(value, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
            var numberCoercer = GetNumberCoercer(lookupableType, valueType, lookupableForge.Expression);
            return new FilterSpecParamValueLimitedExprForge(lookupableForge, op, value, convertor, numberCoercer);
        }
Beispiel #16
0
        public static FilterSpecCompiled BuildNoStmtCtx(
            IList<ExprNode> validatedNodes,
            EventType eventType,
            string eventTypeName,
            string optionalStreamName,
            PropertyEvalSpec optionalPropertyEvalSpec,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            StreamTypeService streamTypeService,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices
        )
        {
            PropertyEvaluatorForge optionalPropertyEvaluator = null;
            if (optionalPropertyEvalSpec != null) {
                optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                    optionalPropertyEvalSpec,
                    eventType,
                    optionalStreamName,
                    statementRawInfo,
                    compileTimeServices);
            }

            var args = new FilterSpecCompilerArgs(
                taggedEventTypes,
                arrayEventTypes,
                streamTypeService,
                null,
                statementRawInfo,
                compileTimeServices);
            IList<FilterSpecParamForge>[] spec = FilterSpecCompilerPlanner.PlanFilterParameters(validatedNodes, args);

            if (Log.IsDebugEnabled) {
                Log.Debug(".makeFilterSpec spec=" + spec);
            }

            return new FilterSpecCompiled(eventType, eventTypeName, spec, optionalPropertyEvaluator);
        }
Beispiel #17
0
        internal static bool HasLevelOrHint(
            FilterSpecCompilerIndexPlannerHint requiredHint,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            var config = services.Configuration.Compiler.Execution.FilterIndexPlanning;
            if (config == ConfigurationCompilerExecution.FilterIndexPlanningEnum.ADVANCED) {
                return true;
            }

            var hints = HintEnum.FILTERINDEX.GetHintAssignedValues(raw.Annotations);
            if (hints == null) {
                return false;
            }

            foreach (var hint in hints) {
                var hintAtoms = HintEnumExtensions.SplitCommaUnlessInParen(hint);
                for (var i = 0; i < hintAtoms.Length; i++) {
                    var hintAtom = hintAtoms[i];
                    var hintLowercase = hintAtom.ToLowerInvariant().Trim();
                    FilterSpecCompilerIndexPlannerHint? found = null;
                    foreach (var available in EnumHelper.GetValues<FilterSpecCompilerIndexPlannerHint>()) {
                        if (hintLowercase.Equals(available.GetNameInvariant())) {
                            found = available;
                            if (requiredHint == available) {
                                return true;
                            }
                        }
                    }

                    if (found == null) {
                        throw new ExprValidationException("Unrecognized filterindex hint value '" + hintAtom + "'");
                    }
                }
            }

            return false;
        }
Beispiel #18
0
 public static FilterSpecCompiled Build(
     IList<ExprNode> validatedNodes,
     EventType eventType,
     string eventTypeName,
     PropertyEvalSpec optionalPropertyEvalSpec,
     IDictionary<string, Pair<EventType, string>> taggedEventTypes,
     IDictionary<string, Pair<EventType, string>> arrayEventTypes,
     StreamTypeService streamTypeService,
     string optionalStreamName,
     StatementRawInfo statementRawInfo,
     StatementCompileTimeServices compileTimeServices)
 {
     return BuildNoStmtCtx(
         validatedNodes,
         eventType,
         eventTypeName,
         optionalStreamName,
         optionalPropertyEvalSpec,
         taggedEventTypes,
         arrayEventTypes,
         streamTypeService,
         statementRawInfo,
         compileTimeServices);
 }
Beispiel #19
0
        private static void RecursiveCompile(
            EvalForgeNode evalNode,
            ISet<string> eventTypeReferences,
            bool isInsertInto,
            MatchEventSpec tags,
            Stack<EvalForgeNode> parentNodeStack,
            ISet<string> allTagNamesOrdered,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            parentNodeStack.Push(evalNode);
            foreach (var child in evalNode.ChildNodes) {
                RecursiveCompile(
                    child,
                    eventTypeReferences,
                    isInsertInto,
                    tags,
                    parentNodeStack,
                    allTagNamesOrdered,
                    streamNum,
                    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);
                    }
                }

                // 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);
                        }
                    }
                }

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

                var spec = FilterSpecCompiler.MakeFilterSpec(
                    resolvedEventType,
                    eventName,
                    exprNodes,
                    filterNode.RawFilterSpec.OptionalPropertyEvalSpec,
                    filterTaggedEventTypes,
                    arrayCompositeEventTypes,
                    streamTypeService,
                    null,
                    statementRawInfo,
                    services);
                filterNode.FilterSpec = spec;
            }
            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);

                    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);

                    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);

                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");
                }

                distinctNode.SetDistinctExpressions(distinctExpressions, timePeriodComputeForge, expiryTimeExp);
            }
            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);

                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);
            }
        }
Beispiel #20
0
        public static PatternStreamSpecCompiled CompilePatternWTags(
            PatternStreamSpecRaw streamSpecRaw,
            ISet<string> eventTypeReferences,
            bool isInsertInto,
            MatchEventSpec tags,
            ISet<string> priorAllTags,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            // validate
            if ((streamSpecRaw.IsSuppressSameEventMatches || streamSpecRaw.IsDiscardPartialsOnMatch) &&
                (isJoin || isContextDeclaration || isOnTrigger)) {
                throw new ExprValidationException(
                    "Discard-partials and suppress-matches is not supported in a joins, context declaration and on-action");
            }

            if (tags == null) {
                tags = new MatchEventSpec();
            }

            var nodeStack = new Stack<EvalForgeNode>();

            // detemine ordered tags
            var allTagNamesOrdered = new LinkedHashSet<string>();
            var filterFactoryNodes = EvalNodeUtil.RecursiveGetChildNodes(
                streamSpecRaw.EvalForgeNode,
                FilterForFilterFactoryNodes.INSTANCE);
            if (priorAllTags != null) {
                allTagNamesOrdered.AddAll(priorAllTags);
            }

            foreach (var filterNode in filterFactoryNodes) {
                var forge = (EvalFilterForgeNode) filterNode;
                int tagNumber;
                if (forge.EventAsName != null) {
                    if (!allTagNamesOrdered.Contains(forge.EventAsName)) {
                        allTagNamesOrdered.Add(forge.EventAsName);
                        tagNumber = allTagNamesOrdered.Count - 1;
                    }
                    else {
                        tagNumber = FindTagNumber(forge.EventAsName, allTagNamesOrdered);
                    }

                    forge.EventAsTagNumber = tagNumber;
                }
            }

            // construct root : assigns factory node ids
            var top = streamSpecRaw.EvalForgeNode;
            var root = new EvalRootForgeNode(top, statementRawInfo.Annotations);
            RecursiveCompile(
                top,
                eventTypeReferences,
                isInsertInto,
                tags,
                nodeStack,
                allTagNamesOrdered,
                streamNum,
                statementRawInfo,
                services);

            var hook = (PatternCompileHook) ImportUtil.GetAnnotationHook(
                statementRawInfo.Annotations,
                HookType.INTERNAL_PATTERNCOMPILE,
                typeof(PatternCompileHook),
                services.ImportServiceCompileTime);
            if (hook != null) {
                hook.Pattern(root);
            }

            return new PatternStreamSpecCompiled(
                root,
                tags.TaggedEventTypes,
                tags.ArrayEventTypes,
                allTagNamesOrdered,
                streamSpecRaw.ViewSpecs,
                streamSpecRaw.OptionalStreamName,
                streamSpecRaw.Options,
                streamSpecRaw.IsSuppressSameEventMatches,
                streamSpecRaw.IsDiscardPartialsOnMatch);
        }
Beispiel #21
0
        public static StatementSpecCompiled Compile(
            StatementSpecRaw spec,
            Compilable compilable,
            bool isSubquery,
            bool isOnDemandQuery,
            Attribute[] annotations,
            IList<ExprSubselectNode> subselectNodes,
            IList<ExprTableAccessNode> tableAccessNodes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            IList<StreamSpecCompiled> compiledStreams;
            ISet<string> eventTypeReferences = new HashSet<string>();

            if (!isOnDemandQuery && spec.FireAndForgetSpec != null) {
                throw new StatementSpecCompileException(
                    "Provided EPL expression is an on-demand query expression (not a continuous query)",
                    compilable.ToEPL());
            }

            // If not using a join and not specifying a data window, make the where-clause, if present, the filter of the stream
            // if selecting using filter spec, and not subquery in where clause
            if (spec.StreamSpecs.Count == 1 &&
                spec.StreamSpecs[0] is FilterStreamSpecRaw &&
                spec.StreamSpecs[0].ViewSpecs.Length == 0 &&
                spec.WhereClause != null &&
                spec.OnTriggerDesc == null &&
                !isSubquery &&
                !isOnDemandQuery &&
                (tableAccessNodes == null || tableAccessNodes.IsEmpty())) {
                bool disqualified;
                ExprNode whereClause = spec.WhereClause;

                var visitorX = new ExprNodeSubselectDeclaredDotVisitor();
                whereClause.Accept(visitorX);
                disqualified = visitorX.Subselects.Count > 0 ||
                               HintEnum.DISABLE_WHEREEXPR_MOVETO_FILTER.GetHint(annotations) != null;

                if (!disqualified) {
                    var viewResourceVisitor = new ExprNodeViewResourceVisitor();
                    whereClause.Accept(viewResourceVisitor);
                    disqualified = viewResourceVisitor.ExprNodes.Count > 0;
                }

                if (!disqualified) {
                    spec.WhereClause = null;
                    var streamSpec = (FilterStreamSpecRaw) spec.StreamSpecs[0];
                    streamSpec.RawFilterSpec.FilterExpressions.Add(whereClause);
                }
            }

            // compile select-clause
            var selectClauseCompiled = CompileSelectClause(spec.SelectClauseSpec);

            // Determine subselects in filter streams, these may need special handling for locking
            var visitor = new ExprNodeSubselectDeclaredDotVisitor();
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkStreamSpecs(spec, visitor);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                subselectNode.IsFilterStreamSubselect = true;
            }

            // Determine subselects for compilation, and lambda-expression shortcut syntax for named windows
            visitor.Reset();
            GroupByClauseExpressions groupByRollupExpressions;
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(spec, visitor);

                var expressionCopier = new ExpressionCopier(
                    spec,
                    statementRawInfo.OptionalContextDescriptor,
                    compileTimeServices,
                    visitor);
                groupByRollupExpressions = GroupByExpressionHelper.GetGroupByRollupExpressions(
                    spec.GroupByExpressions,
                    spec.SelectClauseSpec,
                    spec.HavingClause,
                    spec.OrderByList,
                    expressionCopier);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            if (isSubquery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Invalid nested subquery, subquery-within-subquery is not supported",
                    compilable.ToEPL());
            }

            if (isOnDemandQuery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Subqueries are not a supported feature of on-demand queries",
                    compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                if (!subselectNodes.Contains(subselectNode)) {
                    subselectNodes.Add(subselectNode);
                }
            }

            // Compile subselects found
            var subselectNumber = 0;
            foreach (var subselect in subselectNodes) {
                StatementSpecRaw raw = subselect.StatementSpecRaw;
                var compiled = Compile(
                    raw,
                    compilable,
                    true,
                    isOnDemandQuery,
                    annotations,
                    Collections.GetEmptyList<ExprSubselectNode>(),
                    Collections.GetEmptyList<ExprTableAccessNode>(),
                    statementRawInfo,
                    compileTimeServices);
                subselect.SetStatementSpecCompiled(compiled, subselectNumber);
                subselectNumber++;
            }

            // Set table-access number
            var tableAccessNumber = 0;
            foreach (var tableAccess in tableAccessNodes) {
                tableAccess.TableAccessNumber = tableAccessNumber;
                tableAccessNumber++;
            }

            // compile each stream used
            try {
                compiledStreams = new List<StreamSpecCompiled>(spec.StreamSpecs.Count);
                var streamNum = 0;
                foreach (var rawSpec in spec.StreamSpecs) {
                    streamNum++;
                    var compiled = StreamSpecCompiler.Compile(
                        rawSpec,
                        eventTypeReferences,
                        spec.InsertIntoDesc != null,
                        spec.StreamSpecs.Count > 1,
                        false,
                        spec.OnTriggerDesc != null,
                        rawSpec.OptionalStreamName,
                        streamNum,
                        statementRawInfo,
                        compileTimeServices);
                    compiledStreams.Add(compiled);
                }
            }
            catch (ExprValidationException ex) {
                if (ex.Message == null) {
                    throw new StatementSpecCompileException(
                        "Unexpected exception compiling statement, please consult the log file and report the exception",
                        ex,
                        compilable.ToEPL());
                }

                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (EPException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (Exception ex) {
                var text = "Unexpected error compiling statement";
                Log.Error(text, ex);
                throw new StatementSpecCompileException(
                    text + ": " + ex.GetType().Name + ":" + ex.Message,
                    ex,
                    compilable.ToEPL());
            }

            return new StatementSpecCompiled(
                spec,
                compiledStreams.ToArray(),
                selectClauseCompiled,
                annotations,
                groupByRollupExpressions,
                subselectNodes,
                visitor.DeclaredExpressions,
                tableAccessNodes);
        }
        internal static FilterSpecParamForge HandleEqualsAndRelOp(
            ExprNode constituent,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            FilterOperator op;
            if (constituent is ExprEqualsNode) {
                var equalsNode = (ExprEqualsNode) constituent;
                if (!equalsNode.IsIs) {
                    op = FilterOperator.EQUAL;
                    if (equalsNode.IsNotEquals) {
                        op = FilterOperator.NOT_EQUAL;
                    }
                }
                else {
                    op = FilterOperator.IS;
                    if (equalsNode.IsNotEquals) {
                        op = FilterOperator.IS_NOT;
                    }
                }
            }
            else {
                var relNode = (ExprRelationalOpNode) constituent;
                if (relNode.RelationalOpEnum == RelationalOpEnum.GT) {
                    op = FilterOperator.GREATER;
                }
                else if (relNode.RelationalOpEnum == RelationalOpEnum.LT) {
                    op = FilterOperator.LESS;
                }
                else if (relNode.RelationalOpEnum == RelationalOpEnum.LE) {
                    op = FilterOperator.LESS_OR_EQUAL;
                }
                else if (relNode.RelationalOpEnum == RelationalOpEnum.GE) {
                    op = FilterOperator.GREATER_OR_EQUAL;
                }
                else {
                    throw new IllegalStateException("Opertor '" + relNode.RelationalOpEnum + "' not mapped");
                }
            }

            var left = constituent.ChildNodes[0];
            var right = constituent.ChildNodes[1];

            // check identifier and constant combination
            if (right.Forge.ForgeConstantType.IsCompileTimeConstant && left is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) left;
                if (filterOptimizableNode.FilterLookupEligible) {
                    var lookupableX = filterOptimizableNode.FilterLookupable;
                    var constant = right.Forge.ExprEvaluator.Evaluate(null, true, null);
                    constant = HandleConstantsCoercion(lookupableX, constant);
                    return new FilterSpecParamConstantForge(lookupableX, op, constant);
                }
            }

            if (left.Forge.ForgeConstantType.IsCompileTimeConstant && right is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) right;
                if (filterOptimizableNode.FilterLookupEligible) {
                    var lookupableX = filterOptimizableNode.FilterLookupable;
                    var constant = left.Forge.ExprEvaluator.Evaluate(null, true, null);
                    constant = HandleConstantsCoercion(lookupableX, constant);
                    var opReversed = op.IsComparisonOperator() ? op.ReversedRelationalOp() : op;
                    return new FilterSpecParamConstantForge(lookupableX, opReversed, constant);
                }
            }

            // check identifier and expression containing other streams
            if (left is ExprIdentNode && right is ExprIdentNode) {
                var identNodeLeft = (ExprIdentNode) left;
                var identNodeRight = (ExprIdentNode) right;

                if (identNodeLeft.StreamId == 0 && identNodeLeft.FilterLookupEligible && identNodeRight.StreamId != 0) {
                    return HandleProperty(op, identNodeLeft, identNodeRight, arrayEventTypes, statementName);
                }

                if (identNodeRight.StreamId == 0 && identNodeRight.FilterLookupEligible && identNodeLeft.StreamId != 0) {
                    op = GetReversedOperator(constituent, op); // reverse operators, as the expression is "stream1.prop xyz stream0.prop"
                    return HandleProperty(op, identNodeRight, identNodeLeft, arrayEventTypes, statementName);
                }
            }

            if (left is ExprFilterOptimizableNode && right is ExprContextPropertyNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) left;
                var ctxNode = (ExprContextPropertyNode) right;
                var lookupableX = filterOptimizableNode.FilterLookupable;
                if (filterOptimizableNode.FilterLookupEligible) {
                    var numberCoercer = GetNumberCoercer(lookupableX.ReturnType, ctxNode.Type, lookupableX.Expression);
                    return new FilterSpecParamContextPropForge(lookupableX, op, ctxNode.PropertyName, ctxNode.Getter, numberCoercer);
                }
            }

            if (left is ExprContextPropertyNode && right is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) right;
                var ctxNode = (ExprContextPropertyNode) left;
                var lookupableX = filterOptimizableNode.FilterLookupable;
                if (filterOptimizableNode.FilterLookupEligible) {
                    op = GetReversedOperator(constituent, op); // reverse operators, as the expression is "stream1.prop xyz stream0.prop"
                    var numberCoercer = GetNumberCoercer(lookupableX.ReturnType, ctxNode.Type, lookupableX.Expression);
                    return new FilterSpecParamContextPropForge(lookupableX, op, ctxNode.PropertyName, ctxNode.Getter, numberCoercer);
                }
            }

            if (left is ExprFilterOptimizableNode && right.Forge.ForgeConstantType.IsDeployTimeTimeConstant && right is ExprNodeDeployTimeConst) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) left;
                var deployTimeConst = (ExprNodeDeployTimeConst) right;
                var lookupableX = filterOptimizableNode.FilterLookupable;
                if (filterOptimizableNode.FilterLookupEligible) {
                    var returnType = right.Forge.EvaluationType;
                    var numberCoercer = GetNumberCoercer(lookupableX.ReturnType, returnType, lookupableX.Expression);
                    return new FilterSpecParamDeployTimeConstParamForge(lookupableX, op, deployTimeConst, returnType, numberCoercer);
                }
            }

            if (left.Forge.ForgeConstantType.IsDeployTimeTimeConstant && left is ExprNodeDeployTimeConst && right is ExprFilterOptimizableNode) {
                var filterOptimizableNode = (ExprFilterOptimizableNode) right;
                var deployTimeConst = (ExprNodeDeployTimeConst) left;
                var lookupableX = filterOptimizableNode.FilterLookupable;
                if (filterOptimizableNode.FilterLookupEligible) {
                    var returnType = left.Forge.EvaluationType;
                    op = GetReversedOperator(constituent, op); // reverse operators, as the expression is "stream1.prop xyz stream0.prop"
                    var numberCoercer = GetNumberCoercer(lookupableX.ReturnType, returnType, lookupableX.Expression);
                    return new FilterSpecParamDeployTimeConstParamForge(lookupableX, op, deployTimeConst, returnType, numberCoercer);
                }
            }

            // check lookable-limited and value-limited expression
            ExprNode lookupable = null;
            ExprNode value = null;
            var opWReverse = op;
            if (IsLimitedLookupableExpression(left) && IsLimitedValueExpression(right)) {
                lookupable = left;
                value = right;
            }
            else if (IsLimitedLookupableExpression(right) && IsLimitedValueExpression(left)) {
                lookupable = right;
                value = left;
                opWReverse = GetReversedOperator(constituent, op);
            }

            if (lookupable != null) {
                return HandleLimitedExpr(opWReverse, lookupable, value, taggedEventTypes, arrayEventTypes, allTagNamesOrdered, raw, services);
            }

            return null;
        }
Beispiel #23
0
        internal static FilterSpecParamForge HandleInSetNode(
            ExprInNode constituent,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            ISet <string> allTagNamesOrdered,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            var left = constituent.ChildNodes[0];
            ExprFilterSpecLookupableForge lookupable = null;

            if (left is ExprFilterOptimizableNode)
            {
                var filterOptimizableNode = (ExprFilterOptimizableNode)left;
                lookupable = filterOptimizableNode.FilterLookupable;
            }
            else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) &&
                     IsLimitedLookupableExpression(left))
            {
                lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services);
            }

            if (lookupable == null)
            {
                return(null);
            }

            var op = FilterOperator.IN_LIST_OF_VALUES;

            if (constituent.IsNotIn)
            {
                op = FilterOperator.NOT_IN_LIST_OF_VALUES;
            }

            var expectedNumberOfConstants = constituent.ChildNodes.Length - 1;
            IList <FilterSpecParamInValueForge> listofValues = new List <FilterSpecParamInValueForge>();
            var it = Arrays.AsList(constituent.ChildNodes).GetEnumerator();

            it.MoveNext();             // ignore the first node as it's the identifier
            while (it.MoveNext())
            {
                var subNode = it.Current;
                if (subNode.Forge.ForgeConstantType.IsCompileTimeConstant)
                {
                    var constant = subNode.Forge.ExprEvaluator.Evaluate(null, true, null);
                    if (constant is ICollection <object> )
                    {
                        return(null);
                    }

                    if (constant is IDictionary <object, object> )
                    {
                        return(null);
                    }

                    if ((constant != null) && (constant is Array arrayConstant))
                    {
                        for (var i = 0; i < arrayConstant.Length; i++)
                        {
                            var arrayElement        = arrayConstant.GetValue(i);
                            var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement);
                            listofValues.Add(new FilterForEvalConstantAnyTypeForge(arrayElementCoerced));
                            if (i > 0)
                            {
                                expectedNumberOfConstants++;
                            }
                        }
                    }
                    else
                    {
                        constant = HandleConstantsCoercion(lookupable, constant);
                        listofValues.Add(new FilterForEvalConstantAnyTypeForge(constant));
                    }
                }
                else if (subNode is ExprContextPropertyNode)
                {
                    var     contextPropertyNode = (ExprContextPropertyNode)subNode;
                    var     returnType          = contextPropertyNode.Type;
                    Coercer coercer;
                    if (TypeHelper.IsCollectionMapOrArray(returnType))
                    {
                        CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression);
                        coercer = null;
                    }
                    else
                    {
                        coercer = GetNumberCoercer(left.Forge.EvaluationType, contextPropertyNode.Type, lookupable.Expression);
                    }

                    var finalReturnType = coercer != null ? coercer.ReturnType : returnType;
                    listofValues.Add(new FilterForEvalContextPropForge(contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType));
                }
                else if (subNode.Forge.ForgeConstantType.IsDeployTimeTimeConstant && subNode is ExprNodeDeployTimeConst)
                {
                    var     deployTimeConst = (ExprNodeDeployTimeConst)subNode;
                    var     returnType      = subNode.Forge.EvaluationType;
                    Coercer coercer;
                    if (TypeHelper.IsCollectionMapOrArray(returnType))
                    {
                        CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression);
                        coercer = null;
                    }
                    else
                    {
                        coercer = GetNumberCoercer(left.Forge.EvaluationType, returnType, lookupable.Expression);
                    }

                    listofValues.Add(new FilterForEvalDeployTimeConstForge(deployTimeConst, coercer, returnType));
                }
                else if (subNode is ExprIdentNode)
                {
                    var identNodeInner = (ExprIdentNode)subNode;
                    if (identNodeInner.StreamId == 0)
                    {
                        break;                         // for same event evals use the boolean expression, via count compare failing below
                    }

                    var isMustCoerce    = false;
                    var coerceToType    = Boxing.GetBoxedType(lookupable.ReturnType);
                    var identReturnType = identNodeInner.Forge.EvaluationType;

                    if (TypeHelper.IsCollectionMapOrArray(identReturnType))
                    {
                        CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression);
                        coerceToType = identReturnType;
                        // no action
                    }
                    else if (identReturnType != lookupable.ReturnType)
                    {
                        if (TypeHelper.IsNumeric(lookupable.ReturnType))
                        {
                            if (!TypeHelper.CanCoerce(identReturnType, lookupable.ReturnType))
                            {
                                ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression);
                            }

                            isMustCoerce = true;
                        }
                        else
                        {
                            break;                             // assumed not compatible
                        }
                    }

                    FilterSpecParamInValueForge inValue;
                    var streamName = identNodeInner.ResolvedStreamName;
                    if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName))
                    {
                        var indexAndProp   = GetStreamIndex(identNodeInner.ResolvedPropertyName);
                        var innerEventType = GetArrayInnerEventType(arrayEventTypes, streamName);
                        inValue = new FilterForEvalEventPropIndexedForge(
                            identNodeInner.ResolvedStreamName,
                            indexAndProp.First,
                            indexAndProp.Second,
                            innerEventType,
                            isMustCoerce,
                            coerceToType);
                    }
                    else
                    {
                        inValue = new FilterForEvalEventPropForge(
                            identNodeInner.ResolvedStreamName,
                            identNodeInner.ResolvedPropertyName,
                            identNodeInner.ExprEvaluatorIdent,
                            isMustCoerce,
                            coerceToType);
                    }

                    listofValues.Add(inValue);
                }
                else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                         IsLimitedValueExpression(subNode))
                {
                    var convertor      = GetMatchEventConvertor(subNode, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                    var valueType      = subNode.Forge.EvaluationType;
                    var lookupableType = lookupable.ReturnType;
                    var numberCoercer  = GetNumberCoercer(lookupableType, valueType, lookupable.Expression);
                    var forge          = new FilterForEvalLimitedExprForge(subNode, convertor, numberCoercer);
                    listofValues.Add(forge);
                }
            }

            // Fallback if not all values in the in-node can be resolved to properties or constants
            if (listofValues.Count == expectedNumberOfConstants)
            {
                return(new FilterSpecParamInForge(lookupable, op, listofValues));
            }

            return(null);
        }
Beispiel #24
0
        public static StreamSpecCompiled CompileFilter(
            FilterStreamSpecRaw streamSpec,
            bool isInsertInto,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            string optionalStreamName,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            // Determine the event type
            var rawFilterSpec = streamSpec.RawFilterSpec;
            var eventTypeName = rawFilterSpec.EventTypeName;

            var table = services.TableCompileTimeResolver.Resolve(eventTypeName);
            if (table != null) {
                if (streamSpec.ViewSpecs != null && streamSpec.ViewSpecs.Length > 0) {
                    throw new ExprValidationException("Views are not supported with tables");
                }

                if (streamSpec.RawFilterSpec.OptionalPropertyEvalSpec != null) {
                    throw new ExprValidationException("Contained-event expressions are not supported with tables");
                }

                StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                    new[] {table.InternalEventType},
                    new[] {optionalStreamName},
                    new[] {true},
                    false,
                    false);
                var validatedNodes = FilterSpecCompiler.ValidateAllowSubquery(
                    ExprNodeOrigin.FILTER,
                    rawFilterSpec.FilterExpressions,
                    streamTypeService,
                    null,
                    null,
                    statementRawInfo,
                    services);
                return new TableQueryStreamSpec(
                    streamSpec.OptionalStreamName,
                    streamSpec.ViewSpecs,
                    streamSpec.Options,
                    table,
                    validatedNodes);
            }

            // Could be a named window
            var namedWindowInfo = services.NamedWindowCompileTimeResolver.Resolve(eventTypeName);
            if (namedWindowInfo != null) {
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                    new[] {namedWindowInfo.EventType},
                    new[] {optionalStreamName},
                    new[] {true},
                    false,
                    false);

                var validatedNodes = FilterSpecCompiler.ValidateAllowSubquery(
                    ExprNodeOrigin.FILTER,
                    rawFilterSpec.FilterExpressions,
                    streamTypeService,
                    null,
                    null,
                    statementRawInfo,
                    services);

                PropertyEvaluatorForge optionalPropertyEvaluator = null;
                if (rawFilterSpec.OptionalPropertyEvalSpec != null) {
                    optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                        rawFilterSpec.OptionalPropertyEvalSpec,
                        namedWindowInfo.EventType,
                        streamSpec.OptionalStreamName,
                        statementRawInfo,
                        services);
                }

                return new NamedWindowConsumerStreamSpec(
                    namedWindowInfo,
                    streamSpec.OptionalStreamName,
                    streamSpec.ViewSpecs,
                    validatedNodes,
                    streamSpec.Options,
                    optionalPropertyEvaluator);
            }

            var eventType = ResolveTypeName(eventTypeName, services.EventTypeCompileTimeResolver);

            // Validate all nodes, make sure each returns a boolean and types are good;
            // Also decompose all AND super nodes into individual expressions
            StreamTypeService streamTypeServiceX = new StreamTypeServiceImpl(
                new[] {eventType},
                new[] {streamSpec.OptionalStreamName},
                new[] {true},
                false,
                false);

            var spec = FilterSpecCompiler.MakeFilterSpec(
                eventType,
                eventTypeName,
                rawFilterSpec.FilterExpressions,
                rawFilterSpec.OptionalPropertyEvalSpec,
                null,
                null, // no tags
                streamTypeServiceX,
                streamSpec.OptionalStreamName,
                statementRawInfo,
                services);

            return new FilterStreamSpecCompiled(
                spec,
                streamSpec.ViewSpecs,
                streamSpec.OptionalStreamName,
                streamSpec.Options);
        }
        /// <summary>
        /// For a given expression determine if this is optimizable and create the filter parameter
        /// representing the expression, or null if not optimizable.
        /// </summary>
        /// <param name="constituent">is the expression to look at</param>
        /// <param name="performConditionPlanning"></param>
        /// <param name="taggedEventTypes">event types that provide non-array values</param>
        /// <param name="arrayEventTypes">event types that provide array values</param>
        /// <param name="statementName">statement name</param>
        /// <param name="streamTypeService">stream type service</param>
        /// <returns>filter parameter representing the expression, or null</returns>
        /// <throws>ExprValidationException if the expression is invalid</throws>
        internal static FilterSpecPlanPathTripletForge MakeFilterParam(
            ExprNode constituent,
            bool performConditionPlanning,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            ISet <string> allTagNamesOrdered,
            string statementName,
            StreamTypeService streamTypeService,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // Is this expression node a simple compare, i.e. a=5 or b<4; these can be indexed
            if ((constituent is ExprEqualsNode) || (constituent is ExprRelationalOpNode))
            {
                FilterSpecParamForge param = HandleEqualsAndRelOp(
                    constituent,
                    taggedEventTypes,
                    arrayEventTypes,
                    allTagNamesOrdered,
                    statementName,
                    raw,
                    services);
                if (param != null)
                {
                    return(new FilterSpecPlanPathTripletForge(param, null));
                }
            }

            constituent = RewriteOrToInIfApplicable(constituent, false);

            // Is this expression node a simple compare, i.e. a=5 or b<4; these can be indexed
            if (constituent is ExprInNode)
            {
                FilterSpecParamForge param = HandleInSetNode((ExprInNode)constituent, taggedEventTypes, arrayEventTypes, allTagNamesOrdered, raw, services);
                if (param != null)
                {
                    return(new FilterSpecPlanPathTripletForge(param, null));
                }
            }

            if (constituent is ExprBetweenNode)
            {
                FilterSpecParamForge param = HandleRangeNode(
                    (ExprBetweenNode)constituent,
                    taggedEventTypes,
                    arrayEventTypes,
                    allTagNamesOrdered,
                    statementName,
                    raw,
                    services);
                if (param != null)
                {
                    return(new FilterSpecPlanPathTripletForge(param, null));
                }
            }

            if (constituent is ExprPlugInSingleRowNode)
            {
                FilterSpecParamForge param = HandlePlugInSingleRow((ExprPlugInSingleRowNode)constituent);
                if (param != null)
                {
                    return(new FilterSpecPlanPathTripletForge(param, null));
                }
            }

            if (constituent is FilterSpecCompilerAdvIndexDescProvider)
            {
                FilterSpecParamForge param = HandleAdvancedIndexDescProvider(
                    (FilterSpecCompilerAdvIndexDescProvider)constituent,
                    arrayEventTypes,
                    statementName);
                if (param != null)
                {
                    return(new FilterSpecPlanPathTripletForge(param, null));
                }
            }

            if (constituent is ExprOrNode && performConditionPlanning)
            {
                return(HandleOrAlternateExpression(
                           (ExprOrNode)constituent,
                           performConditionPlanning,
                           taggedEventTypes,
                           arrayEventTypes,
                           allTagNamesOrdered,
                           statementName,
                           streamTypeService,
                           raw,
                           services));
            }

            FilterSpecParamForge paramX = HandleBooleanLimited(
                constituent,
                taggedEventTypes,
                arrayEventTypes,
                allTagNamesOrdered,
                streamTypeService,
                raw,
                services);

            if (paramX != null)
            {
                return(new FilterSpecPlanPathTripletForge(paramX, null));
            }

            return(null);
        }
        private static FilterSpecParamFilterForEvalForge HandleRangeNodeEndpoint(
            ExprNode endpoint,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // constant
            if (endpoint.Forge.ForgeConstantType.IsCompileTimeConstant) {
                var value = endpoint.Forge.ExprEvaluator.Evaluate(null, true, null);
                if (value == null) {
                    return null;
                }

                if (value is string) {
                    return new FilterForEvalConstantStringForge((string) value);
                }

                return new FilterForEvalConstantDoubleForge(value.AsDouble());
            }

            if (endpoint is ExprContextPropertyNode) {
                var node = (ExprContextPropertyNode) endpoint;
                if (node.Type == typeof(string)) {
                    return new FilterForEvalContextPropStringForge(node.Getter, node.PropertyName);
                }

                return new FilterForEvalContextPropDoubleForge(node.Getter, node.PropertyName);
            }

            if (endpoint.Forge.ForgeConstantType.IsDeployTimeTimeConstant && endpoint is ExprNodeDeployTimeConst) {
                var node = (ExprNodeDeployTimeConst) endpoint;
                if (endpoint.Forge.EvaluationType == typeof(string)) {
                    return new FilterForEvalDeployTimeConstStringForge(node);
                }

                return new FilterForEvalDeployTimeConstDoubleForge(node);
            }

            // or property
            if (endpoint is ExprIdentNode) {
                return GetIdentNodeDoubleEval((ExprIdentNode) endpoint, arrayEventTypes, statementName);
            }

            // or limited expression
            if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                IsLimitedValueExpression(endpoint)) {
                var returnType = endpoint.Forge.EvaluationType;
                MatchedEventConvertorForge convertor = GetMatchEventConvertor(endpoint, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                if (returnType == typeof(string)) {
                    return new FilterForEvalLimitedExprForge(endpoint, convertor, null);
                }

                var coercer = SimpleNumberCoercerFactory.GetCoercer(returnType, typeof(double?));
                return new FilterForEvalLimitedExprForge(endpoint, convertor, coercer);
            }

            return null;
        }
Beispiel #27
0
        public static StreamSpecCompiledDesc CompilePatternWTags(
            PatternStreamSpecRaw streamSpecRaw,
            ISet<string> eventTypeReferences,
            bool isInsertInto,
            MatchEventSpec tags,
            ISet<string> priorAllTags,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            int streamNum,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            // validate
            if ((streamSpecRaw.IsSuppressSameEventMatches || streamSpecRaw.IsDiscardPartialsOnMatch) &&
                (isJoin || isContextDeclaration || isOnTrigger)) {
                throw new ExprValidationException(
                    "Discard-partials and suppress-matches is not supported in a joins, context declaration and on-action");
            }

            if (tags == null) {
                tags = new MatchEventSpec();
            }

            var nodeStack = new Stack<EvalForgeNode>();

            // determine ordered tags
            ISet<string> allTagNamesOrdered = FilterSpecCompilerTagUtil.AssignEventAsTagNumber(priorAllTags, streamSpecRaw.EvalForgeNode);

            // construct root : assigns factory node ids
            var top = streamSpecRaw.EvalForgeNode;
            var root = new EvalRootForgeNode(services.IsAttachPatternText, top, statementRawInfo.Annotations);
            var additionalForgeables = new List<StmtClassForgeableFactory>();
            
            RecursiveCompile(
                top,
                tags,
                nodeStack,
                allTagNamesOrdered,
                streamNum,
                additionalForgeables,
                statementRawInfo,
                services);

            var hook = (PatternCompileHook) ImportUtil.GetAnnotationHook(
                statementRawInfo.Annotations,
                HookType.INTERNAL_PATTERNCOMPILE,
                typeof(PatternCompileHook),
                services.ImportServiceCompileTime);
            hook?.Pattern(root);

            PatternStreamSpecCompiled compiled = new PatternStreamSpecCompiled(
                root,
                tags.TaggedEventTypes,
                tags.ArrayEventTypes,
                allTagNamesOrdered,
                streamSpecRaw.ViewSpecs,
                streamSpecRaw.OptionalStreamName,
                streamSpecRaw.Options,
                streamSpecRaw.IsSuppressSameEventMatches,
                streamSpecRaw.IsDiscardPartialsOnMatch);

            return new StreamSpecCompiledDesc(compiled, additionalForgeables);
        }