public static void ValidateFilterWQueryGraphSafe( QueryGraphForge queryGraph, ExprNode filterExpression, StreamTypeServiceImpl typeService, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { try { var validationContext = new ExprValidationContextBuilder(typeService, statementRawInfo, services) .WithAllowBindingConsumption(true) .WithIsFilterExpression(true) .Build(); var validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.FILTER, filterExpression, validationContext); FilterExprAnalyzer.Analyze(validated, queryGraph, false); } catch (Exception ex) { Log.Warn( "Unexpected exception analyzing filterable expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(filterExpression) + "': " + ex.Message, ex); } }
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; }
protected internal static ExprNode ValidateJoinNamedWindow( ExprNodeOrigin exprNodeOrigin, ExprNode deleteJoinExpr, EventType namedWindowType, string namedWindowStreamName, string namedWindowName, EventType filteredType, string filterStreamName, string filteredTypeName, string optionalTableName, StatementRawInfo statementRawInfo, StatementCompileTimeServices compileTimeServices ) { if (deleteJoinExpr == null) { return null; } var namesAndTypes = new LinkedHashMap<string, Pair<EventType, string>>(); namesAndTypes.Put(namedWindowStreamName, new Pair<EventType, string>(namedWindowType, namedWindowName)); namesAndTypes.Put(filterStreamName, new Pair<EventType, string>(filteredType, filteredTypeName)); StreamTypeService typeService = new StreamTypeServiceImpl(namesAndTypes, false, false); var validationContext = new ExprValidationContextBuilder(typeService, statementRawInfo, compileTimeServices) .WithAllowBindingConsumption(true) .Build(); return ExprNodeUtilityValidate.GetValidatedSubtree(exprNodeOrigin, deleteJoinExpr, validationContext); }
public static ExprForge[] CrontabScheduleValidate( ExprNodeOrigin origin, IList<ExprNode> scheduleSpecExpressionList, bool allowBindingConsumption, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { // Validate the expressions ExprForge[] expressions = new ExprForge[scheduleSpecExpressionList.Count]; int count = 0; ExprValidationContext validationContext = new ExprValidationContextBuilder(new StreamTypeServiceImpl(false), statementRawInfo, services) .WithAllowBindingConsumption(allowBindingConsumption) .Build(); foreach (ExprNode parameters in scheduleSpecExpressionList) { ExprNode node = ExprNodeUtilityValidate.GetValidatedSubtree(origin, parameters, validationContext); expressions[count++] = node.Forge; } if (expressions.Length <= 4 || expressions.Length >= 8) { throw new ExprValidationException( "Invalid schedule specification: " + ScheduleSpecUtil.GetExpressionCountException(expressions.Length)); } return expressions; }
public static ExprNode ValidateExpr( string viewName, ExprNode expression, StreamTypeService streamTypeService, ViewForgeEnv viewForgeEnv, int expressionNumber, int streamNumber) { ExprNode validated; try { var names = new ExprValidationMemberNameQualifiedView(streamNumber); var validationContext = new ExprValidationContextBuilder( streamTypeService, viewForgeEnv.StatementRawInfo, viewForgeEnv.StatementCompileTimeServices) .WithMemberName(names) .Build(); validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.VIEWPARAMETER, expression, validationContext); } catch (ExprValidationException ex) { var message = "Invalid parameter expression " + expressionNumber + GetViewDesc(viewName); if (ex.Message != null) { message += ": " + ex.Message; } throw new ViewParameterException(message, ex); } return validated; }
protected override void InitExec( string aliasName, StatementSpecCompiled spec, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { StreamTypeServiceImpl assignmentTypeService = new StreamTypeServiceImpl( new EventType[] { processor.EventTypeRspInputEvents, null, processor.EventTypeRspInputEvents }, new string[] {aliasName, "", INITIAL_VALUE_STREAM_NAME}, new bool[] {true, true, true}, true, false); assignmentTypeService.IsStreamZeroUnambigous = true; ExprValidationContext validationContext = new ExprValidationContextBuilder(assignmentTypeService, statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); // validate update expressions FireAndForgetSpecUpdate updateSpec = (FireAndForgetSpecUpdate) spec.Raw.FireAndForgetSpec; try { foreach (OnTriggerSetAssignment assignment in updateSpec.Assignments) { ExprNode validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.UPDATEASSIGN, assignment.Expression, validationContext); assignment.Expression = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations( validated, "Aggregation functions may not be used within an update-clause"); } } catch (ExprValidationException e) { throw new EPException(e.Message, e); } // make updater //TableUpdateStrategy tableUpdateStrategy = null; try { bool copyOnWrite = processor is FireAndForgetProcessorNamedWindowForge; updateHelper = EventBeanUpdateHelperForgeFactory.Make( processor.NamedWindowOrTableName, (EventTypeSPI) processor.EventTypeRspInputEvents, updateSpec.Assignments, aliasName, null, copyOnWrite, statementRawInfo.StatementName, services.EventTypeAvroHandler); } catch (ExprValidationException e) { throw new EPException(e.Message, e); } }
private static ExprAndNode MakeValidateAndNode( IList<ExprNode> remainingExprNodes, FilterSpecCompilerArgs args) { var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAnd(remainingExprNodes); var validationContext = new ExprValidationContextBuilder(args.streamTypeService, args.statementRawInfo, args.compileTimeServices) .WithAllowBindingConsumption(true) .WithContextDescriptor(args.contextDescriptor) .Build(); andNode.Validate(validationContext); return andNode; }
public ExprNode CompileValidate( string expression, EventType[] eventTypes, string[] streamNames) { var services = new StatementCompileTimeServices(0, moduleServices); ExprNode node; try { node = services.CompilerServices.CompileExpression(expression, services); } catch (ExprValidationException e) { throw new EPCompileException( "Failed to compile expression '" + expression + "': " + e.Message, e, new EmptyList<EPCompileExceptionItem>()); } try { ExprNodeUtilityValidate.ValidatePlainExpression(ExprNodeOrigin.API, node); StreamTypeService streamTypeService; if (eventTypes == null || eventTypes.Length == 0) { streamTypeService = new StreamTypeServiceImpl(true); } else { var istreamOnly = new bool[eventTypes.Length]; istreamOnly.Fill(true); streamTypeService = new StreamTypeServiceImpl(eventTypes, streamNames, istreamOnly, true, false); } var statementRawInfo = new StatementRawInfo( 0, "API-provided", null, StatementType.INTERNAL_USE_API_COMPILE_EXPR, null, null, new CompilableEPL(expression), "API-provided"); var validationContext = new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build(); node = ExprNodeUtilityValidate.GetValidatedSubtree(ExprNodeOrigin.API, node, validationContext); } catch (ExprValidationException e) { throw new EPCompileException( "Failed to validate expression '" + expression + "': " + e.Message, e, new EmptyList<EPCompileExceptionItem>()); } return node; }
private static EventAdvancedIndexProvisionCompileTime ValidateAdvanced( string indexName, string indexType, CreateIndexItem columnDesc, EventType eventType, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { // validate index expressions: valid and plain expressions StreamTypeService streamTypeService = new StreamTypeServiceImpl(eventType, null, false); var validationContextColumns = new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services) .WithDisablePropertyExpressionEventCollCache(true) .Build(); var columns = columnDesc.Expressions.ToArray(); ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CREATEINDEXCOLUMN, columns, validationContextColumns); ExprNodeUtilityValidate.ValidatePlainExpression(ExprNodeOrigin.CREATEINDEXCOLUMN, columns); // validate parameters, may not depend on props ExprNode[] parameters = null; if (columnDesc.Parameters != null && !columnDesc.Parameters.IsEmpty()) { parameters = columnDesc.Parameters.ToArray(); ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CREATEINDEXPARAMETER, parameters, validationContextColumns); ExprNodeUtilityValidate.ValidatePlainExpression(ExprNodeOrigin.CREATEINDEXPARAMETER, parameters); // validate no stream dependency of parameters var visitor = new ExprNodeIdentifierAndStreamRefVisitor(false); foreach (var param in columnDesc.Parameters) { param.Accept(visitor); if (!visitor.Refs.IsEmpty()) { throw new ExprValidationException("Index parameters may not refer to event properties"); } } } // obtain provider AdvancedIndexFactoryProvider provider; try { provider = services.ImportServiceCompileTime.ResolveAdvancedIndexProvider(indexType); } catch (ImportException ex) { throw new ExprValidationException(ex.Message, ex); } return provider.ValidateEventIndex(indexName, indexType, columns, parameters); }
private static IList<NamedWindowSelectedProps> CompileLimitedSelect( SelectFromInfo selectFromInfo, StatementBaseInfo @base, StatementCompileTimeServices compileTimeServices) { IList<NamedWindowSelectedProps> selectProps = new List<NamedWindowSelectedProps>(); StreamTypeService streams = new StreamTypeServiceImpl( new[] {selectFromInfo.EventType}, new[] {"stream_0"}, new[] {false}, false, false); var validationContext = new ExprValidationContextBuilder(streams, @base.StatementRawInfo, compileTimeServices).Build(); foreach (var item in @base.StatementSpec.SelectClauseCompiled.SelectExprList) { if (!(item is SelectClauseExprCompiledSpec)) { continue; } var exprSpec = (SelectClauseExprCompiledSpec) item; var validatedExpression = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.SELECT, exprSpec.SelectExpression, validationContext); // determine an element name if none assigned var asName = exprSpec.ProvidedName; if (asName == null) { asName = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validatedExpression); } // check for fragments EventType fragmentType = null; if (validatedExpression is ExprIdentNode && !(selectFromInfo.EventType is NativeEventType)) { var identNode = (ExprIdentNode) validatedExpression; var fragmentEventType = selectFromInfo.EventType.GetFragmentType(identNode.FullUnresolvedName); if (fragmentEventType != null && !fragmentEventType.IsNative) { fragmentType = fragmentEventType.FragmentType; } } var validatedElement = new NamedWindowSelectedProps( validatedExpression.Forge.EvaluationType, asName, fragmentType); selectProps.Add(validatedElement); } return selectProps; }
private void TopValidate( ExprNode exprNode, StatementRawInfo statementRawInfo, StatementCompileTimeServices compileTimeServices) { try { ExprValidationContext validationContext = new ExprValidationContextBuilder(null, statementRawInfo, compileTimeServices).Build(); exprNode.Validate(validationContext); } catch (ExprValidationException) { throw new IllegalStateException("Failed to make representative node for outer join criteria"); } }
public override IList<StmtClassForgeableFactory> Validate( StreamTypeService typeService, StatementBaseInfo @base, StatementCompileTimeServices services) { int count = 0; ExprValidationContext validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); ExprNode[] inputParamNodes = new ExprNode[inputParameters.Length]; foreach (string inputParam in inputParameters) { ExprNode raw = FindSQLExpressionNode(StreamNum, count, @base.StatementSpec.Raw.SqlParameters); if (raw == null) { throw new ExprValidationException( "Internal error find expression for historical stream parameter " + count + " stream " + StreamNum); } ExprNode evaluator = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.DATABASEPOLL, raw, validationContext); inputParamNodes[count++] = evaluator; ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor(); visitor.Visit(evaluator); foreach (ExprIdentNode identNode in visitor.ExprProperties) { if (identNode.StreamId == StreamNum) { throw new ExprValidationException( "Invalid expression '" + inputParam + "' resolves to the historical data itself"); } SubordinateStreams.Add(identNode.StreamId); } } InputParamEvaluators = ExprNodeUtilityQuery.GetForges(inputParamNodes); // plan multikey MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver); MultiKeyClassRef = multiKeyPlan.ClassRef; return multiKeyPlan.MultiKeyForgeables; }
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); }
public OutputConditionPolledCrontabFactoryForge( IList<ExprNode> list, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { ExprValidationContext validationContext = new ExprValidationContextBuilder(new StreamTypeServiceImpl(false), statementRawInfo, services).Build(); expressions = new ExprNode[list.Count]; int count = 0; foreach (ExprNode parameters in list) { ExprNode node = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.OUTPUTLIMIT, parameters, validationContext); expressions[count++] = node; } }
public static ExprNode ValidateExprNoAgg( ExprNodeOrigin exprNodeOrigin, ExprNode exprNode, StreamTypeService streamTypeService, string errorMsg, bool allowTableConsumption, bool allowTableAggReset, StatementRawInfo raw, StatementCompileTimeServices compileTimeServices) { var validationContext = new ExprValidationContextBuilder(streamTypeService, raw, compileTimeServices) .WithAllowBindingConsumption(allowTableConsumption) .WithAllowTableAggReset(allowTableAggReset) .Build(); var validated = ExprNodeUtilityValidate.GetValidatedSubtree(exprNodeOrigin, exprNode, validationContext); ValidateNoAggregations(validated, errorMsg); return validated; }
private static ExprNode ValidateMeasureClause( ExprNode measureNode, StreamTypeService typeServiceMeasure, ISet<string> variablesMultiple, ISet<string> variablesSingle, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { try { var validationContext = new ExprValidationContextBuilder(typeServiceMeasure, statementRawInfo, services) .WithAllowBindingConsumption(true) .WithDisablePropertyExpressionEventCollCache(true) .WithAggregationFutureNameAlreadySet(true) .Build(); return ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGMEASURE, measureNode, validationContext); } catch (ExprValidationPropertyException e) { var grouped = CollectionUtil.ToString(variablesMultiple); var single = CollectionUtil.ToString(variablesSingle); var message = e.Message; if (!variablesMultiple.IsEmpty()) { message += ", ensure that grouped variables (variables " + grouped + ") are accessed via index (i.e. variable[0].property) or appear within an aggregation"; } if (!variablesSingle.IsEmpty()) { message += ", ensure that singleton variables (variables " + single + ") are not accessed via index"; } throw new ExprValidationPropertyException(message, e); } }
public static ExprNode ValidateSimpleGetSubtree( ExprNodeOrigin origin, ExprNode expression, EventType optionalEventType, bool allowBindingConsumption, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { ExprNodeUtilityValidate.ValidatePlainExpression(origin, expression); StreamTypeServiceImpl streamTypes; if (optionalEventType != null) { streamTypes = new StreamTypeServiceImpl(optionalEventType, null, true); } else { streamTypes = new StreamTypeServiceImpl(false); } var validationContext = new ExprValidationContextBuilder(streamTypes, statementRawInfo, services) .WithAllowBindingConsumption(allowBindingConsumption) .Build(); return ExprNodeUtilityValidate.GetValidatedSubtree(origin, expression, validationContext); }
private IList<StmtClassForgeableFactory> ValidateContextDetail( ContextSpec contextSpec, int nestingLevel, CreateContextValidationEnv validationEnv) { ISet<string> eventTypesReferenced = new HashSet<string>(); IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); if (contextSpec is ContextSpecKeyed) { var segmented = (ContextSpecKeyed) contextSpec; IDictionary<string, EventType> asNames = new Dictionary<string, EventType>(); var partitionHasNameAssignment = false; Type[] getterTypes = null; foreach (var partition in segmented.Items) { Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> pair = CompilePartitionedFilterSpec( partition.FilterSpecRaw, eventTypesReferenced, validationEnv); FilterSpecCompiled filterSpecCompiled = pair.First; additionalForgeables.AddAll(pair.Second); partition.FilterSpecCompiled = filterSpecCompiled; var getters = new EventPropertyGetterSPI[partition.PropertyNames.Count]; var serdes = new DataInputOutputSerdeForge[partition.PropertyNames.Count]; var eventType = (EventTypeSPI) filterSpecCompiled.FilterForEventType; getterTypes = new Type[partition.PropertyNames.Count]; for (var i = 0; i < partition.PropertyNames.Count; i++) { var propertyName = partition.PropertyNames[i]; var getter = eventType.GetGetterSPI(propertyName); if (getter == null) { throw new ExprValidationException( "For context '" + validationEnv.ContextName + "' property name '" + propertyName + "' not found on type " + eventType.Name); } getters[i] = getter; getterTypes[i] = eventType.GetPropertyType(propertyName); serdes[i] = validationEnv.Services.SerdeResolver.SerdeForFilter( getterTypes[i], validationEnv.StatementRawInfo); } partition.Getters = getters; partition.LookupableSerdes = serdes; if (partition.AliasName != null) { partitionHasNameAssignment = true; ValidateAsName(asNames, partition.AliasName, filterSpecCompiled.FilterForEventType); } } // plan multi-key, make sure we use the same multikey for all items MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( getterTypes, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); foreach (ContextSpecKeyedItem partition in segmented.Items) { partition.KeyMultiKey = multiKeyPlan.ClassRef; } segmented.MultiKeyClassRef = multiKeyPlan.ClassRef; if (segmented.OptionalInit != null) { asNames.Clear(); foreach (var initCondition in segmented.OptionalInit) { ContextDetailMatchPair pair = ValidateRewriteContextCondition( true, nestingLevel, initCondition, eventTypesReferenced, new MatchEventSpec(), new EmptySet<string>(), validationEnv); additionalForgeables.AddAll(pair.AdditionalForgeables); var filterForType = initCondition.FilterSpecCompiled.FilterForEventType; var found = false; foreach (var partition in segmented.Items) { if (partition.FilterSpecCompiled.FilterForEventType == filterForType) { found = true; break; } } if (!found) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that all of the event types that are listed in the initialized-by also appear in the partition-by, type '" + filterForType.Name + "' is not one of the types listed in partition-by"); } if (initCondition.OptionalFilterAsName != null) { if (partitionHasNameAssignment) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that either partition-by or initialized-by assign stream names, but not both"); } ValidateAsName(asNames, initCondition.OptionalFilterAsName, filterForType); } } } if (segmented.OptionalTermination != null) { var matchEventSpec = new MatchEventSpec(); var allTags = new LinkedHashSet<string>(); foreach (var partition in segmented.Items) { if (partition.AliasName != null) { allTags.Add(partition.AliasName); var eventType = partition.FilterSpecCompiled.FilterForEventType; matchEventSpec.TaggedEventTypes[partition.AliasName] = new Pair<EventType,string>( eventType, partition.FilterSpecRaw.EventTypeName); var serdeForgeables = SerdeEventTypeUtility.Plan( eventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (segmented.OptionalInit != null) { foreach (var initCondition in segmented.OptionalInit) { if (initCondition.OptionalFilterAsName != null) { allTags.Add(initCondition.OptionalFilterAsName); matchEventSpec.TaggedEventTypes.Put( initCondition.OptionalFilterAsName, new Pair<EventType, string>( initCondition.FilterSpecCompiled.FilterForEventType, initCondition.FilterSpecRaw.EventTypeName)); } } } var endCondition = ValidateRewriteContextCondition( false, nestingLevel, segmented.OptionalTermination, eventTypesReferenced, matchEventSpec, allTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); segmented.OptionalTermination = endCondition.Condition; } } else if (contextSpec is ContextSpecCategory) { // compile filter var category = (ContextSpecCategory) contextSpec; ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var raw = new FilterStreamSpecRaw( category.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.CompileFilter( raw, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); category.FilterSpecCompiled = result.FilterSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); // compile expressions foreach (var item in category.Items) { ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var filterSpecRaw = new FilterSpecRaw( category.FilterSpecRaw.EventTypeName, Collections.SingletonList(item.Expression), null); var rawExpr = new FilterStreamSpecRaw( filterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDescItems = StreamSpecCompiler.CompileFilter( rawExpr, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDescItems.StreamSpecCompiled; additionalForgeables.AddAll(compiledDescItems.AdditionalForgeables); compiled.FilterSpecCompiled.TraverseFilterBooleanExpr( node => validationEnv.FilterBooleanExpressions.Add(node)); item.FilterPlan = compiled.FilterSpecCompiled.Parameters; } } else if (contextSpec is ContextSpecHash) { var hashed = (ContextSpecHash) contextSpec; foreach (var hashItem in hashed.Items) { var raw = new FilterStreamSpecRaw( hashItem.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); ValidateNotTable(hashItem.FilterSpecRaw.EventTypeName, validationEnv.Services); var compiledDesc = StreamSpecCompiler.Compile( raw, eventTypesReferenced, false, false, true, false, null, 0, validationEnv.StatementRawInfo, validationEnv.Services); additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); hashItem.FilterSpecCompiled = result.FilterSpecCompiled; // validate parameters var streamTypes = new StreamTypeServiceImpl( result.FilterSpecCompiled.FilterForEventType, null, true); var validationContext = new ExprValidationContextBuilder( streamTypes, validationEnv.StatementRawInfo, validationEnv.Services) .WithIsFilterExpression(true) .Build(); ExprNodeUtilityValidate.Validate( ExprNodeOrigin.CONTEXT, Collections.SingletonList(hashItem.Function), validationContext); } } else if (contextSpec is ContextSpecInitiatedTerminated) { var def = (ContextSpecInitiatedTerminated) contextSpec; var startCondition = ValidateRewriteContextCondition( true, nestingLevel, def.StartCondition, eventTypesReferenced, new MatchEventSpec(), new LinkedHashSet<string>(), validationEnv); additionalForgeables.AddAll(startCondition.AdditionalForgeables); var endCondition = ValidateRewriteContextCondition( false, nestingLevel, def.EndCondition, eventTypesReferenced, startCondition.Matches, startCondition.AllTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); def.StartCondition = startCondition.Condition; def.EndCondition = endCondition.Condition; if (def.DistinctExpressions != null) { if (!(startCondition.Condition is ContextSpecConditionFilter)) { throw new ExprValidationException( "Distinct-expressions require a stream as the initiated-by condition"); } var distinctExpressions = def.DistinctExpressions; if (distinctExpressions.Length == 0) { throw new ExprValidationException("Distinct-expressions have not been provided"); } var filter = (ContextSpecConditionFilter) startCondition.Condition; if (filter.OptionalFilterAsName == null) { throw new ExprValidationException( "Distinct-expressions require that a stream name is assigned to the stream using 'as'"); } var types = new StreamTypeServiceImpl( filter.FilterSpecCompiled.FilterForEventType, filter.OptionalFilterAsName, true); var validationContext = new ExprValidationContextBuilder(types, validationEnv.StatementRawInfo, validationEnv.Services) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < distinctExpressions.Length; i++) { ExprNodeUtilityValidate.ValidatePlainExpression( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i]); distinctExpressions[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i], validationContext); } var multiKeyPlan = MultiKeyPlanner.PlanMultiKey( distinctExpressions, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); def.DistinctMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } } else if (contextSpec is ContextNested) { var nested = (ContextNested) contextSpec; var level = 0; ISet<string> namesUsed = new HashSet<string>(); namesUsed.Add(validationEnv.ContextName); foreach (var nestedContext in nested.Contexts) { if (namesUsed.Contains(nestedContext.ContextName)) { throw new ExprValidationException( "Context by name '" + nestedContext.ContextName + "' has already been declared within nested context '" + validationEnv.ContextName + "'"); } namesUsed.Add(nestedContext.ContextName); var forgeables = ValidateContextDetail(nestedContext.ContextDetail, level, validationEnv); additionalForgeables.AddAll(forgeables); level++; } } else { throw new IllegalStateException("Unrecognized context detail " + contextSpec); } return additionalForgeables; }
public override IList<StmtClassForgeableFactory> Validate( StreamTypeService typeService, StatementBaseInfo @base, StatementCompileTimeServices services) { // validate and visit var validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); var visitor = new ExprNodeIdentifierAndStreamRefVisitor(true); var validatedInputParameters = new List<ExprNode>(); foreach (var exprNode in methodStreamSpec.Expressions) { var validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.METHODINVJOIN, exprNode, validationContext); validatedInputParameters.Add(validated); validated.Accept(visitor); } // determine required streams foreach (ExprNodePropOrStreamDesc @ref in visitor.Refs) { SubordinateStreams.Add(@ref.StreamNum); } // class-based evaluation MethodInfo targetMethod = null; if (metadata.MethodProviderClass != null) { // resolve actual method to use ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler { ProcHandle = e => { if (methodStreamSpec.Expressions.Count == 0) { return new ExprValidationException( "Method footprint does not match the number or type of expression parameters, expecting no parameters in method: " + e.Message); } var resultTypes = ExprNodeUtilityQuery.GetExprResultTypes(validatedInputParameters); return new ExprValidationException( "Method footprint does not match the number or type of expression parameters, expecting a method where parameters are typed '" + TypeHelper.GetParameterAsString(resultTypes) + "': " + e.Message); } }; var desc = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream( metadata.MethodProviderClass.FullName, metadata.IsStaticMethod ? null : metadata.MethodProviderClass, methodStreamSpec.MethodName, validatedInputParameters, false, null, handler, methodStreamSpec.MethodName, @base.StatementRawInfo, services); InputParamEvaluators = desc.ChildForges; targetMethod = desc.ReflectionMethod; } else { // script-based evaluation InputParamEvaluators = ExprNodeUtilityQuery.GetForges(ExprNodeUtilityQuery.ToArray(validatedInputParameters)); } // plan multikey MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver); MultiKeyClassRef = multiKeyPlan.ClassRef; Pair<MethodTargetStrategyForge, MethodConversionStrategyForge> strategies = PollExecStrategyPlanner.Plan(metadata, targetMethod, EventType); target = strategies.First; conversion = strategies.Second; return multiKeyPlan.MultiKeyForgeables; }
public static SelectExprProcessorDescriptor GetProcessor( SelectProcessorArgs args, InsertIntoDesc insertIntoDesc, bool withSubscriber) { IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); SelectExprProcessorWInsertTarget synthetic = GetProcessorInternal(args, insertIntoDesc); additionalForgeables.AddAll(synthetic.AdditionalForgeables); // plan serdes for variant event types if (synthetic.InsertIntoTargetType is VariantEventType || synthetic.InsertIntoTargetType is WrapperEventType && (((WrapperEventType) synthetic.InsertIntoTargetType).UnderlyingEventType is VariantEventType)) { var serdeForgeables = SerdeEventTypeUtility.Plan( synthetic.Forge.ResultEventType, args.StatementRawInfo, args.CompileTimeServices.SerdeEventTypeRegistry, args.CompileTimeServices.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); foreach (EventType eventType in args.TypeService.EventTypes) { serdeForgeables = SerdeEventTypeUtility.Plan( eventType, args.StatementRawInfo, args.CompileTimeServices.SerdeEventTypeRegistry, args.CompileTimeServices.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (args.IsFireAndForget || !withSubscriber) { return new SelectExprProcessorDescriptor(new SelectSubscriberDescriptor(), synthetic.Forge, additionalForgeables); } // Handle for-clause delivery contract checking ExprNode[] groupedDeliveryExpr = null; MultiKeyClassRef groupedDeliveryMultiKey = null; var forDelivery = false; if (args.ForClauseSpec != null) { foreach (var item in args.ForClauseSpec.Clauses) { if (item.Keyword == null) { throw new ExprValidationException( "Expected any of the " + EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() + " for-clause keywords after reserved keyword 'for'"); } try { var keyword = EnumHelper.Parse<ForClauseKeyword>(item.Keyword); if (keyword == ForClauseKeyword.GROUPED_DELIVERY && item.Expressions.IsEmpty()) { throw new ExprValidationException( "The for-clause with the " + ForClauseKeyword.GROUPED_DELIVERY.GetName() + " keyword requires one or more grouping expressions"); } if (keyword == ForClauseKeyword.DISCRETE_DELIVERY && !item.Expressions.IsEmpty()) { throw new ExprValidationException( "The for-clause with the " + ForClauseKeyword.DISCRETE_DELIVERY.GetName() + " keyword does not allow grouping expressions"); } if (forDelivery) { throw new ExprValidationException( "The for-clause with delivery keywords may only occur once in a statement"); } } catch (ExprValidationException) { throw; } catch (EPException) { throw; } catch (Exception) { throw new ExprValidationException( "Expected any of the " + EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() + " for-clause keywords after reserved keyword 'for'"); } StreamTypeService type = new StreamTypeServiceImpl(synthetic.Forge.ResultEventType, null, false); groupedDeliveryExpr = new ExprNode[item.Expressions.Count]; var validationContext = new ExprValidationContextBuilder( type, args.StatementRawInfo, args.CompileTimeServices) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < item.Expressions.Count; i++) { groupedDeliveryExpr[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.FORCLAUSE, item.Expressions[i], validationContext); } forDelivery = true; MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( groupedDeliveryExpr, false, args.StatementRawInfo, args.SerdeResolver); groupedDeliveryMultiKey = multiKeyPlan.ClassRef; additionalForgeables = multiKeyPlan.MultiKeyForgeables; } if (groupedDeliveryExpr != null && groupedDeliveryExpr.Length == 0) { groupedDeliveryExpr = null; } } var allowSubscriber = args.CompileTimeServices.Configuration.Compiler.ByteCode.IsAllowSubscriber; SelectSubscriberDescriptor descriptor; SelectExprProcessorForge forge; if (allowSubscriber) { BindProcessorForge bindProcessor = new BindProcessorForge( synthetic.Forge, args.SelectionList, args.TypeService.EventTypes, args.TypeService.StreamNames, args.TableCompileTimeResolver); descriptor = new SelectSubscriberDescriptor( bindProcessor.ExpressionTypes, bindProcessor.ColumnNamesAssigned, forDelivery, groupedDeliveryExpr, groupedDeliveryMultiKey); forge = new BindSelectExprProcessorForge(synthetic.Forge, bindProcessor); } else { descriptor = new SelectSubscriberDescriptor(); forge = new ListenerOnlySelectExprProcessorForge(synthetic.Forge); } return new SelectExprProcessorDescriptor(descriptor, forge, additionalForgeables); }
public static OnTriggerPlanValidationResult ValidateOnTriggerPlan( EventType namedWindowOrTableType, OnTriggerWindowDesc onTriggerDesc, StreamSpecCompiled streamSpec, OnTriggerActivatorDesc activatorResult, IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation, StatementBaseInfo @base, StatementCompileTimeServices services) { var zeroStreamAliasName = onTriggerDesc.OptionalAsName; if (zeroStreamAliasName == null) { zeroStreamAliasName = "stream_0"; } var streamName = streamSpec.OptionalStreamName; if (streamName == null) { streamName = "stream_1"; } var namedWindowTypeName = onTriggerDesc.WindowName; // Materialize sub-select views // 0 - named window stream // 1 - arriving stream // 2 - initial value before update string[] subselectStreamNames = {zeroStreamAliasName, streamSpec.OptionalStreamName}; EventType[] subselectEventTypes = {namedWindowOrTableType, activatorResult.ActivatorResultEventType}; string[] subselectEventTypeNames = {namedWindowTypeName, activatorResult.TriggerEventTypeName}; var subselectForges = SubSelectHelperForgePlanner.PlanSubSelect( @base, subselectActivation, subselectStreamNames, subselectEventTypes, subselectEventTypeNames, services); var typeService = new StreamTypeServiceImpl( new[] {namedWindowOrTableType, activatorResult.ActivatorResultEventType}, new[] {zeroStreamAliasName, streamName}, new[] {false, true}, true, false); // allow "initial" as a prefix to properties StreamTypeServiceImpl assignmentTypeService; if (zeroStreamAliasName.Equals(INITIAL_VALUE_STREAM_NAME) || streamName.Equals(INITIAL_VALUE_STREAM_NAME)) { assignmentTypeService = typeService; } else { assignmentTypeService = new StreamTypeServiceImpl( new[] {namedWindowOrTableType, activatorResult.ActivatorResultEventType, namedWindowOrTableType}, new[] {zeroStreamAliasName, streamName, INITIAL_VALUE_STREAM_NAME}, new[] {false, true, true}, false, false); assignmentTypeService.IsStreamZeroUnambigous = true; } if (onTriggerDesc is OnTriggerWindowUpdateDesc) { var updateDesc = (OnTriggerWindowUpdateDesc) onTriggerDesc; var validationContext = new ExprValidationContextBuilder( assignmentTypeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); foreach (var assignment in updateDesc.Assignments) { var validated = ExprNodeUtilityValidate.GetValidatedAssignment(assignment, validationContext); assignment.Expression = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations( validated, "Aggregation functions may not be used within an on-update-clause"); } } if (onTriggerDesc is OnTriggerMergeDesc) { var mergeDesc = (OnTriggerMergeDesc) onTriggerDesc; ValidateMergeDesc( mergeDesc, namedWindowOrTableType, zeroStreamAliasName, activatorResult.ActivatorResultEventType, streamName, @base.StatementRawInfo, services); } // validate join expression var validatedJoin = ValidateJoinNamedWindow( ExprNodeOrigin.WHERE, @base.StatementSpec.Raw.WhereClause, namedWindowOrTableType, zeroStreamAliasName, namedWindowTypeName, activatorResult.ActivatorResultEventType, streamName, activatorResult.TriggerEventTypeName, null, @base.StatementRawInfo, services); // validate filter, output rate limiting EPStatementStartMethodHelperValidate.ValidateNodes( @base.StatementSpec.Raw, typeService, null, @base.StatementRawInfo, services); // Construct a processor for results; for use in on-select to process selection results // Use a wildcard select if the select-clause is empty, such as for on-delete. // For on-select the select clause is not empty. if (@base.StatementSpec.SelectClauseCompiled.SelectExprList.Length == 0) { @base.StatementSpec.SelectClauseCompiled.WithSelectExprList(new SelectClauseElementWildcard()); } var resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.GetProcessorPrototype( new ResultSetSpec(@base.StatementSpec), typeService, null, new bool[0], true, @base.ContextPropertyRegistry, false, true, @base.StatementRawInfo, services); // plan table access var tableAccessForges = ExprTableEvalHelperPlan.PlanTableAccess(@base.StatementSpec.TableAccessNodes); return new OnTriggerPlanValidationResult( subselectForges, tableAccessForges, resultSetProcessorPrototype, validatedJoin, zeroStreamAliasName); }
public StmtForgeMethodResult Make( string @namespace, string classPostfix, StatementCompileTimeServices services) { var statementSpec = @base.StatementSpec; // determine context var contextName = @base.StatementSpec.Raw.OptionalContextName; if (contextName != null) { throw new ExprValidationException("Update IStream is not supported in conjunction with a context"); } var streamSpec = statementSpec.StreamSpecs[0]; var updateSpec = statementSpec.Raw.UpdateDesc; string triggereventTypeName; EventType streamEventType; if (streamSpec is FilterStreamSpecCompiled) { var filterStreamSpec = (FilterStreamSpecCompiled) streamSpec; triggereventTypeName = filterStreamSpec.FilterSpecCompiled.FilterForEventTypeName; streamEventType = filterStreamSpec.FilterSpecCompiled.FilterForEventType; } else if (streamSpec is NamedWindowConsumerStreamSpec) { var namedSpec = (NamedWindowConsumerStreamSpec) streamSpec; streamEventType = namedSpec.NamedWindow.EventType; triggereventTypeName = streamEventType.Name; } else if (streamSpec is TableQueryStreamSpec) { throw new ExprValidationException("Tables cannot be used in an update-istream statement"); } else { throw new ExprValidationException("Unknown stream specification streamEventType: " + streamSpec); } // determine a stream name var streamName = triggereventTypeName; if (updateSpec.OptionalStreamName != null) { streamName = updateSpec.OptionalStreamName; } StreamTypeService typeService = new StreamTypeServiceImpl( new[] {streamEventType}, new[] {streamName}, new[] {true}, false, false); // create subselect information IList<FilterSpecCompiled> filterSpecCompileds = new List<FilterSpecCompiled>(); IList<NamedWindowConsumerStreamSpec> namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>(); var subselectActivation = SubSelectHelperActivations.CreateSubSelectActivation( filterSpecCompileds, namedWindowConsumers, @base, services); // handle subselects var subselectForges = SubSelectHelperForgePlanner.PlanSubSelect( @base, subselectActivation, typeService.StreamNames, typeService.EventTypes, new[] {triggereventTypeName}, services); var validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services).Build(); foreach (var assignment in updateSpec.Assignments) { var validated = ExprNodeUtilityValidate.GetValidatedAssignment(assignment, validationContext); assignment.Expression = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations( validated, "Aggregation functions may not be used within an update-clause"); } if (updateSpec.OptionalWhereClause != null) { var validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.WHERE, updateSpec.OptionalWhereClause, validationContext); updateSpec.OptionalWhereClause = validated; EPStatementStartMethodHelperValidate.ValidateNoAggregations( validated, "Aggregation functions may not be used within an update-clause"); } // build route information var routerDesc = InternalEventRouterDescFactory.GetValidatePreprocessing( streamEventType, updateSpec, @base.StatementRawInfo.Annotations); var statementFieldsClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementFields), classPostfix); var packageScope = new CodegenNamespaceScope( @namespace, statementFieldsClassName, services.IsInstrumented); var aiFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(StatementAIFactoryProvider), classPostfix); var forge = new StatementAgentInstanceFactoryUpdateForge(routerDesc, subselectForges); var aiFactoryForgable = new StmtClassForgableAIFactoryProviderUpdate( aiFactoryProviderClassName, packageScope, forge); var selectSubscriberDescriptor = new SelectSubscriberDescriptor( new[] {streamEventType.UnderlyingType}, new[] {"*"}, false, null); var informationals = StatementInformationalsUtil.GetInformationals( @base, filterSpecCompileds, Collections.GetEmptyList<ScheduleHandleCallbackProvider>(), Collections.GetEmptyList<NamedWindowConsumerStreamSpec>(), false, selectSubscriberDescriptor, packageScope, services); var statementProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix); var stmtProvider = new StmtClassForgableStmtProvider( aiFactoryProviderClassName, statementProviderClassName, informationals, packageScope); IList<StmtClassForgable> forgables = new List<StmtClassForgable>(); forgables.Add(aiFactoryForgable); forgables.Add(stmtProvider); forgables.Add(new StmtClassForgableStmtFields(statementFieldsClassName, packageScope, 0)); return new StmtForgeMethodResult( forgables, filterSpecCompileds, Collections.GetEmptyList<ScheduleHandleCallbackProvider>(), namedWindowConsumers, Collections.GetEmptyList<FilterSpecParamExprNodeForge>()); }
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); } }
private static AggregationServiceForgeDesc[] PlanAggregations( IList<ExprAggregateNode> measureAggregateExprNodes, StreamTypeService compositeTypeServiceMeasure, string[] allStreamNames, EventType[] allTypes, IOrderedDictionary<int, string> streamVariables, ISet<string> variablesMultiple, StatementBaseInfo @base, StatementCompileTimeServices services) { IDictionary<int, IList<ExprAggregateNode>> measureExprAggNodesPerStream = new Dictionary<int, IList<ExprAggregateNode>>(); foreach (var aggregateNode in measureAggregateExprNodes) { // validate node and params var count = 0; var visitor = new ExprNodeIdentifierVisitor(true); var isIStreamOnly = new bool[allStreamNames.Length]; var typeServiceAggregateMeasure = new StreamTypeServiceImpl( allTypes, allStreamNames, isIStreamOnly, false, true); var validationContext = new ExprValidationContextBuilder(typeServiceAggregateMeasure, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); aggregateNode.ValidatePositionals(validationContext); if (aggregateNode.OptionalLocalGroupBy != null) { throw new ExprValidationException( "Match-recognize does not allow aggregation functions to specify a group-by"); } foreach (var child in aggregateNode.ChildNodes) { var validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGMEASURE, child, validationContext); validated.Accept(visitor); aggregateNode.SetChildNode(count++, new ExprNodeValidated(validated)); } // verify properties used within the aggregation ISet<int> aggregatedStreams = new HashSet<int>(); foreach (var pair in visitor.ExprProperties) { aggregatedStreams.Add(pair.First); } int? multipleVarStream = null; foreach (var streamNumAggregated in aggregatedStreams) { var variable = streamVariables.Get(streamNumAggregated); if (variablesMultiple.Contains(variable)) { if (multipleVarStream == null) { multipleVarStream = streamNumAggregated; continue; } throw new ExprValidationException( "Aggregation functions in the measure-clause must only refer to properties of exactly one group variable returning multiple events"); } } if (multipleVarStream == null) { throw new ExprValidationException( "Aggregation functions in the measure-clause must refer to one or more properties of exactly one group variable returning multiple events"); } var aggNodesForStream = measureExprAggNodesPerStream.Get(multipleVarStream.Value); if (aggNodesForStream == null) { aggNodesForStream = new List<ExprAggregateNode>(); measureExprAggNodesPerStream.Put(multipleVarStream.Value, aggNodesForStream); } aggNodesForStream.Add(aggregateNode); } // validate aggregation itself foreach (var entry in measureExprAggNodesPerStream) { foreach (var aggregateNode in entry.Value) { var validationContext = new ExprValidationContextBuilder( compositeTypeServiceMeasure, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .WithMemberName(new ExprValidationMemberNameQualifiedRowRecogAgg(entry.Key)) .Build(); aggregateNode.Validate(validationContext); } } // get aggregation service per variable var aggServices = new AggregationServiceForgeDesc[allStreamNames.Length]; var declareds = Arrays.AsList(@base.StatementSpec.DeclaredExpressions); foreach (var entry in measureExprAggNodesPerStream) { EventType[] typesPerStream = {allTypes[entry.Key]}; AggregationServiceForgeDesc desc = AggregationServiceFactoryFactory.GetService( entry.Value, EmptyDictionary<ExprNode, string>.Instance, declareds, new ExprNode[0], null, EmptyList<ExprAggregateNode>.Instance, EmptyList<ExprAggregateNode>.Instance, EmptyList<ExprAggregateNodeGroupKey>.Instance, false, @base.StatementRawInfo.Annotations, services.VariableCompileTimeResolver, true, null, null, typesPerStream, null, @base.ContextName, null, services.TableCompileTimeResolver, false, true, false, services.ImportServiceCompileTime, @base.StatementRawInfo, services.SerdeResolver); aggServices[entry.Key] = desc; } return aggServices; }
public static RowRecogPlan ValidateAndPlan( IContainer container, EventType parentEventType, bool unbound, StatementBaseInfo @base, StatementCompileTimeServices services) { var statementRawInfo = @base.StatementRawInfo; var matchRecognizeSpec = @base.StatementSpec.Raw.MatchRecognizeSpec; var annotations = statementRawInfo.Annotations; var iterateOnly = HintEnum.ITERATE_ONLY.GetHint(annotations) != null; var additionalForgeables = new List<StmtClassForgeableFactory>(); // Expanded pattern already there RowRecogExprNode expandedPatternNode = matchRecognizeSpec.Pattern; // Determine single-row and multiple-row variables var variablesSingle = new LinkedHashSet<string>(); var variablesMultiple = new LinkedHashSet<string>(); RowRecogHelper.RecursiveInspectVariables(expandedPatternNode, false, variablesSingle, variablesMultiple); // each variable gets associated with a stream number (multiple-row variables as well to hold the current event for the expression). var streamNum = 0; var variableStreams = new LinkedHashMap<string, Pair<int, bool>>(); foreach (var variableSingle in variablesSingle) { variableStreams.Put(variableSingle, new Pair<int, bool>(streamNum, false)); streamNum++; } foreach (var variableMultiple in variablesMultiple) { variableStreams.Put(variableMultiple, new Pair<int, bool>(streamNum, true)); streamNum++; } // mapping of stream to variable var streamVariables = new OrderedListDictionary<int, string>(); foreach (var entry in variableStreams) { streamVariables.Put(entry.Value.First, entry.Key); } // determine visibility rules var visibility = RowRecogHelper.DetermineVisibility(expandedPatternNode); // assemble all single-row variables for expression validation var allStreamNames = new string[variableStreams.Count]; var allTypes = new EventType[variableStreams.Count]; streamNum = 0; foreach (var variableSingle in variablesSingle) { allStreamNames[streamNum] = variableSingle; allTypes[streamNum] = parentEventType; streamNum++; } foreach (var variableMultiple in variablesMultiple) { allStreamNames[streamNum] = variableMultiple; allTypes[streamNum] = parentEventType; streamNum++; } // determine type service for use with DEFINE // validate each DEFINE clause expression ISet<string> definedVariables = new HashSet<string>(); IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>(); var isExprRequiresMultimatchState = new bool[variableStreams.Count]; var previousNodes = new OrderedListDictionary<int, IList<ExprPreviousMatchRecognizeNode>>(); for (var defineIndex = 0; defineIndex < matchRecognizeSpec.Defines.Count; defineIndex++) { MatchRecognizeDefineItem defineItem = matchRecognizeSpec.Defines[defineIndex]; if (definedVariables.Contains(defineItem.Identifier)) { throw new ExprValidationException( "Variable '" + defineItem.Identifier + "' has already been defined"); } definedVariables.Add(defineItem.Identifier); // stream-type visibilities handled here var typeServiceDefines = BuildDefineStreamTypeServiceDefine( defineIndex, variableStreams, defineItem, visibility, parentEventType, statementRawInfo, services); var exprNodeResult = HandlePreviousFunctions(defineItem.Expression, previousNodes); var validationContext = new ExprValidationContextBuilder(typeServiceDefines, statementRawInfo, services) .WithAllowBindingConsumption(true) .WithDisablePropertyExpressionEventCollCache(true) .Build(); ExprNode validated; try { // validate validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGDEFINE, exprNodeResult, validationContext); // check aggregates defineItem.Expression = validated; ExprAggregateNodeUtil.GetAggregatesBottomUp(validated, aggregateNodes); if (!aggregateNodes.IsEmpty()) { throw new ExprValidationException("An aggregate function may not appear in a DEFINE clause"); } } catch (ExprValidationException ex) { throw new ExprValidationException( "Failed to validate condition expression for variable '" + defineItem.Identifier + "': " + ex.Message, ex); } // determine access to event properties from multi-matches var visitor = new ExprNodeStreamRequiredVisitor(); validated.Accept(visitor); var streamsRequired = visitor.StreamsRequired; foreach (var streamRequired in streamsRequired) { if (streamRequired >= variableStreams.Count) { var streamNumIdent = variableStreams.Get(defineItem.Identifier).First; isExprRequiresMultimatchState[streamNumIdent] = true; break; } } } var defineAsksMultimatches = CollectionUtil.IsAnySet(isExprRequiresMultimatchState); // determine type service for use with MEASURE IDictionary<string, object> measureTypeDef = new LinkedHashMap<string, object>(); foreach (var variableSingle in variablesSingle) { measureTypeDef.Put(variableSingle, parentEventType); } foreach (var variableMultiple in variablesMultiple) { measureTypeDef.Put(variableMultiple, new[] {parentEventType}); } var compositeTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogCompositeName; var compositeTypeMetadata = new EventTypeMetadata( compositeTypeName, @base.ModuleName, EventTypeTypeClass.MATCHRECOGDERIVED, EventTypeApplicationType.OBJECTARR, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var compositeEventType = BaseNestableEventUtil.MakeOATypeCompileTime( compositeTypeMetadata, measureTypeDef, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(compositeEventType); StreamTypeService compositeTypeServiceMeasure = new StreamTypeServiceImpl(compositeEventType, "MATCH_RECOGNIZE", true); // find MEASURE clause aggregations var measureReferencesMultivar = false; IList<ExprAggregateNode> measureAggregateExprNodes = new List<ExprAggregateNode>(); foreach (var measureItem in matchRecognizeSpec.Measures) { ExprAggregateNodeUtil.GetAggregatesBottomUp(measureItem.Expr, measureAggregateExprNodes); } AggregationServiceForgeDesc[] aggregationServices = null; if (!measureAggregateExprNodes.IsEmpty()) { aggregationServices = PlanAggregations( measureAggregateExprNodes, compositeTypeServiceMeasure, allStreamNames, allTypes, streamVariables, variablesMultiple, @base, services); foreach (AggregationServiceForgeDesc svc in aggregationServices) { if (svc != null) { additionalForgeables.AddAll(svc.AdditionalForgeables); } } } // validate each MEASURE clause expression IDictionary<string, object> rowTypeDef = new LinkedHashMap<string, object>(); var streamRefVisitor = new ExprNodeStreamUseCollectVisitor(); foreach (var measureItem in matchRecognizeSpec.Measures) { if (measureItem.Name == null) { throw new ExprValidationException( "The measures clause requires that each expression utilizes the AS keyword to assign a column name"); } var validated = ValidateMeasureClause( measureItem.Expr, compositeTypeServiceMeasure, variablesMultiple, variablesSingle, statementRawInfo, services); measureItem.Expr = validated; rowTypeDef.Put(measureItem.Name, validated.Forge.EvaluationType); validated.Accept(streamRefVisitor); } // Determine if any of the multi-var streams are referenced in the measures (non-aggregated only) foreach (var @ref in streamRefVisitor.Referenced) { var rootPropName = @ref.RootPropertyNameIfAny; if (rootPropName != null) { if (variablesMultiple.Contains(rootPropName)) { measureReferencesMultivar = true; break; } } var streamRequired = @ref.StreamReferencedIfAny; if (streamRequired != null) { var streamVariable = streamVariables.Get(streamRequired.Value); if (streamVariable != null) { var def = variableStreams.Get(streamVariable); if (def != null && def.Second) { measureReferencesMultivar = true; break; } } } } var collectMultimatches = measureReferencesMultivar || defineAsksMultimatches; // create rowevent type var rowTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogRowName; var rowTypeMetadata = new EventTypeMetadata( rowTypeName, @base.ModuleName, EventTypeTypeClass.MATCHRECOGDERIVED, EventTypeApplicationType.MAP, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var rowEventType = BaseNestableEventUtil.MakeMapTypeCompileTime( rowTypeMetadata, rowTypeDef, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(rowEventType); // validate partition-by expressions, if any ExprNode[] partitionBy; MultiKeyClassRef partitionMultiKey; if (!matchRecognizeSpec.PartitionByExpressions.IsEmpty()) { StreamTypeService typeServicePartition = new StreamTypeServiceImpl( parentEventType, "MATCH_RECOGNIZE_PARTITION", true); IList<ExprNode> validated = new List<ExprNode>(); var validationContext = new ExprValidationContextBuilder(typeServicePartition, statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); foreach (var partitionExpr in matchRecognizeSpec.PartitionByExpressions) { validated.Add( ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGPARTITION, partitionExpr, validationContext)); } matchRecognizeSpec.PartitionByExpressions = validated; partitionBy = ExprNodeUtilityQuery.ToArray(validated); MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(partitionBy, false, @base.StatementRawInfo, services.SerdeResolver); partitionMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } else { partitionBy = null; partitionMultiKey = null; } // validate interval if present if (matchRecognizeSpec.Interval != null) { var validationContext = new ExprValidationContextBuilder(new StreamTypeServiceImpl(false), statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); var validated = (ExprTimePeriod) ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGINTERVAL, matchRecognizeSpec.Interval.TimePeriodExpr, validationContext); matchRecognizeSpec.Interval.TimePeriodExpr = validated; } // compile variable definition expressions IDictionary<string, ExprNode> variableDefinitions = new Dictionary<string, ExprNode>(); foreach (var defineItem in matchRecognizeSpec.Defines) { variableDefinitions.Put(defineItem.Identifier, defineItem.Expression); } // create evaluators var columnNames = new string[matchRecognizeSpec.Measures.Count]; var columnForges = new ExprNode[matchRecognizeSpec.Measures.Count]; var count = 0; foreach (var measureItem in matchRecognizeSpec.Measures) { columnNames[count] = measureItem.Name; columnForges[count] = measureItem.Expr; count++; } // build states var strand = RowRecogHelper.BuildStartStates( expandedPatternNode, variableDefinitions, variableStreams, isExprRequiresMultimatchState); var startStates = strand.StartStates.ToArray(); RowRecogNFAStateForge[] allStates = strand.AllStates.ToArray(); if (Log.IsInfoEnabled) { Log.Info("NFA tree:\n" + RowRecogNFAViewUtil.Print(startStates)); } // determine names of multimatching variables string[] multimatchVariablesArray; int[] multimatchStreamNumToVariable; int[] multimatchVariableToStreamNum; if (variablesSingle.Count == variableStreams.Count) { multimatchVariablesArray = new string[0]; multimatchStreamNumToVariable = new int[0]; multimatchVariableToStreamNum = new int[0]; } else { multimatchVariablesArray = new string[variableStreams.Count - variablesSingle.Count]; multimatchVariableToStreamNum = new int[multimatchVariablesArray.Length]; multimatchStreamNumToVariable = new int[variableStreams.Count]; CompatExtensions.Fill(multimatchStreamNumToVariable, -1); count = 0; foreach (var entry in variableStreams) { if (entry.Value.Second) { var index = count; multimatchVariablesArray[index] = entry.Key; multimatchVariableToStreamNum[index] = entry.Value.First; multimatchStreamNumToVariable[entry.Value.First] = index; count++; } } } var numEventsEventsPerStreamDefine = defineAsksMultimatches ? variableStreams.Count + 1 : variableStreams.Count; // determine interval-or-terminated var orTerminated = matchRecognizeSpec.Interval != null && matchRecognizeSpec.Interval.IsOrTerminated; TimePeriodComputeForge intervalCompute = null; if (matchRecognizeSpec.Interval != null) { intervalCompute = matchRecognizeSpec.Interval.TimePeriodExpr.TimePeriodComputeForge; } EventType multimatchEventType = null; if (defineAsksMultimatches) { multimatchEventType = GetDefineMultimatchEventType(variableStreams, parentEventType, @base, services); } // determine previous-access indexes and assign "prev" node indexes // Since an expression such as "prior(2, price), prior(8, price)" translates into {2, 8} the relative index is {0, 1}. // Map the expression-supplied index to a relative index int[] previousRandomAccessIndexes = null; if (!previousNodes.IsEmpty()) { previousRandomAccessIndexes = new int[previousNodes.Count]; var countPrev = 0; foreach (var entry in previousNodes) { previousRandomAccessIndexes[countPrev] = entry.Key; foreach (var callback in entry.Value) { callback.AssignedIndex = countPrev; } countPrev++; } } RowRecogDescForge forge = new RowRecogDescForge( parentEventType, rowEventType, compositeEventType, multimatchEventType, multimatchStreamNumToVariable, multimatchVariableToStreamNum, partitionBy, partitionMultiKey, variableStreams, matchRecognizeSpec.Interval != null, iterateOnly, unbound, orTerminated, collectMultimatches, defineAsksMultimatches, numEventsEventsPerStreamDefine, multimatchVariablesArray, startStates, allStates, matchRecognizeSpec.IsAllMatches, matchRecognizeSpec.Skip.Skip, columnForges, columnNames, intervalCompute, previousRandomAccessIndexes, aggregationServices); return new RowRecogPlan(forge, additionalForgeables); }
private ContextDetailMatchPair ValidateRewriteContextCondition( bool isStartCondition, int nestingLevel, ContextSpecCondition endpoint, ISet<string> eventTypesReferenced, MatchEventSpec priorMatches, ISet<string> priorAllTags, CreateContextValidationEnv validationEnv) { if (endpoint is ContextSpecConditionCrontab) { var crontab = (ContextSpecConditionCrontab) endpoint; var forgesPerCrontab = new ExprForge[crontab.Crontabs.Count][]; for (int i = 0; i < crontab.Crontabs.Count; i++) { var item = crontab.Crontabs[i]; var forges = ScheduleExpressionUtil.CrontabScheduleValidate( ExprNodeOrigin.CONTEXTCONDITION, item, false, validationEnv.StatementRawInfo, validationEnv.Services); forgesPerCrontab[i] = forges; } crontab.ForgesPerCrontab = forgesPerCrontab; validationEnv.ScheduleHandleCallbackProviders.Add(crontab); return new ContextDetailMatchPair( crontab, new MatchEventSpec(), new LinkedHashSet<string>(), EmptyList<StmtClassForgeableFactory>.Instance); } if (endpoint is ContextSpecConditionTimePeriod) { var timePeriod = (ContextSpecConditionTimePeriod) endpoint; var validationContext = new ExprValidationContextBuilder( new StreamTypeServiceImpl(false), validationEnv.StatementRawInfo, validationEnv.Services).Build(); ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTCONDITION, timePeriod.TimePeriod, validationContext); if (timePeriod.TimePeriod.IsConstantResult) { if (timePeriod.TimePeriod.EvaluateAsSeconds(null, true, null) < 0) { throw new ExprValidationException( "Invalid negative time period expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(timePeriod.TimePeriod) + "'"); } } validationEnv.ScheduleHandleCallbackProviders.Add(timePeriod); return new ContextDetailMatchPair( timePeriod, new MatchEventSpec(), new LinkedHashSet<string>(), EmptyList<StmtClassForgeableFactory>.Instance); } if (endpoint is ContextSpecConditionPattern) { var pattern = (ContextSpecConditionPattern) endpoint; var matches = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); var validatedDesc = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); return new ContextDetailMatchPair( pattern, validatedDesc.MatchEventSpec, validatedDesc.AllTags, validatedDesc.AdditionalForgeables); } if (endpoint is ContextSpecConditionFilter) { var filter = (ContextSpecConditionFilter) endpoint; ValidateNotTable(filter.FilterSpecRaw.EventTypeName, validationEnv.Services); // compile as filter if there are no prior match to consider if (priorMatches == null || priorMatches.ArrayEventTypes.IsEmpty() && priorMatches.TaggedEventTypes.IsEmpty()) { var rawExpr = new FilterStreamSpecRaw( filter.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.Compile( rawExpr, eventTypesReferenced, false, false, true, false, filter.OptionalFilterAsName, 0, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; filter.FilterSpecCompiled = compiled.FilterSpecCompiled; var matchEventSpec = new MatchEventSpec(); var filterForType = compiled.FilterSpecCompiled.FilterForEventType; var allTags = new LinkedHashSet<string>(); if (filter.OptionalFilterAsName != null) { matchEventSpec.TaggedEventTypes.Put( filter.OptionalFilterAsName, new Pair<EventType, string>(filterForType, rawExpr.RawFilterSpec.EventTypeName)); allTags.Add(filter.OptionalFilterAsName); } validationEnv.FilterSpecCompileds.Add(compiled.FilterSpecCompiled); var serdeForgeables = SerdeEventTypeUtility.Plan( filter.FilterSpecCompiled.FilterForEventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); var allForgeables = compiledDesc.AdditionalForgeables .Concat(serdeForgeables) .ToList(); return new ContextDetailMatchPair(filter, matchEventSpec, allTags, allForgeables); } // compile as pattern if there are prior matches to consider, since this is a type of followed-by relationship EvalForgeNode forgeNode = new EvalFilterForgeNode(validationEnv.Services.IsAttachPatternText, filter.FilterSpecRaw, filter.OptionalFilterAsName, 0); var pattern = new ContextSpecConditionPattern(forgeNode, true, false); var validated = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); return new ContextDetailMatchPair(pattern, validated.MatchEventSpec, validated.AllTags, validated.AdditionalForgeables); } if (endpoint is ContextSpecConditionImmediate || endpoint is ContextSpecConditionNever) { return new ContextDetailMatchPair( endpoint, new MatchEventSpec(), new LinkedHashSet<String>(), EmptyList<StmtClassForgeableFactory>.Instance); } throw new IllegalStateException("Unrecognized endpoint type " + endpoint); }
public static OnTriggerSetPlan HandleSetVariable( string className, CodegenNamespaceScope namespaceScope, string classPostfix, OnTriggerActivatorDesc activatorResult, string optionalStreamName, IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation, OnTriggerSetDesc desc, StatementBaseInfo @base, StatementCompileTimeServices services) { StreamTypeService typeService = new StreamTypeServiceImpl( new[] {activatorResult.ActivatorResultEventType}, new[] {optionalStreamName}, new[] {true}, false, false); var validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); // handle subselects var subselectForges = SubSelectHelperForgePlanner.PlanSubSelect( @base, subselectActivation, new[] {optionalStreamName}, new[] {activatorResult.ActivatorResultEventType}, new[] {activatorResult.TriggerEventTypeName}, services); // validate assignments foreach (var assignment in desc.Assignments) { var validated = ExprNodeUtilityValidate.GetValidatedAssignment(assignment, validationContext); assignment.Expression = validated; } // create read-write logic var variableReadWritePackageForge = new VariableReadWritePackageForge(desc.Assignments, services); // plan table access var tableAccessForges = ExprTableEvalHelperPlan.PlanTableAccess(@base.StatementSpec.TableAccessNodes); // create output event type var eventTypeName = services.EventTypeNameGeneratorStatement.AnonymousTypeName; var eventTypeMetadata = new EventTypeMetadata( eventTypeName, @base.ModuleName, EventTypeTypeClass.STATEMENTOUT, EventTypeApplicationType.MAP, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var eventType = BaseNestableEventUtil.MakeMapTypeCompileTime( eventTypeMetadata, variableReadWritePackageForge.VariableTypes, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(eventType); // Handle output format var defaultSelectAllSpec = new StatementSpecCompiled(); defaultSelectAllSpec.SelectClauseCompiled.WithSelectExprList(new SelectClauseElementWildcard()); defaultSelectAllSpec.Raw.SelectStreamDirEnum = SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH; StreamTypeService streamTypeService = new StreamTypeServiceImpl( new EventType[] {eventType}, new[] {"trigger_stream"}, new[] {true}, false, false); var resultSetProcessor = ResultSetProcessorFactoryFactory.GetProcessorPrototype( new ResultSetSpec(defaultSelectAllSpec), streamTypeService, null, new bool[1], false, @base.ContextPropertyRegistry, false, false, @base.StatementRawInfo, services); var classNameRSP = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(ResultSetProcessorFactoryProvider), classPostfix); var forge = new StatementAgentInstanceFactoryOnTriggerSetForge( activatorResult.Activator, eventType, subselectForges, tableAccessForges, variableReadWritePackageForge, classNameRSP); IList<StmtClassForgable> forgables = new List<StmtClassForgable>(); forgables.Add( new StmtClassForgableRSPFactoryProvider( classNameRSP, resultSetProcessor, namespaceScope, @base.StatementRawInfo)); var onTrigger = new StmtClassForgableAIFactoryProviderOnTrigger(className, namespaceScope, forge); return new OnTriggerSetPlan(onTrigger, forgables, resultSetProcessor.SelectSubscriberDescriptor); }
private static IList<SelectClauseElementCompiled> ValidateInsertSelect( IList<SelectClauseElementRaw> selectClause, StreamTypeService insertTypeSvc, IList<string> insertColumns, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { var colIndex = 0; IList<SelectClauseElementCompiled> compiledSelect = new List<SelectClauseElementCompiled>(); foreach (var raw in selectClause) { if (raw is SelectClauseStreamRawSpec) { var rawStreamSpec = (SelectClauseStreamRawSpec) raw; int? foundStreamNum = null; for (var s = 0; s < insertTypeSvc.StreamNames.Length; s++) { if (rawStreamSpec.StreamName.Equals(insertTypeSvc.StreamNames[s])) { foundStreamNum = s; break; } } if (foundStreamNum == null) { throw new ExprValidationException( "Stream by name '" + rawStreamSpec.StreamName + "' was not found"); } var streamSelectSpec = new SelectClauseStreamCompiledSpec( rawStreamSpec.StreamName, rawStreamSpec.OptionalAsName); streamSelectSpec.StreamNumber = foundStreamNum.Value; compiledSelect.Add(streamSelectSpec); } else if (raw is SelectClauseExprRawSpec) { var exprSpec = (SelectClauseExprRawSpec) raw; var validationContext = new ExprValidationContextBuilder(insertTypeSvc, statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); var exprCompiled = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.SELECT, exprSpec.SelectExpression, validationContext); var resultName = exprSpec.OptionalAsName; if (resultName == null) { if (insertColumns.Count > colIndex) { resultName = insertColumns[colIndex]; } else { resultName = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(exprCompiled); } } compiledSelect.Add( new SelectClauseExprCompiledSpec( exprCompiled, resultName, exprSpec.OptionalAsName, exprSpec.IsEvents)); EPStatementStartMethodHelperValidate.ValidateNoAggregations( exprCompiled, "Expression in a merge-selection may not utilize aggregation functions"); } else if (raw is SelectClauseElementWildcard) { compiledSelect.Add(new SelectClauseElementWildcard()); } else { throw new IllegalStateException("Unknown select clause item:" + raw); } colIndex++; } return compiledSelect; }
public static PropertyEvaluatorForge MakeEvaluator( PropertyEvalSpec spec, EventType sourceEventType, string optionalSourceStreamName, StatementRawInfo rawInfo, StatementCompileTimeServices services) { var length = spec.Atoms.Count; var containedEventForges = new ContainedEventEvalForge[length]; var fragmentEventTypes = new FragmentEventType[length]; var currentEventType = sourceEventType; var whereClauses = new ExprForge[length]; IList<EventType> streamEventTypes = new List<EventType>(); IList<string> streamNames = new List<string>(); IDictionary<string, int> streamNameAndNumber = new Dictionary<string, int>().WithNullKeySupport(); IList<string> expressionTexts = new List<string>(); streamEventTypes.Add(sourceEventType); streamNames.Add(optionalSourceStreamName); streamNameAndNumber.Put(optionalSourceStreamName, 0); expressionTexts.Add(sourceEventType.Name); IList<SelectClauseElementCompiled> cumulativeSelectClause = new List<SelectClauseElementCompiled>(); for (var i = 0; i < length; i++) { var atom = spec.Atoms[i]; ContainedEventEvalForge containedEventEval = null; string expressionText = null; EventType streamEventType = null; FragmentEventType fragmentEventType = null; // Resolve directly as fragment event type if possible if (atom.SplitterExpression is ExprIdentNode) { var propertyName = ((ExprIdentNode) atom.SplitterExpression).FullUnresolvedName; fragmentEventType = currentEventType.GetFragmentType(propertyName); if (fragmentEventType != null) { var getter = ((EventTypeSPI) currentEventType).GetGetterSPI(propertyName); if (getter != null) { containedEventEval = new ContainedEventEvalGetterForge(getter); expressionText = propertyName; streamEventType = fragmentEventType.FragmentType; } } } // evaluate splitter expression if (containedEventEval == null) { ExprNodeUtilityValidate.ValidatePlainExpression( ExprNodeOrigin.CONTAINEDEVENT, atom.SplitterExpression); var availableTypes = streamEventTypes.ToArray(); var availableStreamNames = streamNames.ToArray(); var isIStreamOnly = new bool[streamNames.Count]; isIStreamOnly.Fill(true); StreamTypeService streamTypeService = new StreamTypeServiceImpl( availableTypes, availableStreamNames, isIStreamOnly, false, false); var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services) .WithAllowBindingConsumption(true) .Build(); var validatedExprNode = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTAINEDEVENT, atom.SplitterExpression, validationContext); // determine result type if (atom.OptionalResultEventType == null) { throw new ExprValidationException( "Missing @type(name) declaration providing the event type name of the return type for expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(atom.SplitterExpression) + "'"); } streamEventType = services.EventTypeCompileTimeResolver.GetTypeByName(atom.OptionalResultEventType); if (streamEventType == null) { throw new ExprValidationException( "Event type by name '" + atom.OptionalResultEventType + "' could not be found"); } var returnType = validatedExprNode.Forge.EvaluationType; // when the expression returns an array, allow array values to become the column of the single-column event type if (returnType.IsArray && streamEventType.PropertyNames.Length == 1 && !(streamEventType is JsonEventType) && // since json string-array should not become itself the property TypeHelper.IsSubclassOrImplementsInterface( returnType.GetElementType().GetBoxedType(), streamEventType.GetPropertyType(streamEventType.PropertyNames[0]).GetBoxedType())) { var writables = EventTypeUtility.GetWriteableProperties(streamEventType, false, false); if (writables != null && !writables.IsEmpty()) { try { var manufacturer = EventTypeUtility.GetManufacturer( streamEventType, new[] {writables.First()}, services.ImportServiceCompileTime, false, services.EventTypeAvroHandler); containedEventEval = new ContainedEventEvalArrayToEventForge( validatedExprNode.Forge, manufacturer); } catch (EventBeanManufactureException e) { throw new ExprValidationException( "Event type '" + streamEventType.Name + "' cannot be populated: " + e.Message, e); } } else { throw new ExprValidationException( "Event type '" + streamEventType.Name + "' cannot be written to"); } } else if (returnType.IsArray && returnType.GetElementType() == typeof(EventBean)) { containedEventEval = new ContainedEventEvalEventBeanArrayForge(validatedExprNode.Forge); } else { // check expression result type against eventtype expected underlying type if (returnType.IsArray) { if (!(streamEventType is JsonEventType)) { if (!TypeHelper.IsSubclassOrImplementsInterface( returnType.GetElementType(), streamEventType.UnderlyingType)) { throw new ExprValidationException( "Event type '" + streamEventType.Name + "' underlying type " + streamEventType.UnderlyingType.CleanName() + " cannot be assigned a value of type " + returnType.CleanName()); } } else { if (returnType.GetElementType() != typeof(string)) { throw new ExprValidationException( "Event type '" + streamEventType.Name + "' requires string-type array and cannot be assigned from value of type " + returnType.CleanName()); } } } else if (GenericExtensions.IsGenericEnumerable(returnType) || TypeHelper.IsImplementsInterface<System.Collections.IEnumerable>(returnType)) { // fine, assumed to return the right type } else { throw new ExprValidationException( "Return type of expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(atom.SplitterExpression) + "' is '" + returnType.Name + "', expected an Iterable or array result"); } containedEventEval = new ContainedEventEvalExprNodeForge( validatedExprNode.Forge, streamEventType); } expressionText = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validatedExprNode); fragmentEventType = new FragmentEventType(streamEventType, true, false); } // validate where clause, if any streamEventTypes.Add(streamEventType); streamNames.Add(atom.OptionalAsName); streamNameAndNumber.Put(atom.OptionalAsName, i + 1); expressionTexts.Add(expressionText); if (atom.OptionalWhereClause != null) { var whereTypes = streamEventTypes.ToArray(); var whereStreamNames = streamNames.ToArray(); var isIStreamOnly = new bool[streamNames.Count]; isIStreamOnly.Fill(true); StreamTypeService streamTypeService = new StreamTypeServiceImpl( whereTypes, whereStreamNames, isIStreamOnly, false, false); var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services) .WithAllowBindingConsumption(true) .Build(); var whereClause = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTAINEDEVENT, atom.OptionalWhereClause, validationContext); whereClauses[i] = whereClause.Forge; } // validate select clause if (atom.OptionalSelectClause != null && !atom.OptionalSelectClause.SelectExprList.IsEmpty()) { var whereTypes = streamEventTypes.ToArray(); var whereStreamNames = streamNames.ToArray(); var isIStreamOnly = new bool[streamNames.Count]; isIStreamOnly.Fill(true); StreamTypeService streamTypeService = new StreamTypeServiceImpl( whereTypes, whereStreamNames, isIStreamOnly, false, false); var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services) .WithAllowBindingConsumption(true) .Build(); foreach (var raw in atom.OptionalSelectClause.SelectExprList) { if (raw is SelectClauseStreamRawSpec) { var rawStreamSpec = (SelectClauseStreamRawSpec) raw; if (!streamNames.Contains(rawStreamSpec.StreamName)) { throw new ExprValidationException( "Property rename '" + rawStreamSpec.StreamName + "' not found in path"); } var streamSpec = new SelectClauseStreamCompiledSpec( rawStreamSpec.StreamName, rawStreamSpec.OptionalAsName); var streamNumber = streamNameAndNumber.Get(rawStreamSpec.StreamName); streamSpec.StreamNumber = streamNumber; cumulativeSelectClause.Add(streamSpec); } else if (raw is SelectClauseExprRawSpec) { var exprSpec = (SelectClauseExprRawSpec) raw; var exprCompiled = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTAINEDEVENT, exprSpec.SelectExpression, validationContext); var resultName = exprSpec.OptionalAsName; if (resultName == null) { resultName = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(exprCompiled); } cumulativeSelectClause.Add( new SelectClauseExprCompiledSpec( exprCompiled, resultName, exprSpec.OptionalAsName, exprSpec.IsEvents)); var isMinimal = ExprNodeUtilityValidate.IsMinimalExpression(exprCompiled); if (isMinimal != null) { throw new ExprValidationException( "Expression in a property-selection may not utilize " + isMinimal); } } else if (raw is SelectClauseElementWildcard) { // wildcards are stream selects: we assign a stream name (any) and add a stream wildcard select var streamNameAtom = atom.OptionalAsName; if (streamNameAtom == null) { streamNameAtom = UuidGenerator.Generate(); } var streamSpec = new SelectClauseStreamCompiledSpec(streamNameAtom, atom.OptionalAsName); var streamNumber = i + 1; streamSpec.StreamNumber = streamNumber; cumulativeSelectClause.Add(streamSpec); } else { throw new IllegalStateException("Unknown select clause item:" + raw); } } } currentEventType = fragmentEventType.FragmentType; fragmentEventTypes[i] = fragmentEventType; containedEventForges[i] = containedEventEval; } if (cumulativeSelectClause.IsEmpty()) { if (length == 1) { return new PropertyEvaluatorSimpleForge( containedEventForges[0], fragmentEventTypes[0], whereClauses[0], expressionTexts[0]); } return new PropertyEvaluatorNestedForge( containedEventForges, fragmentEventTypes, whereClauses, expressionTexts.ToArray()); } { var fragmentEventTypeIsIndexed = new bool[fragmentEventTypes.Length]; for (var i = 0; i < fragmentEventTypes.Length; i++) { fragmentEventTypeIsIndexed[i] = fragmentEventTypes[i].IsIndexed; } var accumulative = new PropertyEvaluatorAccumulativeForge( containedEventForges, fragmentEventTypeIsIndexed, whereClauses, expressionTexts); var whereTypes = streamEventTypes.ToArray(); var whereStreamNames = streamNames.ToArray(); var isIStreamOnly = new bool[streamNames.Count]; isIStreamOnly.Fill(true); StreamTypeService streamTypeService = new StreamTypeServiceImpl( whereTypes, whereStreamNames, isIStreamOnly, false, false); var cumulativeSelectArr = cumulativeSelectClause.ToArray(); var args = new SelectProcessorArgs( cumulativeSelectArr, null, false, null, null, streamTypeService, null, false, rawInfo.Annotations, rawInfo, services); var selectExprDesc = SelectExprProcessorFactory.GetProcessor(args, null, false); return new PropertyEvaluatorSelectForge(selectExprDesc, accumulative); } }
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); }