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; }
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); }
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; }
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); }
public ExprValidationContextBuilder WithViewResourceDelegate(ViewResourceDelegateExpr viewResourceDelegate) { _viewResourceDelegate = viewResourceDelegate; return this; }
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; }
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); }