Ejemplo n.º 1
0
        internal ExprValidationContext(
            StreamTypeService streamTypeService,
            ViewResourceDelegateExpr viewResourceDelegate,
            ContextCompileTimeDescriptor contextDescriptor,
            bool disablePropertyExpressionEventCollCache,
            bool allowRollupFunctions,
            bool allowBindingConsumption,
            bool allowTableAggReset,
            bool isUnidirectionalJoin,
            string intoTableName,
            bool isFilterExpression,
            ExprValidationMemberName memberName,
            bool aggregationFutureNameAlreadySet,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            StreamTypeService = streamTypeService;
            ViewResourceDelegate = viewResourceDelegate;
            this.contextDescriptor = contextDescriptor;
            IsDisablePropertyExpressionEventCollCache = disablePropertyExpressionEventCollCache;
            IsAllowRollupFunctions = allowRollupFunctions;
            IsAllowBindingConsumption = allowBindingConsumption;
            IsAllowTableAggReset = allowTableAggReset;
            IsResettingAggregations = isUnidirectionalJoin;
            this.intoTableName = intoTableName;
            IsFilterExpression = isFilterExpression;
            MemberNames = memberName;
            IsAggregationFutureNameAlreadySet = aggregationFutureNameAlreadySet;
            StatementRawInfo = statementRawInfo;
            StatementCompileTimeService = compileTimeServices;

            IsExpressionAudit = AuditEnum.EXPRESSION.GetAudit(statementRawInfo.Annotations) != null;
            IsExpressionNestedAudit = AuditEnum.EXPRESSION_NESTED.GetAudit(statementRawInfo.Annotations) != null;
        }
Ejemplo n.º 2
0
        public static IList <StmtClassForgeableFactory> HandleSubselectSelectClauses(
            ExprSubselectNode subselect,
            EventType outerEventType,
            string outerEventTypeName,
            string outerStreamName,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (subselect.SubselectNumber == -1)
            {
                throw new IllegalStateException("Subselect is unassigned");
            }

            var statementSpec    = subselect.StatementSpecCompiled;
            var filterStreamSpec = statementSpec.StreamSpecs[0];

            IList <ViewFactoryForge> viewForges;
            string subselecteventTypeName;
            IList <StmtClassForgeableFactory> additionalForgeables;

            // construct view factory chain
            EventType eventType;

            try {
                var args = new ViewFactoryForgeArgs(
                    -1,
                    true,
                    subselect.SubselectNumber,
                    StreamSpecOptions.DEFAULT,
                    null,
                    statementRawInfo,
                    services);
                var streamSpec = statementSpec.StreamSpecs[0];

                if (streamSpec is FilterStreamSpecCompiled)
                {
                    var filterStreamSpecCompiled = (FilterStreamSpecCompiled)statementSpec.StreamSpecs[0];
                    subselecteventTypeName = filterStreamSpecCompiled.FilterSpecCompiled.FilterForEventTypeName;

                    // A child view is required to limit the stream
                    if (filterStreamSpec.ViewSpecs.Length == 0)
                    {
                        throw new ExprValidationException(
                                  "Subqueries require one or more views to limit the stream, consider declaring a length or time window");
                    }

                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(
                        filterStreamSpecCompiled.ViewSpecs,
                        args,
                        filterStreamSpecCompiled.FilterSpecCompiled.ResultEventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    // Register filter, create view factories
                    eventType = viewForges.IsEmpty() ? filterStreamSpecCompiled.FilterSpecCompiled.ResultEventType : viewForges[viewForges.Count - 1].EventType;
                    subselect.RawEventType = eventType;
                }
                else if (streamSpec is NamedWindowConsumerStreamSpec)
                {
                    var namedSpec   = (NamedWindowConsumerStreamSpec)statementSpec.StreamSpecs[0];
                    var namedWindow = namedSpec.NamedWindow;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(namedSpec.ViewSpecs, args, namedWindow.EventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    var namedWindowName = namedWindow.EventType.Name;
                    subselecteventTypeName = namedWindowName;
                    EPLValidationUtil.ValidateContextName(false, namedWindowName, namedWindow.ContextName, statementRawInfo.ContextName, true);
                    subselect.RawEventType = namedWindow.EventType;
                    eventType = namedWindow.EventType;
                }
                else if (streamSpec is TableQueryStreamSpec)
                {
                    var namedSpec = (TableQueryStreamSpec)statementSpec.StreamSpecs[0];
                    var table     = namedSpec.Table;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(namedSpec.ViewSpecs, args, table.InternalEventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    var namedWindowName = table.TableName;
                    subselecteventTypeName = namedWindowName;
                    EPLValidationUtil.ValidateContextName(false, namedWindowName, table.OptionalContextName, statementRawInfo.ContextName, true);
                    subselect.RawEventType = table.InternalEventType;
                    eventType = table.InternalEventType;
                }
                else
                {
                    throw new IllegalStateException("Unexpected stream spec " + streamSpec);
                }
            }
            catch (ViewProcessingException ex) {
                throw new ExprValidationException("Failed to validate subexpression: " + ex.Message, ex);
            }

            // determine a stream name unless one was supplied
            var subexpressionStreamName = SubselectUtil.GetStreamName(filterStreamSpec.OptionalStreamName, subselect.SubselectNumber);

            // Named windows don't allow data views
            if (filterStreamSpec is NamedWindowConsumerStreamSpec | filterStreamSpec is TableQueryStreamSpec)
            {
                EPStatementStartMethodHelperValidate.ValidateNoDataWindowOnNamedWindow(viewForges);
            }

            // Streams event types are the original stream types with the stream zero the subselect stream
            var namesAndTypes = new LinkedHashMap <string, Pair <EventType, string> >();

            namesAndTypes.Put(subexpressionStreamName, new Pair <EventType, string>(eventType, subselecteventTypeName));
            namesAndTypes.Put(outerStreamName, new Pair <EventType, string>(outerEventType, outerEventTypeName));
            if (taggedEventTypes != null)
            {
                foreach (var entry in taggedEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }

            if (arrayEventTypes != null)
            {
                foreach (var entry in arrayEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }

            StreamTypeService subselectTypeService = new StreamTypeServiceImpl(namesAndTypes, true, true);
            var viewResourceDelegateSubselect      = new ViewResourceDelegateExpr();

            subselect.FilterSubqueryStreamTypes = subselectTypeService;

            // Validate select expression
            var selectClauseSpec = subselect.StatementSpecCompiled.SelectClauseCompiled;

            if (selectClauseSpec.SelectExprList.Length > 0)
            {
                if (selectClauseSpec.SelectExprList.Length > 1)
                {
                    throw new ExprValidationException("Subquery multi-column select is not allowed in this context.");
                }

                var element = selectClauseSpec.SelectExprList[0];
                if (element is SelectClauseExprCompiledSpec)
                {
                    // validate
                    var compiled          = (SelectClauseExprCompiledSpec)element;
                    var selectExpression  = compiled.SelectExpression;
                    var validationContext = new ExprValidationContextBuilder(subselectTypeService, statementRawInfo, services)
                                            .WithViewResourceDelegate(viewResourceDelegateSubselect)
                                            .WithAllowBindingConsumption(true)
                                            .WithMemberName(new ExprValidationMemberNameQualifiedSubquery(subselect.SubselectNumber))
                                            .Build();
                    selectExpression        = ExprNodeUtilityValidate.GetValidatedSubtree(ExprNodeOrigin.SUBQUERYSELECT, selectExpression, validationContext);
                    subselect.SelectClause  = new ExprNode[] { selectExpression };
                    subselect.SelectAsNames = new string[] { compiled.AssignedName };

                    // handle aggregation
                    var aggExprNodes = new List <ExprAggregateNode>();
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(selectExpression, aggExprNodes);
                    if (aggExprNodes.Count > 0)
                    {
                        // Other stream properties, if there is aggregation, cannot be under aggregation.
                        foreach (var aggNode in aggExprNodes)
                        {
                            var propertiesNodesAggregated = ExprNodeUtilityQuery.GetExpressionProperties(aggNode, true);
                            foreach (var pair in propertiesNodesAggregated)
                            {
                                if (pair.First != 0)
                                {
                                    throw new ExprValidationException("Subselect aggregation function cannot aggregate across correlated properties");
                                }
                            }
                        }

                        // This stream (stream 0) properties must either all be under aggregation, or all not be.
                        var propertiesNotAggregated = ExprNodeUtilityQuery.GetExpressionProperties(selectExpression, false);
                        foreach (var pair in propertiesNotAggregated)
                        {
                            if (pair.First == 0)
                            {
                                throw new ExprValidationException("Subselect properties must all be within aggregation functions");
                            }
                        }
                    }
                }
            }

            return(additionalForgeables);
        }
Ejemplo n.º 3
0
        public static ViewResourceDelegateDesc[] VerifyPreviousAndPriorRequirements(
            IList<ViewFactoryForge>[] unmaterializedViewChain,
            ViewResourceDelegateExpr @delegate)
        {
            var numStreams = unmaterializedViewChain.Length;
            var perStream = new ViewResourceDelegateDesc[numStreams];

            // verify "previous"
            var previousPerStream = new bool[numStreams];
            foreach (ExprPreviousNode previousNode in @delegate.PreviousRequests) {
                var stream = previousNode.StreamNumber;
                var forges = unmaterializedViewChain[stream];

                var pass = InspectViewFactoriesForPrevious(forges);
                if (!pass) {
                    throw new ExprValidationException(
                        "Previous function requires a single data window view onto the stream");
                }

                var found = FindDataWindow(forges);
                if (!found) {
                    throw new ExprValidationException(
                        "Required data window not found for the 'prev' function, specify a data window for which previous events are retained");
                }

                previousPerStream[stream] = true;
            }

            // determine 'prior' indexes
            var priorPerStream = new IOrderedDictionary<int, IList<ExprPriorNode>>[numStreams];
            foreach (var priorNode in @delegate.PriorRequests) {
                var stream = priorNode.StreamNumber;

                if (priorPerStream[stream] == null) {
                    priorPerStream[stream] = new OrderedListDictionary<int, IList<ExprPriorNode>>();
                }

                var treemap = priorPerStream[stream];
                var callbackList = treemap.Get(priorNode.ConstantIndexNumber);
                if (callbackList == null) {
                    callbackList = new List<ExprPriorNode>();
                    treemap.Put(priorNode.ConstantIndexNumber, callbackList);
                }

                callbackList.Add(priorNode);
            }

            // when a given stream has multiple 'prior' nodes, assign a relative index
            for (var i = 0; i < numStreams; i++) {
                if (priorPerStream[i] != null) {
                    var relativeIndex = 0;
                    foreach (var entry in priorPerStream[i]) {
                        foreach (var node in entry.Value) {
                            node.RelativeIndex = relativeIndex;
                        }

                        relativeIndex++;
                    }
                }
            }

            // build per-stream info
            for (var i = 0; i < numStreams; i++) {
                if (priorPerStream[i] == null) {
                    priorPerStream[i] = new OrderedListDictionary<int, IList<ExprPriorNode>>();
                }

                perStream[i] = new ViewResourceDelegateDesc(
                    previousPerStream[i],
                    new SortedSet<int>(priorPerStream[i].Keys));
            }

            return perStream;
        }
Ejemplo n.º 4
0
        public static StmtForgeMethodSelectResult Make(
            IContainer container,
            bool dataflowOperator,
            string @namespace,
            string classPostfix,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            var filterSpecCompileds = new List<FilterSpecCompiled>();
            var scheduleHandleCallbackProviders = new List<ScheduleHandleCallbackProvider>();
            var namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
            var statementSpec = @base.StatementSpec;
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            var streamNames = StatementForgeMethodSelectUtil.DetermineStreamNames(statementSpec.StreamSpecs);
            var numStreams = streamNames.Length;
            if (numStreams == 0) {
                throw new ExprValidationException("The from-clause is required but has not been specified");
            }

            // first we create streams for subselects, if there are any
            SubSelectActivationDesc subSelectActivationDesc = SubSelectHelperActivations.CreateSubSelectActivation(
                filterSpecCompileds, namedWindowConsumers, @base, services);
            IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation = subSelectActivationDesc.Subselects;
            additionalForgeables.AddAll(subSelectActivationDesc.AdditionalForgeables);

            // verify for joins that required views are present
            StreamJoinAnalysisResultCompileTime joinAnalysisResult = StatementForgeMethodSelectUtil.VerifyJoinViews(statementSpec);

            var streamEventTypes = new EventType[statementSpec.StreamSpecs.Length];
            var eventTypeNames = new string[numStreams];
            var isNamedWindow = new bool[numStreams];
            var viewableActivatorForges = new ViewableActivatorForge[numStreams];
            var viewForges = new IList<ViewFactoryForge>[numStreams];
            var historicalEventViewables = new HistoricalEventViewableForge[numStreams];

            for (var stream = 0; stream < numStreams; stream++) {
                var streamSpec = statementSpec.StreamSpecs[stream];
                var isCanIterateUnbound = streamSpec.ViewSpecs.Length == 0 &&
                                          (services.Configuration.Compiler.ViewResources.IsIterableUnbound ||
                                           AnnotationUtil.HasAnnotation(statementSpec.Annotations, typeof(IterableUnboundAttribute)));

                var args = new ViewFactoryForgeArgs(
                    stream,
                    false,
                    -1,
                    streamSpec.Options,
                    null,
                    @base.StatementRawInfo,
                    services);

                if (dataflowOperator) {
                    var dfResult = HandleDataflowActivation(args, streamSpec);
                    streamEventTypes[stream] = dfResult.StreamEventType;
                    eventTypeNames[stream] = dfResult.EventTypeName;
                    viewableActivatorForges[stream] = dfResult.ViewableActivatorForge;
                    viewForges[stream] = dfResult.ViewForges;
                    additionalForgeables.AddAll(dfResult.AdditionalForgeables);
                }
                else if (streamSpec is FilterStreamSpecCompiled) {
                    var filterStreamSpec = (FilterStreamSpecCompiled) statementSpec.StreamSpecs[stream];
                    var filterSpecCompiled = filterStreamSpec.FilterSpecCompiled;
                    streamEventTypes[stream] = filterSpecCompiled.ResultEventType;
                    eventTypeNames[stream] = filterStreamSpec.FilterSpecCompiled.FilterForEventTypeName;

                    viewableActivatorForges[stream] = new ViewableActivatorFilterForge(
                        filterSpecCompiled,
                        isCanIterateUnbound,
                        stream,
                        false,
                        -1);
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, streamEventTypes[stream]);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                    filterSpecCompileds.Add(filterSpecCompiled);
                }
                else if (streamSpec is PatternStreamSpecCompiled) {
                    var patternStreamSpec = (PatternStreamSpecCompiled) streamSpec;
                    var forges = patternStreamSpec.Root.CollectFactories();
                    foreach (var forgeNode in forges) {
                        forgeNode.CollectSelfFilterAndSchedule(filterSpecCompileds, scheduleHandleCallbackProviders);
                    }

                    var patternType = ViewableActivatorPatternForge.MakeRegisterPatternType(
                        @base,
                        stream,
                        patternStreamSpec,
                        services);
                    var patternContext = new PatternContext(0, patternStreamSpec.MatchedEventMapMeta, false, -1, false);
                    viewableActivatorForges[stream] = new ViewableActivatorPatternForge(
                        patternType,
                        patternStreamSpec,
                        patternContext,
                        isCanIterateUnbound);
                    streamEventTypes[stream] = patternType;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, patternType);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                }
                else if (streamSpec is NamedWindowConsumerStreamSpec) {
                    var namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
                    var namedWindow =
                        services.NamedWindowCompileTimeResolver.Resolve(namedSpec.NamedWindow.EventType.Name);
                    var namedWindowType = namedWindow.EventType;
                    if (namedSpec.OptPropertyEvaluator != null) {
                        namedWindowType = namedSpec.OptPropertyEvaluator.FragmentEventType;
                    }

                    var typesFilterValidation = new StreamTypeServiceImpl(
                        namedWindowType,
                        namedSpec.OptionalStreamName,
                        false);
                    var filterSingle =
                        ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(namedSpec.FilterExpressions);
                    var filterQueryGraph = EPLValidationUtil.ValidateFilterGetQueryGraphSafe(
                        filterSingle,
                        typesFilterValidation,
                        @base.StatementRawInfo,
                        services);

                    namedWindowConsumers.Add(namedSpec);
                    viewableActivatorForges[stream] = new ViewableActivatorNamedWindowForge(
                        namedSpec,
                        namedWindow,
                        filterSingle,
                        filterQueryGraph,
                        true,
                        namedSpec.OptPropertyEvaluator);
                    streamEventTypes[stream] = namedWindowType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    joinAnalysisResult.SetNamedWindowsPerStream(stream, namedWindow);
                    eventTypeNames[stream] = namedSpec.NamedWindow.EventType.Name;
                    isNamedWindow[stream] = true;

                    // Consumers to named windows cannot declare a data window view onto the named window to avoid duplicate remove streams
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, namedWindowType);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);

                    EPStatementStartMethodHelperValidate.ValidateNoDataWindowOnNamedWindow(viewForges[stream]);
                }
                else if (streamSpec is TableQueryStreamSpec) {
                    ValidateNoViews(streamSpec, "Table data");
                    var tableStreamSpec = (TableQueryStreamSpec) streamSpec;
                    if (numStreams > 1 && tableStreamSpec.FilterExpressions.Count > 0) {
                        throw new ExprValidationException(
                            "Joins with tables do not allow table filter expressions, please add table filters to the where-clause instead");
                    }

                    var table = tableStreamSpec.Table;
                    EPLValidationUtil.ValidateContextName(
                        true,
                        table.TableName,
                        table.OptionalContextName,
                        statementSpec.Raw.OptionalContextName,
                        false);
                    var filter =
                        ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(tableStreamSpec.FilterExpressions);
                    viewableActivatorForges[stream] = new ViewableActivatorTableForge(table, filter);
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    eventTypeNames[stream] = tableStreamSpec.Table.TableName;
                    streamEventTypes[stream] = tableStreamSpec.Table.InternalEventType;
                    joinAnalysisResult.SetTablesForStream(stream, table);

                    if (tableStreamSpec.Options.IsUnidirectional) {
                        throw new ExprValidationException("Tables cannot be marked as unidirectional");
                    }

                    if (tableStreamSpec.Options.IsRetainIntersection || tableStreamSpec.Options.IsRetainUnion) {
                        throw new ExprValidationException("Tables cannot be marked with retain");
                    }
                }
                else if (streamSpec is DBStatementStreamSpec) {
                    ValidateNoViews(streamSpec, "Historical data");
                    var sqlStreamSpec = (DBStatementStreamSpec) streamSpec;
                    var typeConversionHook = (SQLColumnTypeConversion) ImportUtil.GetAnnotationHook(
                        statementSpec.Annotations,
                        HookType.SQLCOL,
                        typeof(SQLColumnTypeConversion),
                        services.ImportServiceCompileTime);
                    var outputRowConversionHook = (SQLOutputRowConversion) ImportUtil.GetAnnotationHook(
                        statementSpec.Annotations,
                        HookType.SQLROW,
                        typeof(SQLOutputRowConversion),
                        services.ImportServiceCompileTime);
                    var viewable = HistoricalEventViewableDatabaseForgeFactory.CreateDBStatementView(
                        stream,
                        sqlStreamSpec,
                        typeConversionHook,
                        outputRowConversionHook,
                        @base,
                        services,
                        statementSpec.Annotations);
                    streamEventTypes[stream] = viewable.EventType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    viewableActivatorForges[stream] = new ViewableActivatorHistoricalForge(viewable);
                    historicalEventViewables[stream] = viewable;
                }
                else if (streamSpec is MethodStreamSpec) {
                    ValidateNoViews(streamSpec, "Method data");
                    var methodStreamSpec = (MethodStreamSpec) streamSpec;
                    var viewable = HistoricalEventViewableMethodForgeFactory.CreateMethodStatementView(
                        stream,
                        methodStreamSpec,
                        @base,
                        services);
                    historicalEventViewables[stream] = viewable;
                    streamEventTypes[stream] = viewable.EventType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    viewableActivatorForges[stream] = new ViewableActivatorHistoricalForge(viewable);
                    historicalEventViewables[stream] = viewable;
                }
                else {
                    throw new IllegalStateException("Unrecognized stream " + streamSpec);
                }
                
                // plan serde for iterate-unbound
                if (isCanIterateUnbound) {
                    var serdeForgeables = SerdeEventTypeUtility.Plan(
                        streamEventTypes[stream], @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                    additionalForgeables.AddAll(serdeForgeables);
                }
            }

            // handle match-recognize pattern
            if (statementSpec.Raw.MatchRecognizeSpec != null) {
                if (numStreams > 1) {
                    throw new ExprValidationException("Joins are not allowed when using match-recognize");
                }

                if (joinAnalysisResult.TablesPerStream[0] != null) {
                    throw new ExprValidationException("Tables cannot be used with match-recognize");
                }

                var isUnbound = viewForges[0].IsEmpty() &&
                                !(statementSpec.StreamSpecs[0] is NamedWindowConsumerStreamSpec);
                var eventType = viewForges[0].IsEmpty()
                    ? streamEventTypes[0]
                    : viewForges[0][(viewForges[0].Count - 1)].EventType;
                
                var plan = RowRecogNFAViewPlanUtil.ValidateAndPlan(services.Container, eventType, isUnbound, @base, services);
                var forge = new RowRecogNFAViewFactoryForge(plan.Forge);
                additionalForgeables.AddAll(plan.AdditionalForgeables);
                scheduleHandleCallbackProviders.Add(forge);
                viewForges[0].Add(forge);
                var serdeForgeables = SerdeEventTypeUtility.Plan(
                    eventType, @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                additionalForgeables.AddAll(serdeForgeables);
            }

            // Obtain event types from view factory chains
            for (var i = 0; i < viewForges.Length; i++) {
                streamEventTypes[i] = viewForges[i].IsEmpty()
                    ? streamEventTypes[i]
                    : viewForges[i][(viewForges[i].Count - 1)].EventType;
            }

            // add unique-information to join analysis
            joinAnalysisResult.AddUniquenessInfo(viewForges, statementSpec.Annotations);

            // plan sub-selects
            SubSelectHelperForgePlan subselectForgePlan = SubSelectHelperForgePlanner.PlanSubSelect(
                @base, subselectActivation, streamNames, streamEventTypes, eventTypeNames, services);
            var subselectForges = subselectForgePlan.Subselects;
            additionalForgeables.AddAll(subselectForgePlan.AdditionalForgeables);

            DetermineViewSchedules(subselectForges, scheduleHandleCallbackProviders);

            // determine view schedules
            var viewResourceDelegateExpr = new ViewResourceDelegateExpr();
            ViewFactoryForgeUtil.DetermineViewSchedules(viewForges, scheduleHandleCallbackProviders);

            var hasIStreamOnly = StatementForgeMethodSelectUtil.GetHasIStreamOnly(isNamedWindow, viewForges);
            var optionalStreamsIfAny = OuterJoinAnalyzer.OptionalStreamsIfAny(statementSpec.Raw.OuterJoinDescList);
            StreamTypeService typeService = new StreamTypeServiceImpl(
                streamEventTypes,
                streamNames,
                hasIStreamOnly,
                false,
                optionalStreamsIfAny);

            // Validate views that require validation, specifically streams that don't have
            // sub-views such as DB SQL joins
            var historicalViewableDesc = new HistoricalViewableDesc(numStreams);
            for (var stream = 0; stream < historicalEventViewables.Length; stream++) {
                var historicalEventViewable = historicalEventViewables[stream];
                if (historicalEventViewable == null) {
                    continue;
                }

                scheduleHandleCallbackProviders.Add(historicalEventViewable);
                IList<StmtClassForgeableFactory> forgeables = historicalEventViewable.Validate(typeService, @base, services);
                additionalForgeables.AddAll(forgeables);
                historicalViewableDesc.SetHistorical(stream, historicalEventViewable.RequiredStreams);
                if (historicalEventViewable.RequiredStreams.Contains(stream)) {
                    throw new ExprValidationException(
                        "Parameters for historical stream " +
                        stream +
                        " indicate that the stream is subordinate to itself as stream parameters originate in the same stream");
                }
            }

            // Validate where-clause filter tree, outer join clause and output limit expression
            var whereClauseValidated = EPStatementStartMethodHelperValidate.ValidateNodes(
                statementSpec.Raw,
                typeService,
                viewResourceDelegateExpr,
                @base.StatementRawInfo,
                services);
            var whereClauseForge = whereClauseValidated?.Forge;

            // Obtain result set processor
            var resultSetProcessorDesc = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                new ResultSetSpec(statementSpec),
                typeService,
                viewResourceDelegateExpr,
                joinAnalysisResult.UnidirectionalInd,
                true,
                @base.ContextPropertyRegistry,
                false,
                false,
                @base.StatementRawInfo,
                services);
            additionalForgeables.AddAll(resultSetProcessorDesc.AdditionalForgeables);

            // Handle 'prior' function nodes in terms of view requirements
            var viewResourceDelegateDesc =
                ViewResourceVerifyHelper.VerifyPreviousAndPriorRequirements(viewForges, viewResourceDelegateExpr);
            var hasPrior = ViewResourceDelegateDesc.HasPrior(viewResourceDelegateDesc);
            if (hasPrior) {
                for (var stream = 0; stream < numStreams; stream++) {
                    if (!viewResourceDelegateDesc[stream].PriorRequests.IsEmpty()) {
                        viewForges[stream].Add(new PriorEventViewForge(viewForges[stream].IsEmpty(), streamEventTypes[stream]));
                        var serdeForgeables = SerdeEventTypeUtility.Plan(
                            streamEventTypes[stream], @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                        additionalForgeables.AddAll(serdeForgeables);
                    }
                }
            }

            var outputProcessDesc = OutputProcessViewForgeFactory.Make(
                typeService.EventTypes,
                resultSetProcessorDesc.ResultEventType,
                resultSetProcessorDesc.ResultSetProcessorType,
                statementSpec,
                @base.StatementRawInfo,
                services);
            var outputProcessViewFactoryForge = outputProcessDesc.Forge;
            additionalForgeables.AddAll(outputProcessDesc.AdditionalForgeables);
            outputProcessViewFactoryForge.CollectSchedules(scheduleHandleCallbackProviders);

            JoinSetComposerPrototypeForge joinForge = null;
            if (numStreams > 1) {
                var hasAggregations = !resultSetProcessorDesc.AggregationServiceForgeDesc.Expressions.IsEmpty();
                var desc = JoinSetComposerPrototypeForgeFactory.MakeComposerPrototype(
                    statementSpec,
                    joinAnalysisResult,
                    typeService,
                    historicalViewableDesc,
                    false,
                    hasAggregations,
                    @base.StatementRawInfo,
                    services);
                joinForge = desc.Forge;
                additionalForgeables.AddAll(desc.AdditionalForgeables);
                HandleIndexDependencies(joinForge.OptionalQueryPlan, services);
            }

            // plan table access
            var tableAccessForges =
                ExprTableEvalHelperPlan.PlanTableAccess(@base.StatementSpec.TableAccessNodes);
            ValidateTableAccessUse(statementSpec.Raw.IntoTableSpec, statementSpec.Raw.TableExpressions);
            if (joinAnalysisResult.IsUnidirectional && statementSpec.Raw.IntoTableSpec != null) {
                throw new ExprValidationException("Into-table does not allow unidirectional joins");
            }

            var orderByWithoutOutputLimit = statementSpec.Raw.OrderByList != null &&
                                            !statementSpec.Raw.OrderByList.IsEmpty() &&
                                            statementSpec.Raw.OutputLimitSpec == null;

            var statementAIFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(StatementAIFactoryProvider),
                classPostfix);
            var resultSetProcessorProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(ResultSetProcessorFactoryProvider),
                classPostfix);
            var outputProcessViewProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(OutputProcessViewFactoryProvider),
                classPostfix);
            var statementProviderClassName =
                CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix);
            var statementFieldsClassName =
                CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementFields), classPostfix);
            //var statementFieldsClassName = namespaceScope.FieldsClassNameOptional;

            var forgeX = new StatementAgentInstanceFactorySelectForge(
                typeService.StreamNames,
                viewableActivatorForges,
                resultSetProcessorProviderClassName,
                viewForges,
                viewResourceDelegateDesc,
                whereClauseForge,
                joinForge,
                outputProcessViewProviderClassName,
                subselectForges,
                tableAccessForges,
                orderByWithoutOutputLimit,
                joinAnalysisResult.IsUnidirectional);

            var namespaceScope = new CodegenNamespaceScope(
                @namespace,
                statementFieldsClassName,
                services.IsInstrumented);

            var forgeablesX = additionalForgeables
                .Select(additional => additional.Make(namespaceScope, classPostfix))
                .ToList();

            forgeablesX.Add(
                new StmtClassForgeableRSPFactoryProvider(
                    resultSetProcessorProviderClassName,
                    resultSetProcessorDesc,
                    namespaceScope,
                    @base.StatementRawInfo));
            forgeablesX.Add(
                new StmtClassForgeableOPVFactoryProvider(
                    outputProcessViewProviderClassName,
                    outputProcessViewFactoryForge,
                    namespaceScope,
                    numStreams,
                    @base.StatementRawInfo));
            forgeablesX.Add(
                new StmtClassForgeableAIFactoryProviderSelect(statementAIFactoryProviderClassName, namespaceScope, forgeX));
            forgeablesX.Add(
                new StmtClassForgeableStmtFields(statementFieldsClassName, namespaceScope, numStreams));

            if (!dataflowOperator) {
                var informationals = StatementInformationalsUtil.GetInformationals(
                    @base,
                    filterSpecCompileds,
                    scheduleHandleCallbackProviders,
                    namedWindowConsumers,
                    true,
                    resultSetProcessorDesc.SelectSubscriberDescriptor,
                    namespaceScope,
                    services);
                forgeablesX.Add(
                    new StmtClassForgeableStmtProvider(statementAIFactoryProviderClassName, statementProviderClassName, informationals, namespaceScope));
            }

            var forgeableResult = new StmtForgeMethodResult(
                forgeablesX,
                filterSpecCompileds,
                scheduleHandleCallbackProviders,
                namedWindowConsumers,
                FilterSpecCompiled.MakeExprNodeList(filterSpecCompileds, EmptyList<FilterSpecParamExprNodeForge>.Instance));
            return new StmtForgeMethodSelectResult(forgeableResult, resultSetProcessorDesc.ResultEventType, numStreams);
        }
Ejemplo n.º 5
0
 public ExprValidationContextBuilder WithViewResourceDelegate(ViewResourceDelegateExpr viewResourceDelegate)
 {
     _viewResourceDelegate = viewResourceDelegate;
     return this;
 }
Ejemplo n.º 6
0
        public static ExprNode ValidateNodes(
            StatementSpecRaw statementSpec,
            StreamTypeService typeService,
            ViewResourceDelegateExpr viewResourceDelegate,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            var intoTableName = statementSpec.IntoTableSpec == null ? null : statementSpec.IntoTableSpec.Name;

            ExprNode whereClauseValidated = null;
            if (statementSpec.WhereClause != null) {
                var whereClause = statementSpec.WhereClause;

                // Validate where clause, initializing nodes to the stream ids used
                try {
                    var validationContext = new ExprValidationContextBuilder(
                            typeService,
                            statementRawInfo,
                            compileTimeServices)
                        .WithViewResourceDelegate(viewResourceDelegate)
                        .WithAllowBindingConsumption(true)
                        .WithIntoTableName(intoTableName)
                        .Build();
                    whereClause = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.FILTER,
                        whereClause,
                        validationContext);
                    if (whereClause.Forge.EvaluationType != typeof(bool) &&
                        whereClause.Forge.EvaluationType != typeof(bool?)) {
                        throw new ExprValidationException(
                            "The where-clause filter expression must return a boolean value");
                    }

                    whereClauseValidated = whereClause;

                    // Make sure there is no aggregation in the where clause
                    IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>();
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(whereClause, aggregateNodes);
                    if (!aggregateNodes.IsEmpty()) {
                        throw new ExprValidationException(
                            "An aggregate function may not appear in a WHERE clause (use the HAVING clause)");
                    }
                }
                catch (ExprValidationException ex) {
                    throw new ExprValidationException("Failed to validate expression: " + ex.Message, ex);
                }
            }

            if ((statementSpec.OutputLimitSpec != null) && 
                (statementSpec.OutputLimitSpec.WhenExpressionNode != null || 
                 statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null || 
                 statementSpec.OutputLimitSpec.AndAfterTerminateThenExpressions != null)) {
                // Validate where clause, initializing nodes to the stream ids used
                EventType outputLimitType = OutputConditionExpressionTypeUtil.GetBuiltInEventType(
                    statementRawInfo.ModuleName,
                    compileTimeServices.BeanEventTypeFactoryPrivate);
                StreamTypeService typeServiceOutputWhen = new StreamTypeServiceImpl(
                    new[] {outputLimitType},
                    new string[] {null},
                    new[] {true},
                    false,
                    false);
                var validationContext = new ExprValidationContextBuilder(
                        typeServiceOutputWhen,
                        statementRawInfo,
                        compileTimeServices)
                    .WithIntoTableName(intoTableName)
                    .Build();

                var outputLimitWhenNode = statementSpec.OutputLimitSpec.WhenExpressionNode;
                if (outputLimitWhenNode != null) {
                    outputLimitWhenNode = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.OUTPUTLIMIT,
                        outputLimitWhenNode,
                        validationContext);
                    statementSpec.OutputLimitSpec.WhenExpressionNode = outputLimitWhenNode;

                    if (outputLimitWhenNode.Forge.EvaluationType.GetBoxedType() != typeof(bool?)) {
                        throw new ExprValidationException(
                            "The when-trigger expression in the OUTPUT WHEN clause must return a boolean-type value");
                    }

                    ValidateNoAggregations(
                        outputLimitWhenNode,
                        "An aggregate function may not appear in a OUTPUT LIMIT clause");
                }

                // validate and-terminate expression if provided
                if (statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null) {
                    if (statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.WHEN_EXPRESSION &&
                        statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.TERM) {
                        throw new ExprValidationException(
                            "A terminated-and expression must be used with the OUTPUT WHEN clause");
                    }

                    var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.OUTPUTLIMIT,
                        statementSpec.OutputLimitSpec.AndAfterTerminateExpr,
                        validationContext);
                    statementSpec.OutputLimitSpec.AndAfterTerminateExpr = validated;

                    if (validated.Forge.EvaluationType.GetBoxedType() != typeof(bool?)) {
                        throw new ExprValidationException(
                            "The terminated-and expression must return a boolean-type value");
                    }

                    ValidateNoAggregations(
                        validated,
                        "An aggregate function may not appear in a terminated-and clause");
                }

                // validate then-expression
                ValidateThenSetAssignments(statementSpec.OutputLimitSpec.ThenExpressions, validationContext, false);

                // validate after-terminated then-expression
                ValidateThenSetAssignments(statementSpec.OutputLimitSpec.AndAfterTerminateThenExpressions, validationContext, false);
            }

            for (var outerJoinCount = 0; outerJoinCount < statementSpec.OuterJoinDescList.Count; outerJoinCount++) {
                var outerJoinDesc = statementSpec.OuterJoinDescList[outerJoinCount];

                // validate on-expression nodes, if provided
                if (outerJoinDesc.OptLeftNode != null) {
                    var streamIdPair = ValidateOuterJoinPropertyPair(
                        outerJoinDesc.OptLeftNode,
                        outerJoinDesc.OptRightNode,
                        outerJoinCount,
                        typeService,
                        viewResourceDelegate,
                        statementRawInfo,
                        compileTimeServices
                    );

                    if (outerJoinDesc.AdditionalLeftNodes != null) {
                        ISet<int> streamSet = new HashSet<int>();
                        streamSet.Add(streamIdPair.First);
                        streamSet.Add(streamIdPair.Second);
                        for (var i = 0; i < outerJoinDesc.AdditionalLeftNodes.Length; i++) {
                            var streamIdPairAdd = ValidateOuterJoinPropertyPair(
                                outerJoinDesc.AdditionalLeftNodes[i],
                                outerJoinDesc.AdditionalRightNodes[i],
                                outerJoinCount,
                                typeService,
                                viewResourceDelegate,
                                statementRawInfo,
                                compileTimeServices
                            );

                            // make sure all additional properties point to the same two streams
                            if (!streamSet.Contains(streamIdPairAdd.First) ||
                                !streamSet.Contains(streamIdPairAdd.Second)) {
                                var message =
                                    "Outer join ON-clause columns must refer to properties of the same joined streams" +
                                    " when using multiple columns in the on-clause";
                                throw new ExprValidationException("Failed to validate outer-join expression: " + message);
                            }
                        }
                    }
                }
            }

            return whereClauseValidated;
        }
Ejemplo n.º 7
0
        protected internal static UniformPair<int> ValidateOuterJoinPropertyPair(
            ExprIdentNode leftNode,
            ExprIdentNode rightNode,
            int outerJoinCount,
            StreamTypeService typeService,
            ViewResourceDelegateExpr viewResourceDelegate,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            // Validate the outer join clause using an artificial equals-node on top.
            // Thus types are checked via equals.
            // Sets stream ids used for validated nodes.
            ExprNode equalsNode = new ExprEqualsNodeImpl(false, false);
            equalsNode.AddChildNode(leftNode);
            equalsNode.AddChildNode(rightNode);
            try {
                var validationContext = new ExprValidationContextBuilder(
                        typeService,
                        statementRawInfo,
                        compileTimeServices)
                    .WithViewResourceDelegate(viewResourceDelegate)
                    .WithAllowBindingConsumption(true)
                    .WithIsFilterExpression(true)
                    .Build();
                ExprNodeUtilityValidate.GetValidatedSubtree(ExprNodeOrigin.JOINON, equalsNode, validationContext);
            }
            catch (ExprValidationException ex) {
                throw new ExprValidationException("Failed to validate outer-join expression: " + ex.Message, ex);
            }

            // Make sure we have left-hand-side and right-hand-side refering to different streams
            var streamIdLeft = leftNode.StreamId;
            var streamIdRight = rightNode.StreamId;
            if (streamIdLeft == streamIdRight) {
                var message = "Outer join ON-clause cannot refer to properties of the same stream";
                throw new ExprValidationException("Failed to validate outer-join expression: " + message);
            }

            // Make sure one of the properties refers to the acutual stream currently being joined
            var expectedStreamJoined = outerJoinCount + 1;
            if (streamIdLeft != expectedStreamJoined && streamIdRight != expectedStreamJoined) {
                var message = "Outer join ON-clause must refer to at least one property of the joined stream" +
                              " for stream " +
                              expectedStreamJoined;
                throw new ExprValidationException("Failed to validate outer-join expression: " + message);
            }

            // Make sure neither of the streams refer to a 'future' stream
            string badPropertyName = null;
            if (streamIdLeft > outerJoinCount + 1) {
                badPropertyName = leftNode.ResolvedPropertyName;
            }

            if (streamIdRight > outerJoinCount + 1) {
                badPropertyName = rightNode.ResolvedPropertyName;
            }

            if (badPropertyName != null) {
                var message = "Outer join ON-clause invalid scope for property" +
                              " '" +
                              badPropertyName +
                              "', expecting the current or a prior stream scope";
                throw new ExprValidationException("Failed to validate outer-join expression: " + message);
            }

            return new UniformPair<int>(streamIdLeft, streamIdRight);
        }