private AggregationMethodFactory ValidateAggregationInternal(ExprValidationContext context, TableMetadataColumnAggregation tableAccessColumn) { if (IsDistinct) { throw new ExprValidationException(MessagePrefix + "is not supported with distinct"); } // for declaration, validate the specification and return the state factory if (_aggType == CountMinSketchAggType.STATE) { if (context.ExprEvaluatorContext.StatementType != StatementType.CREATE_TABLE) { throw new ExprValidationException(MessagePrefix + "can only be used in create-table statements"); } var specification = ValidateSpecification(context); var stateFactory = context.EngineImportService.AggregationFactoryFactory.MakeCountMinSketch(context.StatementExtensionSvcContext, this, specification); return(new ExprAggCountMinSketchNodeFactoryState(stateFactory)); } // validate number of parameters if (_aggType == CountMinSketchAggType.ADD || _aggType == CountMinSketchAggType.FREQ) { if (ChildNodes.Count == 0 || ChildNodes.Count > 1) { throw new ExprValidationException(MessagePrefix + "requires a single parameter expression"); } } else { if (ChildNodes.Count != 0) { throw new ExprValidationException(MessagePrefix + "requires a no parameter expressions"); } } // validate into-table and table-access if (_aggType == CountMinSketchAggType.ADD) { if (context.IntoTableName == null) { throw new ExprValidationException(MessagePrefix + "can only be used with into-table"); } } else { if (tableAccessColumn == null) { throw new ExprValidationException(MessagePrefix + "requires the use of a table-access expression"); } ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.AGGPARAM, ChildNodes, context); } // obtain evaluator ExprEvaluator addOrFrequencyEvaluator = null; if (_aggType == CountMinSketchAggType.ADD || _aggType == CountMinSketchAggType.FREQ) { addOrFrequencyEvaluator = ChildNodes[0].ExprEvaluator; } return(new ExprAggCountMinSketchNodeFactoryUse(this, addOrFrequencyEvaluator)); }
private static FilterSpecParam HandleInSetNode( ExprInNode constituent, IDictionary <string, Pair <EventType, string> > arrayEventTypes, ExprEvaluatorContext exprEvaluatorContext, string statementName) { var left = constituent.ChildNodes[0]; if (!(left is ExprFilterOptimizableNode)) { return(null); } var filterOptimizableNode = (ExprFilterOptimizableNode)left; var lookupable = filterOptimizableNode.FilterLookupable; var op = FilterOperator.IN_LIST_OF_VALUES; if (constituent.IsNotIn) { op = FilterOperator.NOT_IN_LIST_OF_VALUES; } var expectedNumberOfConstants = constituent.ChildNodes.Count - 1; var listofValues = new List <FilterSpecParamInValue>(); var enumerator = constituent.ChildNodes.GetEnumerator(); enumerator.MoveNext(); // ignore the first node as it's the identifier while (enumerator.MoveNext()) { ExprNode subNode = enumerator.Current; if (ExprNodeUtility.IsConstantValueExpr(subNode)) { var constantNode = (ExprConstantNode)subNode; var constant = constantNode.GetConstantValue(exprEvaluatorContext); if (constant is Array asArray) { for (var i = 0; i < asArray.Length; i++) { var arrayElement = asArray.GetValue(i); var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement); listofValues.Add(new FilterForEvalConstantAnyType(arrayElementCoerced)); if (i > 0) { expectedNumberOfConstants++; } } } else if (constant is ICollection <object> ) { return(null); } else if (constant is IDictionary <string, object> ) { return(null); } else { constant = HandleConstantsCoercion(lookupable, constant); listofValues.Add(new FilterForEvalConstantAnyType(constant)); } } if (subNode is ExprContextPropertyNode) { var contextPropertyNode = (ExprContextPropertyNode)subNode; var returnType = contextPropertyNode.ReturnType; Coercer coercer; Type coercerType; if (returnType.IsCollectionMapOrArray()) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; coercerType = null; } else { coercer = GetNumberCoercer( left.ExprEvaluator.ReturnType, contextPropertyNode.ReturnType, lookupable.Expression, out coercerType); } var finalReturnType = coercer != null ? coercerType : returnType; listofValues.Add(new FilterForEvalContextPropMayCoerce(contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType)); } if (subNode is ExprIdentNode) { var identNodeInner = (ExprIdentNode)subNode; if (identNodeInner.StreamId == 0) { break; // for same event evals use the bool expression, via count compare failing below } var isMustCoerce = false; var coerceToType = lookupable.ReturnType.GetBoxedType(); var identReturnType = identNodeInner.ExprEvaluator.ReturnType; if (identReturnType.IsCollectionMapOrArray()) { CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression); coerceToType = identReturnType; // no action } else if (identReturnType != lookupable.ReturnType) { if (lookupable.ReturnType.IsNumeric()) { if (!identReturnType.CanCoerce(lookupable.ReturnType)) { ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression); } isMustCoerce = true; } else { break; // assumed not compatible } } FilterSpecParamInValue inValue; var streamName = identNodeInner.ResolvedStreamName; if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName)) { var indexAndProp = GetStreamIndex(identNodeInner.ResolvedPropertyName); inValue = new FilterForEvalEventPropIndexedMayCoerce(identNodeInner.ResolvedStreamName, indexAndProp.First, indexAndProp.Second, isMustCoerce, coerceToType, statementName); } else { inValue = new FilterForEvalEventPropMayCoerce(identNodeInner.ResolvedStreamName, identNodeInner.ResolvedPropertyName, isMustCoerce, coerceToType); } listofValues.Add(inValue); } } // Fallback if not all values in the in-node can be resolved to properties or constants if (listofValues.Count == expectedNumberOfConstants) { return(new FilterSpecParamIn(lookupable, op, listofValues)); } return(null); }
private static ExprOptionalConstant GetExprOrConstant(ExprNode exprNode) { if (exprNode is ExprTimePeriod) { var timePeriod = (ExprTimePeriod)exprNode; if (!timePeriod.HasMonth && !timePeriod.HasYear) { // no-month and constant if (exprNode.IsConstantResult) { double sec = timePeriod.EvaluateAsSeconds(null, true, null); var l = (long)(sec * 1000L); IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => l, }; return(new ExprOptionalConstant(eval, l)); } // no-month and not constant else { IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => { double sec = timePeriod.EvaluateAsSeconds(eventsPerStream, isNewData, context); return((long)Math.Round(sec * 1000d)); }, }; return(new ExprOptionalConstant(eval, null)); } } // has-month else { // has-month and constant if (exprNode.IsConstantResult) { ExprTimePeriodEvalDeltaConst timerPeriodConst = timePeriod.ConstEvaluator(null); IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => { return (timerPeriodConst .DeltaMillisecondsAdd (reference)); }, }; return(new ExprOptionalConstant(eval, null)); } // has-month and not constant else { ExprTimePeriodEvalDeltaNonConst timerPeriodNonConst = timePeriod.NonconstEvaluator(); IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => timerPeriodNonConst.DeltaMillisecondsAdd( reference, eventsPerStream, isNewData, context), }; return(new ExprOptionalConstant(eval, null)); } } } else if (ExprNodeUtility.IsConstantValueExpr(exprNode)) { var constantNode = (ExprConstantNode)exprNode; long l = constantNode.GetConstantValue(null).AsLong(); IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => l, }; return(new ExprOptionalConstant(eval, l)); } else { var evaluator = exprNode.ExprEvaluator; IntervalDeltaExprEvaluator eval = new ProxyIntervalDeltaExprEvaluator { ProcEvaluate = (reference, eventsPerStream, isNewData, context) => evaluator.Evaluate( new EvaluateParams(eventsPerStream, isNewData, context)).AsLong(), }; return(new ExprOptionalConstant(eval, null)); } }
private static void RecursiveCompile( EvalFactoryNode evalNode, StatementContext context, ExprEvaluatorContext evaluatorContext, ICollection <string> eventTypeReferences, bool isInsertInto, MatchEventSpec tags, Deque <int> subexpressionIdStack, Stack <EvalFactoryNode> parentNodeStack, ICollection <string> allTagNamesOrdered) { var counter = 0; parentNodeStack.Push(evalNode); foreach (var child in evalNode.ChildNodes) { subexpressionIdStack.AddLast(counter++); RecursiveCompile( child, context, evaluatorContext, eventTypeReferences, isInsertInto, tags, subexpressionIdStack, parentNodeStack, allTagNamesOrdered); subexpressionIdStack.RemoveLast(); } parentNodeStack.Pop(); LinkedHashMap <string, Pair <EventType, string> > newTaggedEventTypes = null; LinkedHashMap <string, Pair <EventType, string> > newArrayEventTypes = null; if (evalNode is EvalFilterFactoryNode) { var filterNode = (EvalFilterFactoryNode)evalNode; var eventName = filterNode.RawFilterSpec.EventTypeName; if (context.TableService.GetTableMetadata(eventName) != null) { throw new ExprValidationException("Tables cannot be used in pattern filter atoms"); } var resolvedEventType = FilterStreamSpecRaw.ResolveType( context.EngineURI, eventName, context.EventAdapterService, context.PlugInTypeResolutionURIs); 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 = PropertyEvaluatorFactory.MakeEvaluator( filterNode.RawFilterSpec.OptionalPropertyEvalSpec, resolvedEventType, filterNode.EventAsName, context.EventAdapterService, context.EngineImportService, context.SchedulingService, context.VariableService, context.ScriptingService, context.TableService, context.EngineURI, context.StatementId, context.StatementName, context.Annotations, subexpressionIdStack, context.ConfigSnapshot, context.NamedWindowMgmtService, context.StatementExtensionServicesContext); finalEventType = optionalPropertyEvaluator.FragmentEventType; isPropertyEvaluation = true; } if (finalEventType is EventTypeSPI) { eventTypeReferences.Add(((EventTypeSPI)finalEventType).Metadata.PrimaryName); } // 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.FullName); } 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) LinkedHashMap <string, Pair <EventType, string> > arrayCompositeEventTypes = null; if (tags.ArrayEventTypes != null && !tags.ArrayEventTypes.IsEmpty()) { arrayCompositeEventTypes = new LinkedHashMap <string, Pair <EventType, string> >(); var patternSubexEventType = GetPatternSubexEventType( context.StatementId, "pattern", subexpressionIdStack); foreach (var entry in tags.ArrayEventTypes) { var specificArrayType = new LinkedHashMap <string, Pair <EventType, string> >(); specificArrayType.Put(entry.Key, entry.Value); var arrayTagCompositeEventType = context.EventAdapterService.CreateSemiAnonymousMapType( patternSubexEventType, Collections.GetEmptyMap <string, Pair <EventType, string> >(), specificArrayType, isInsertInto); context.StatementSemiAnonymousTypeRegistry.Register(arrayTagCompositeEventType); var tag = entry.Key; if (!filterTypes.ContainsKey(tag)) { var pair = new Pair <EventType, string>(arrayTagCompositeEventType, tag); filterTypes.Put(tag, pair); arrayCompositeEventTypes.Put(tag, pair); } } } StreamTypeService streamTypeService = new StreamTypeServiceImpl( filterTypes, context.EngineURI, true, false); var exprNodes = filterNode.RawFilterSpec.FilterExpressions; var spec = FilterSpecCompiler.MakeFilterSpec( resolvedEventType, eventName, exprNodes, filterNode.RawFilterSpec.OptionalPropertyEvalSpec, filterTaggedEventTypes, arrayCompositeEventTypes, streamTypeService, null, context, subexpressionIdStack); filterNode.FilterSpec = spec; } else if (evalNode is EvalObserverFactoryNode) { var observerNode = (EvalObserverFactoryNode)evalNode; try { var observerFactory = context.PatternResolutionService.Create(observerNode.PatternObserverSpec); var streamTypeService = GetStreamTypeService( context.EngineURI, context.StatementId, context.EventAdapterService, tags.TaggedEventTypes, tags.ArrayEventTypes, subexpressionIdStack, "observer", context); var validationContext = new ExprValidationContext( streamTypeService, context.EngineImportService, context.StatementExtensionServicesContext, null, context.SchedulingService, context.VariableService, context.TableService, evaluatorContext, context.EventAdapterService, context.StatementName, context.StatementId, context.Annotations, context.ContextDescriptor, context.ScriptingService, false, false, false, false, null, false); var validated = ValidateExpressions( ExprNodeOrigin.PATTERNOBSERVER, observerNode.PatternObserverSpec.ObjectParameters, validationContext); MatchedEventConvertor convertor = new MatchedEventConvertorImpl( tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered, context.EventAdapterService); observerNode.ObserverFactory = observerFactory; observerFactory.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 EvalGuardFactoryNode) { var guardNode = (EvalGuardFactoryNode)evalNode; try { var guardFactory = context.PatternResolutionService.Create(guardNode.PatternGuardSpec); var streamTypeService = GetStreamTypeService( context.EngineURI, context.StatementId, context.EventAdapterService, tags.TaggedEventTypes, tags.ArrayEventTypes, subexpressionIdStack, "guard", context); var validationContext = new ExprValidationContext( streamTypeService, context.EngineImportService, context.StatementExtensionServicesContext, null, context.SchedulingService, context.VariableService, context.TableService, evaluatorContext, context.EventAdapterService, context.StatementName, context.StatementId, context.Annotations, context.ContextDescriptor, context.ScriptingService, false, false, false, false, null, false); var validated = ValidateExpressions( ExprNodeOrigin.PATTERNGUARD, guardNode.PatternGuardSpec.ObjectParameters, validationContext); MatchedEventConvertor convertor = new MatchedEventConvertorImpl( tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered, context.EventAdapterService); guardNode.GuardFactory = guardFactory; guardFactory.SetGuardParameters(validated, convertor); } 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 EvalEveryDistinctFactoryNode) { var distinctNode = (EvalEveryDistinctFactoryNode)evalNode; var matchEventFromChildNodes = AnalyzeMatchEvent(distinctNode); var streamTypeService = GetStreamTypeService( context.EngineURI, context.StatementId, context.EventAdapterService, matchEventFromChildNodes.TaggedEventTypes, matchEventFromChildNodes.ArrayEventTypes, subexpressionIdStack, "every-distinct", context); var validationContext = new ExprValidationContext( streamTypeService, context.EngineImportService, context.StatementExtensionServicesContext, null, context.SchedulingService, context.VariableService, context.TableService, evaluatorContext, context.EventAdapterService, context.StatementName, context.StatementId, context.Annotations, context.ContextDescriptor, context.ScriptingService, false, false, false, false, null, false); 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); } MatchedEventConvertor convertor = new MatchedEventConvertorImpl( matchEventFromChildNodes.TaggedEventTypes, matchEventFromChildNodes.ArrayEventTypes, allTagNamesOrdered, context.EventAdapterService); distinctNode.Convertor = convertor; // Determine whether some expressions are constants or time period IList <ExprNode> distinctExpressions = new List <ExprNode>(); ExprTimePeriodEvalDeltaConst timeDeltaComputation = 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; timeDeltaComputation = timePeriodExpr.ConstEvaluator(new ExprEvaluatorContextStatement(context, false)); } else if (expr.IsConstantResult) { if (count == last) { var evaluateParams = new EvaluateParams(null, true, evaluatorContext); var value = expr.ExprEvaluator.Evaluate(evaluateParams); if (!(value.IsNumber())) { throw new ExprValidationException( "Invalid parameter for every-distinct, expected number of seconds constant (constant not considered for distinct)"); } var secondsExpire = expr.ExprEvaluator.Evaluate(evaluateParams).AsBoxedDouble(); if ((secondsExpire != null) && (secondsExpire > 0)) { timeDeltaComputation = new ExprTimePeriodEvalDeltaConstMsec((long)Math.Round(1000d * secondsExpire.Value)); expiryTimeExp = expr; } } else { Log.Warn( "Every-distinct node utilizes an expression returning a constant value, please check expression '{0}', not adding expression to distinct-value expression list", expr.ToExpressionStringMinPrecedenceSafe()); } } 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, timeDeltaComputation, expiryTimeExp); } else if (evalNode is EvalMatchUntilFactoryNode) { var matchUntilNode = (EvalMatchUntilFactoryNode)evalNode; // compile bounds expressions, if any var untilMatchEventSpec = new MatchEventSpec(tags.TaggedEventTypes, tags.ArrayEventTypes); var streamTypeService = GetStreamTypeService( context.EngineURI, context.StatementId, context.EventAdapterService, untilMatchEventSpec.TaggedEventTypes, untilMatchEventSpec.ArrayEventTypes, subexpressionIdStack, "until", context); var validationContext = new ExprValidationContext( streamTypeService, context.EngineImportService, context.StatementExtensionServicesContext, null, context.SchedulingService, context.VariableService, context.TableService, evaluatorContext, context.EventAdapterService, context.StatementName, context.StatementId, context.Annotations, context.ContextDescriptor, context.ScriptingService, false, false, false, false, null, false); 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; var convertor = new MatchedEventConvertorImpl( untilMatchEventSpec.TaggedEventTypes, untilMatchEventSpec.ArrayEventTypes, allTagNamesOrdered, context.EventAdapterService); 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.TagsArrayed = GetIndexesForTags(allTagNamesOrdered, arrayTags); } else if (evalNode is EvalFollowedByFactoryNode) { var followedByNode = (EvalFollowedByFactoryNode)evalNode; StreamTypeService streamTypeService = new StreamTypeServiceImpl(context.EngineURI, false); var validationContext = new ExprValidationContext( streamTypeService, context.EngineImportService, context.StatementExtensionServicesContext, null, context.SchedulingService, context.VariableService, context.TableService, evaluatorContext, context.EventAdapterService, context.StatementName, context.StatementId, context.Annotations, context.ContextDescriptor, context.ScriptingService, false, false, false, false, null, false); 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 = ExprNodeUtility.GetValidatedSubtree( ExprNodeOrigin.FOLLOWEDBYMAX, maxExpr, validationContext); validated.Add(validatedExpr); if ((validatedExpr.ExprEvaluator.ReturnType == null) || (!validatedExpr.ExprEvaluator.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 FilterSpecParam HandleAdvancedIndexDescProvider( FilterSpecCompilerAdvIndexDescProvider provider, IDictionary <string, Pair <EventType, string> > arrayEventTypes, string statementName, ExprEvaluatorContext exprEvaluatorContext) { var filterDesc = provider.FilterSpecDesc; if (filterDesc == null) { return(null); } var keyExpressions = filterDesc.KeyExpressions; var xGetter = ResolveFilterIndexRequiredGetter(filterDesc.IndexName, keyExpressions[0]); var yGetter = ResolveFilterIndexRequiredGetter(filterDesc.IndexName, keyExpressions[1]); var widthGetter = ResolveFilterIndexRequiredGetter(filterDesc.IndexName, keyExpressions[2]); var heightGetter = ResolveFilterIndexRequiredGetter(filterDesc.IndexName, keyExpressions[3]); var config = (AdvancedIndexConfigContextPartitionQuadTree)filterDesc.IndexSpec; var builder = new StringWriter(); ExprNodeUtility.ToExpressionString(keyExpressions[0], builder); builder.Write(","); ExprNodeUtility.ToExpressionString(keyExpressions[1], builder); builder.Write(","); ExprNodeUtility.ToExpressionString(keyExpressions[2], builder); builder.Write(","); ExprNodeUtility.ToExpressionString(keyExpressions[3], builder); builder.Write("/"); builder.Write(filterDesc.IndexName.ToLower()); builder.Write("/"); builder.Write(filterDesc.IndexType.ToLower()); builder.Write("/"); config.ToConfiguration(builder); var expression = builder.ToString(); Type returnType; switch (filterDesc.IndexType) { case EngineImportApplicationDotMethodPointInsideRectangle.INDEX_TYPE_NAME: returnType = typeof(XYPoint); break; case EngineImportApplicationDotMethodRectangeIntersectsRectangle.INDEX_TYPE_NAME: returnType = typeof(XYWHRectangle); break; default: throw new IllegalStateException("Unrecognized index type " + filterDesc.IndexType); } var lookupable = new FilterSpecLookupableAdvancedIndex(expression, null, returnType, config, xGetter, yGetter, widthGetter, heightGetter, filterDesc.IndexType); var indexExpressions = filterDesc.IndexExpressions; var xEval = ResolveFilterIndexDoubleEval(filterDesc.IndexName, indexExpressions[0], arrayEventTypes, statementName, exprEvaluatorContext); var yEval = ResolveFilterIndexDoubleEval(filterDesc.IndexName, indexExpressions[1], arrayEventTypes, statementName, exprEvaluatorContext); switch (filterDesc.IndexType) { case EngineImportApplicationDotMethodPointInsideRectangle.INDEX_TYPE_NAME: return(new FilterSpecParamAdvancedIndexQuadTreePointRegion(lookupable, FilterOperator.ADVANCED_INDEX, xEval, yEval)); case EngineImportApplicationDotMethodRectangeIntersectsRectangle.INDEX_TYPE_NAME: var widthEval = ResolveFilterIndexDoubleEval(filterDesc.IndexName, indexExpressions[2], arrayEventTypes, statementName, exprEvaluatorContext); var heightEval = ResolveFilterIndexDoubleEval(filterDesc.IndexName, indexExpressions[3], arrayEventTypes, statementName, exprEvaluatorContext); return(new FilterSpecParamAdvancedIndexQuadTreeMXCIF(lookupable, FilterOperator.ADVANCED_INDEX, xEval, yEval, widthEval, heightEval)); default: throw new IllegalStateException("Unrecognized index type " + filterDesc.IndexType); } }
public override void ReplaceUnlistedChildNode(ExprNode nodeToReplace, ExprNode newNode) { ExprNodeUtility.ReplaceChainChildNode(nodeToReplace, newNode, _chainSpec); }
public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient) { var createDesc = StatementSpec.CreateVariableDesc; VariableServiceUtil.CheckAlreadyDeclaredTable(createDesc.VariableName, services.TableService); // Get assignment value Object value = null; if (createDesc.Assignment != null) { // Evaluate assignment expression var typeService = new StreamTypeServiceImpl(new EventType[0], new String[0], new bool[0], services.EngineURI, false); var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false); var validationContext = new ExprValidationContext( typeService, statementContext.MethodResolutionService, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, false, false, null, false); var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.VARIABLEASSIGN, createDesc.Assignment, validationContext); value = validated.ExprEvaluator.Evaluate(new EvaluateParams(null, true, evaluatorContextStmt)); } // Create variable try { services.VariableService.CreateNewVariable( StatementSpec.OptionalContextName, createDesc.VariableName, createDesc.VariableType, createDesc.IsConstant, createDesc.IsArray, createDesc.IsArrayOfPrimitive, value, services.EngineImportService); } catch (VariableExistsException ex) { // for new statement we don't allow creating the same variable if (isNewStatement) { throw new ExprValidationException("Cannot create variable: " + ex.Message, ex); } } catch (VariableDeclarationException ex) { throw new ExprValidationException("Cannot create variable: " + ex.Message, ex); } var destroyMethod = new EPStatementDestroyCallbackList(); destroyMethod.AddCallback( () => { try { services.StatementVariableRefService.RemoveReferencesStatement(statementContext.StatementName); } catch (Exception ex) { Log.Error("Error removing variable '" + createDesc.VariableName + "': " + ex.Message); } }); var stopMethod = new EPStatementStopMethod(() => { }); VariableMetaData variableMetaData = services.VariableService.GetVariableMetaData(createDesc.VariableName); Viewable outputView; if (StatementSpec.OptionalContextName != null) { EventType eventType = CreateVariableView.GetEventType(statementContext.StatementId, services.EventAdapterService, variableMetaData); var contextFactory = new StatementAgentInstanceFactoryCreateVariable(statementContext, services, variableMetaData, eventType); var mergeView = new ContextMergeView(eventType); outputView = mergeView; var statement = new ContextManagedStatementCreateVariableDesc(StatementSpec, statementContext, mergeView, contextFactory); services.ContextManagementService.AddStatement(StatementSpec.OptionalContextName, statement, isRecoveringResilient); ContextManagementService contextManagementService = services.ContextManagementService; destroyMethod.AddCallback(() => contextManagementService.DestroyedStatement(StatementSpec.OptionalContextName, statementContext.StatementName, statementContext.StatementId)); } else { // allocate services.VariableService.AllocateVariableState(createDesc.VariableName, VariableServiceConstants.NOCONTEXT_AGENTINSTANCEID, statementContext.StatementExtensionServicesContext); var createView = new CreateVariableView(statementContext.StatementId, services.EventAdapterService, services.VariableService, createDesc.VariableName, statementContext.StatementResultService); services.VariableService.RegisterCallback(createDesc.VariableName, 0, createView.Update); statementContext.StatementStopService.StatementStopped += () => services.VariableService.UnregisterCallback(createDesc.VariableName, 0, createView.Update); // Create result set processor, use wildcard selection StatementSpec.SelectClauseSpec.SetSelectExprList(new SelectClauseElementWildcard()); StatementSpec.SelectStreamDirEnum = SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH; StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[] { createView.EventType }, new String[] { "create_variable" }, new bool[] { true }, services.EngineURI, false); var agentInstanceContext = GetDefaultAgentInstanceContext(statementContext); var resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.GetProcessorPrototype( StatementSpec, statementContext, typeService, null, new bool[0], true, ContextPropertyRegistryImpl.EMPTY_REGISTRY, null, services.ConfigSnapshot); var resultSetProcessor = EPStatementStartMethodHelperAssignExpr.GetAssignResultSetProcessor(agentInstanceContext, resultSetProcessorPrototype); // Attach output view var outputViewFactory = OutputProcessViewFactoryFactory.Make(StatementSpec, services.InternalEventRouter, agentInstanceContext.StatementContext, resultSetProcessor.ResultEventType, null, services.TableService, resultSetProcessorPrototype.ResultSetProcessorFactory.ResultSetProcessorType); var outputViewBase = outputViewFactory.MakeView(resultSetProcessor, agentInstanceContext); createView.AddView(outputViewBase); outputView = outputViewBase; } services.StatementVariableRefService.AddReferences(statementContext.StatementName, Collections.SingletonList(createDesc.VariableName), null); return(new EPStatementStartResult(outputView, stopMethod, destroyMethod.Destroy)); }
/// <summary> /// Ctor. /// </summary> /// <param name="container">The container.</param> /// <param name="viewChain">views</param> /// <param name="matchRecognizeSpec">specification</param> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="isUnbound">true for unbound stream</param> /// <param name="annotations">annotations</param> /// <param name="matchRecognizeConfig">The match recognize configuration.</param> /// <throws>ExprValidationException if validation fails</throws> public EventRowRegexNFAViewFactory( IContainer container, ViewFactoryChain viewChain, MatchRecognizeSpec matchRecognizeSpec, AgentInstanceContext agentInstanceContext, bool isUnbound, Attribute[] annotations, ConfigurationEngineDefaults.MatchRecognizeConfig matchRecognizeConfig) { var parentViewType = viewChain.EventType; _matchRecognizeSpec = matchRecognizeSpec; _isUnbound = isUnbound; _isIterateOnly = HintEnum.ITERATE_ONLY.GetHint(annotations) != null; _matchRecognizeConfig = matchRecognizeConfig; var statementContext = agentInstanceContext.StatementContext; // Expand repeats and permutations _expandedPatternNode = RegexPatternExpandUtil.Expand( container, matchRecognizeSpec.Pattern); // Determine single-row and multiple-row variables _variablesSingle = new LinkedHashSet <string>(); ISet <string> variablesMultiple = new LinkedHashSet <string>(); EventRowRegexHelper.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; _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 _streamVariables = new SortedDictionary <int, string>(); foreach (var entry in _variableStreams) { _streamVariables.Put(entry.Value.First, entry.Key); } // determine visibility rules var visibility = EventRowRegexHelper.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] = parentViewType; streamNum++; } foreach (var variableMultiple in variablesMultiple) { allStreamNames[streamNum] = variableMultiple; allTypes[streamNum] = parentViewType; 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 exprEvaluatorContext = new ExprEvaluatorContextStatement(statementContext, false); _isExprRequiresMultimatchState = new bool[_variableStreams.Count]; for (var defineIndex = 0; defineIndex < matchRecognizeSpec.Defines.Count; defineIndex++) { var 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 = EventRowRegexNFAViewFactoryHelper.BuildDefineStreamTypeServiceDefine(statementContext, _variableStreams, defineItem, visibility, parentViewType); var exprNodeResult = HandlePreviousFunctions(defineItem.Expression); var validationContext = new ExprValidationContext( statementContext.Container, typeServiceDefines, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, true, false, true, false, null, false); ExprNode validated; try { // validate validated = ExprNodeUtility.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; } } } _isDefineAsksMultimatches = CollectionUtil.IsAnySet(_isExprRequiresMultimatchState); _defineMultimatchEventBean = _isDefineAsksMultimatches ? EventRowRegexNFAViewFactoryHelper.GetDefineMultimatchBean(statementContext, _variableStreams, parentViewType) : null; // 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 var countPrev = 0; foreach (var entry in _callbacksPerIndex) { foreach (var callback in entry.Value) { callback.AssignedIndex = countPrev; } countPrev++; } // determine type service for use with MEASURE IDictionary <string, object> measureTypeDef = new LinkedHashMap <string, object>(); foreach (var variableSingle in _variablesSingle) { measureTypeDef.Put(variableSingle, parentViewType); } foreach (var variableMultiple in variablesMultiple) { measureTypeDef.Put(variableMultiple, new EventType[] { parentViewType }); } var outputEventTypeName = statementContext.StatementId + "_rowrecog"; _compositeEventType = (ObjectArrayEventType)statementContext.EventAdapterService.CreateAnonymousObjectArrayType(outputEventTypeName, measureTypeDef); StreamTypeService typeServiceMeasure = new StreamTypeServiceImpl(_compositeEventType, "MATCH_RECOGNIZE", true, statementContext.EngineURI); // find MEASURE clause aggregations var measureReferencesMultivar = false; IList <ExprAggregateNode> measureAggregateExprNodes = new List <ExprAggregateNode>(); foreach (var measureItem in matchRecognizeSpec.Measures) { ExprAggregateNodeUtil.GetAggregatesBottomUp(measureItem.Expr, measureAggregateExprNodes); } if (!measureAggregateExprNodes.IsEmpty()) { var isIStreamOnly = new bool[allStreamNames.Length]; CompatExtensions.Fill(isIStreamOnly, true); var typeServiceAggregateMeasure = new StreamTypeServiceImpl(allTypes, allStreamNames, isIStreamOnly, statementContext.EngineURI, false); var measureExprAggNodesPerStream = new Dictionary <int, IList <ExprAggregateNode> >(); foreach (var aggregateNode in measureAggregateExprNodes) { // validate absence of group-by aggregateNode.ValidatePositionals(); if (aggregateNode.OptionalLocalGroupBy != null) { throw new ExprValidationException("Match-recognize does not allow aggregation functions to specify a group-by"); } // validate node and params var count = 0; var visitor = new ExprNodeIdentifierVisitor(true); var validationContext = new ExprValidationContext( statementContext.Container, typeServiceAggregateMeasure, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, null, false); for (int ii = 0; ii < aggregateNode.ChildNodes.Count; ii++) { var child = aggregateNode.ChildNodes[ii]; var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.MATCHRECOGMEASURE, child, validationContext); validated.Accept(visitor); aggregateNode.SetChildNode(count++, new ExprNodeValidated(validated)); } validationContext = new ExprValidationContext( statementContext.Container, typeServiceMeasure, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, null, false); aggregateNode.Validate(validationContext); // verify properties used within the aggregation var aggregatedStreams = new HashSet <int>(); foreach (var pair in visitor.ExprProperties) { aggregatedStreams.Add(pair.First); } int?multipleVarStream = null; foreach (int streamNumAggregated in aggregatedStreams) { var variable = _streamVariables.Get(streamNumAggregated); if (variablesMultiple.Contains(variable)) { measureReferencesMultivar = true; 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); } var factoryDesc = AggregationServiceFactoryFactory.GetServiceMatchRecognize(_streamVariables.Count, measureExprAggNodesPerStream, typeServiceAggregateMeasure.EventTypes); _aggregationService = factoryDesc.AggregationServiceFactory.MakeService(agentInstanceContext); _aggregationExpressions = factoryDesc.Expressions; } else { _aggregationService = null; _aggregationExpressions = Collections.GetEmptyList <AggregationServiceAggExpressionDesc>(); } // 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, typeServiceMeasure, variablesMultiple, _variablesSingle, statementContext); measureItem.Expr = validated; rowTypeDef.Put(measureItem.Name, validated.ExprEvaluator.ReturnType); 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; } } } } _isCollectMultimatches = measureReferencesMultivar || _isDefineAsksMultimatches; // create rowevent type var rowEventTypeName = statementContext.StatementId + "_rowrecogrow"; _rowEventType = statementContext.EventAdapterService.CreateAnonymousMapType(rowEventTypeName, rowTypeDef, true); // validate partition-by expressions, if any if (!matchRecognizeSpec.PartitionByExpressions.IsEmpty()) { var typeServicePartition = new StreamTypeServiceImpl(parentViewType, "MATCH_RECOGNIZE_PARTITION", true, statementContext.EngineURI); var validated = new List <ExprNode>(); var validationContext = new ExprValidationContext( statementContext.Container, typeServicePartition, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, null, false); foreach (var partitionExpr in matchRecognizeSpec.PartitionByExpressions) { validated.Add(ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.MATCHRECOGPARTITION, partitionExpr, validationContext)); } matchRecognizeSpec.PartitionByExpressions = validated; } // validate interval if present if (matchRecognizeSpec.Interval != null) { var validationContext = new ExprValidationContext( statementContext.Container, new StreamTypeServiceImpl(statementContext.EngineURI, false), statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, exprEvaluatorContext, statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, true, false, null, false); matchRecognizeSpec.Interval.Validate(validationContext); } }
public static SubordPropPlan GetJoinProps(ExprNode filterExpr, int outsideStreamCount, EventType[] allStreamTypesZeroIndexed, ExcludePlanHint excludePlanHint) { // No filter expression means full table scan if (filterExpr == null) { return(new SubordPropPlan()); } // analyze query graph var queryGraph = new QueryGraph(outsideStreamCount + 1, excludePlanHint, true); FilterExprAnalyzer.Analyze(filterExpr, queryGraph, false); // Build a list of streams and indexes var joinProps = new LinkedHashMap <String, SubordPropHashKey>(); var rangeProps = new LinkedHashMap <String, SubordPropRangeKey>(); for (int stream = 0; stream < outsideStreamCount; stream++) { int lookupStream = stream + 1; QueryGraphValue queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0); QueryGraphValuePairHashKeyIndex hashKeysAndIndexes = queryGraphValue.HashKeyProps; // handle key-lookups var keyPropertiesJoin = hashKeysAndIndexes.Keys; var indexPropertiesJoin = hashKeysAndIndexes.Indexed; if (keyPropertiesJoin.IsNotEmpty()) { if (keyPropertiesJoin.Count != indexPropertiesJoin.Count) { throw new IllegalStateException("Invalid query key and index property collection for stream " + stream); } for (int i = 0; i < keyPropertiesJoin.Count; i++) { QueryGraphValueEntryHashKeyed keyDesc = keyPropertiesJoin[i]; ExprNode compareNode = keyDesc.KeyExpr; var keyPropType = compareNode.ExprEvaluator.ReturnType.GetBoxedType(); var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(indexPropertiesJoin[i]).GetBoxedType(); var coercionType = indexedPropType; if (keyPropType != indexedPropType) { coercionType = keyPropType.GetCompareToCoercionType(indexedPropType); } SubordPropHashKey desc; if (keyPropertiesJoin[i] is QueryGraphValueEntryHashKeyedExpr) { var keyExpr = (QueryGraphValueEntryHashKeyedExpr)keyPropertiesJoin[i]; var keyStreamNum = keyExpr.IsRequiresKey ? stream : (int?)null; desc = new SubordPropHashKey(keyDesc, keyStreamNum, coercionType); } else { var prop = (QueryGraphValueEntryHashKeyedProp)keyDesc; desc = new SubordPropHashKey(prop, stream, coercionType); } joinProps.Put(indexPropertiesJoin[i], desc); } } // handle range lookups QueryGraphValuePairRangeIndex rangeKeysAndIndexes = queryGraphValue.RangeProps; var rangeIndexes = rangeKeysAndIndexes.Indexed; var rangeDescs = rangeKeysAndIndexes.Keys; if (rangeDescs.IsEmpty()) { continue; } // get all ranges lookups int count = -1; foreach (QueryGraphValueEntryRange rangeDesc in rangeDescs) { count++; String rangeIndexProp = rangeIndexes[count]; SubordPropRangeKey subqRangeDesc = rangeProps.Get(rangeIndexProp); // other streams may specify the start or end endpoint of a range, therefore this operation can be additive if (subqRangeDesc != null) { if (subqRangeDesc.RangeInfo.RangeType.IsRange()) { continue; } // see if we can make this additive by using a range var relOpOther = (QueryGraphValueEntryRangeRelOp)subqRangeDesc.RangeInfo; var relOpThis = (QueryGraphValueEntryRangeRelOp)rangeDesc; QueryGraphRangeConsolidateDesc opsDesc = QueryGraphRangeUtil.GetCanConsolidate( relOpThis.RangeType, relOpOther.RangeType); if (opsDesc != null) { ExprNode start; ExprNode end; if (!opsDesc.IsReverse) { start = relOpOther.Expression; end = relOpThis.Expression; } else { start = relOpThis.Expression; end = relOpOther.Expression; } var allowRangeReversal = relOpOther.IsBetweenPart && relOpThis.IsBetweenPart; var rangeIn = new QueryGraphValueEntryRangeIn(opsDesc.RangeType, start, end, allowRangeReversal); var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType(); var coercionType = indexedPropType; var proposedType = CoercionUtil.GetCoercionTypeRangeIn(indexedPropType, rangeIn.ExprStart, rangeIn.ExprEnd); if (proposedType != null && proposedType != indexedPropType) { coercionType = proposedType; } subqRangeDesc = new SubordPropRangeKey(rangeIn, coercionType); rangeProps.Put(rangeIndexProp, subqRangeDesc); } // ignore continue; } // an existing entry has not been found if (rangeDesc.RangeType.IsRange()) { var rangeIn = (QueryGraphValueEntryRangeIn)rangeDesc; var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType(); var coercionType = indexedPropType; var proposedType = CoercionUtil.GetCoercionTypeRangeIn(indexedPropType, rangeIn.ExprStart, rangeIn.ExprEnd); if (proposedType != null && proposedType != indexedPropType) { coercionType = proposedType; } subqRangeDesc = new SubordPropRangeKey(rangeDesc, coercionType); } else { var relOp = (QueryGraphValueEntryRangeRelOp)rangeDesc; var keyPropType = relOp.Expression.ExprEvaluator.ReturnType; var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType(); var coercionType = indexedPropType; if (keyPropType != indexedPropType) { coercionType = keyPropType.GetCompareToCoercionType(indexedPropType); } subqRangeDesc = new SubordPropRangeKey(rangeDesc, coercionType); } rangeProps.Put(rangeIndexProp, subqRangeDesc); } } SubordPropInKeywordSingleIndex inKeywordSingleIdxProp = null; SubordPropInKeywordMultiIndex inKeywordMultiIdxProp = null; if (joinProps.IsEmpty() && rangeProps.IsEmpty()) { for (int stream = 0; stream < outsideStreamCount; stream++) { int lookupStream = stream + 1; QueryGraphValue queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0); QueryGraphValuePairInKWSingleIdx inkwSingles = queryGraphValue.InKeywordSingles; if (inkwSingles.Indexed.Length != 0) { ExprNode[] keys = inkwSingles.Key[0].KeyExprs; String key = inkwSingles.Indexed[0]; if (inKeywordSingleIdxProp != null) { continue; } var coercionType = keys[0].ExprEvaluator.ReturnType; // for in-comparison the same type is required inKeywordSingleIdxProp = new SubordPropInKeywordSingleIndex(key, coercionType, keys); } IList <QueryGraphValuePairInKWMultiIdx> inkwMultis = queryGraphValue.InKeywordMulti; if (!inkwMultis.IsEmpty()) { QueryGraphValuePairInKWMultiIdx multi = inkwMultis[0]; inKeywordMultiIdxProp = new SubordPropInKeywordMultiIndex(ExprNodeUtility.GetIdentResolvedPropertyNames(multi.Indexed), multi.Indexed[0].ExprEvaluator.ReturnType, multi.Key.KeyExpr); } if (inKeywordSingleIdxProp != null && inKeywordMultiIdxProp != null) { inKeywordMultiIdxProp = null; } } } return(new SubordPropPlan(joinProps, rangeProps, inKeywordSingleIdxProp, inKeywordMultiIdxProp)); }
public void Attach(EventType parentEventType, StatementContext statementContext, ViewFactory optionalParentFactory, IList <ViewFactory> parentViewFactories) { // Find the group by view matching the merge view GroupByViewFactoryMarker groupByViewFactory = null; var unvalidated = _viewParameters.ToArray(); foreach (var parentView in parentViewFactories) { if (!(parentView is GroupByViewFactoryMarker)) { continue; } var candidateGroupByView = (GroupByViewFactoryMarker)parentView; if (ExprNodeUtility.DeepEquals(candidateGroupByView.CriteriaExpressions, unvalidated)) { groupByViewFactory = candidateGroupByView; } } if (groupByViewFactory == null) { throw new ViewParameterException("Groupwin view for this merge view could not be found among parent views"); } _criteriaExpressions = groupByViewFactory.CriteriaExpressions; _removable = groupByViewFactory.IsReclaimAged; // determine types of fields var fieldTypes = new Type[_criteriaExpressions.Length]; for (var i = 0; i < fieldTypes.Length; i++) { fieldTypes[i] = _criteriaExpressions[i].ExprEvaluator.ReturnType; } // Determine the readonly event type that the merge view generates // This event type is ultimatly generated by AddPropertyValueView which is added to each view branch for each // group key. // If the parent event type contains the merge fields, we use the same event type var parentContainsMergeKeys = true; var fieldNames = new String[_criteriaExpressions.Length]; for (var i = 0; i < _criteriaExpressions.Length; i++) { var name = ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(_criteriaExpressions[i]); fieldNames[i] = name; if (!(parentEventType.IsProperty(name))) { parentContainsMergeKeys = false; } } // If the parent view contains the fields to group by, the event type after merging stays the same if (parentContainsMergeKeys) { _eventType = parentEventType; } else // If the parent event type does not contain the fields, such as when a statistics views is // grouped which simply provides a map of calculated values, // then we need to add in the merge field as an event property thus changing event types. { IDictionary <String, Object> additionalProps = new Dictionary <String, Object>(); for (var i = 0; i < fieldNames.Length; i++) { additionalProps.Put(fieldNames[i], fieldTypes[i]); } var outputEventTypeName = statementContext.StatementId + "_mergeview_" + _streamNumber; _eventType = statementContext.EventAdapterService.CreateAnonymousWrapperType(outputEventTypeName, parentEventType, additionalProps); } }
private ExprNode HandlePreviousFunctions(ExprNode defineItemExpression) { var previousVisitor = new ExprNodePreviousVisitorWParent(); defineItemExpression.Accept(previousVisitor); if (previousVisitor.Previous == null) { return(defineItemExpression); } foreach (var previousNodePair in previousVisitor.Previous) { var previousNode = previousNodePair.Second; var matchRecogPrevNode = new ExprPreviousMatchRecognizeNode(); if (previousNodePair.Second.ChildNodes.Count == 1) { matchRecogPrevNode.AddChildNode(previousNode.ChildNodes[0]); matchRecogPrevNode.AddChildNode(new ExprConstantNodeImpl(1)); } else if (previousNodePair.Second.ChildNodes.Count == 2) { var first = previousNode.ChildNodes[0]; var second = previousNode.ChildNodes[1]; if ((first.IsConstantResult) && (!second.IsConstantResult)) { matchRecogPrevNode.AddChildNode(second); matchRecogPrevNode.AddChildNode(first); } else if ((!first.IsConstantResult) && (second.IsConstantResult)) { matchRecogPrevNode.AddChildNode(first); matchRecogPrevNode.AddChildNode(second); } else { throw new ExprValidationException("PREV operator requires a constant index"); } } if (previousNodePair.First == null) { defineItemExpression = matchRecogPrevNode; } else { ExprNodeUtility.ReplaceChildNode(previousNodePair.First, previousNodePair.Second, matchRecogPrevNode); } // store in a list per index such that we can consolidate this into a single buffer var index = matchRecogPrevNode.ConstantIndexNumber; var callbackList = _callbacksPerIndex.Get(index); if (callbackList == null) { callbackList = new List <ExprPreviousMatchRecognizeNode>(); _callbacksPerIndex.Put(index, callbackList); } callbackList.Add(matchRecogPrevNode); } return(defineItemExpression); }
public String ToQueryPlan() { return("in-keyword multi-indexed single keyed lookup " + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(KeyExpr)); }
protected override AggregationMethodFactory ValidateAggregationChild(ExprValidationContext validationContext) { var positionalParams = base.PositionalParams; if (positionalParams.Length == 0) { throw new ExprValidationException( "The rate aggregation function minimally requires a numeric constant or expression as a parameter."); } var first = positionalParams[0]; if (first.IsConstantResult) { const string message = "The rate aggregation function requires a numeric constant or time period as the first parameter in the constant-value notation"; long intervalTime; if (first is ExprTimePeriod period) { double secInterval = period.EvaluateAsSeconds( null, true, validationContext.ExprEvaluatorContext); intervalTime = validationContext.EngineImportService.TimeAbacus.DeltaForSecondsDouble(secInterval); } else if (ExprNodeUtility.IsConstantValueExpr(first)) { if (!first.ExprEvaluator.ReturnType.IsNumeric()) { throw new ExprValidationException(message); } var num = first.ExprEvaluator.Evaluate( new EvaluateParams(null, true, validationContext.ExprEvaluatorContext)); intervalTime = validationContext.EngineImportService.TimeAbacus.DeltaForSecondsNumber(num); } else { throw new ExprValidationException(message); } var optionalFilter = this.OptionalFilter; if (optionalFilter == null) { this.PositionalParams = ExprNodeUtility.EMPTY_EXPR_ARRAY; } else { this.PositionalParams = new ExprNode[] { optionalFilter }; } return (validationContext.EngineImportService.AggregationFactoryFactory.MakeRate( validationContext.StatementExtensionSvcContext, this, true, intervalTime, validationContext.TimeProvider, validationContext.EngineImportService.TimeAbacus)); } const string messageX = "The rate aggregation function requires a property or expression returning a non-constant long-type value as the first parameter in the timestamp-property notation"; Type boxedParamOne = first.ExprEvaluator.ReturnType.GetBoxedType(); if (boxedParamOne != typeof(long?)) { throw new ExprValidationException(messageX); } if (first.IsConstantResult) { throw new ExprValidationException(messageX); } if (first is ExprTimestampNode) { throw new ExprValidationException( "The rate aggregation function does not allow the current engine timestamp as a parameter"); } if (((positionalParams.Length == 2) && (this.OptionalFilter == null)) || ((positionalParams.Length > 2) && (this.OptionalFilter != null))) { if (!TypeHelper.IsNumeric(positionalParams[1].ExprEvaluator.ReturnType)) { throw new ExprValidationException( "The rate aggregation function accepts an expression returning a numeric value to accumulate as an optional second parameter"); } } bool hasDataWindows = ExprNodeUtility.HasRemoveStreamForAggregations( first, validationContext.StreamTypeService, validationContext.IsResettingAggregations); if (!hasDataWindows) { throw new ExprValidationException( "The rate aggregation function in the timestamp-property notation requires data windows"); } return (validationContext.EngineImportService.AggregationFactoryFactory.MakeRate( validationContext.StatementExtensionSvcContext, this, false, -1, validationContext.TimeProvider, validationContext.EngineImportService.TimeAbacus)); }
private ExprAggregateNode ValidateAggregationExpr( ExprNode columnExpressionType, EventType optionalProvidedType, EPServicesContext services, StatementContext statementContext) { // determine validation context types and istream/irstream EventType[] types; string[] streamNames; bool[] istreamOnly; if (optionalProvidedType != null) { types = new EventType[] { optionalProvidedType }; streamNames = new string[] { types[0].Name }; istreamOnly = new bool[] { false }; // always false (expected to be bound by data window), use "ever"-aggregation functions otherwise } else { types = new EventType[0]; streamNames = new string[0]; istreamOnly = new bool[0]; } var streamTypeService = new StreamTypeServiceImpl(types, streamNames, istreamOnly, services.EngineURI, false); var validationContext = new ExprValidationContext( statementContext.Container, streamTypeService, statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, new ExprEvaluatorContextStatement(statementContext, false), statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, false, false, null, false); // substitute parameter nodes foreach (var childNode in columnExpressionType.ChildNodes.ToArray()) { if (childNode is ExprIdentNode) { var identNode = (ExprIdentNode)childNode; var propname = identNode.FullUnresolvedName.Trim(); var clazz = TypeHelper.GetTypeForSimpleName(propname); if (propname.ToLower().Trim() == "object") { clazz = typeof(object); } EngineImportException ex = null; if (clazz == null) { try { clazz = services.EngineImportService.ResolveType(propname, false); } catch (EngineImportException e) { ex = e; } } if (clazz != null) { var typeNode = new ExprTypedNoEvalNode(propname, clazz); ExprNodeUtility.ReplaceChildNode(columnExpressionType, identNode, typeNode); } else { if (optionalProvidedType == null) { if (ex != null) { throw new ExprValidationException("Failed to resolve type '" + propname + "': " + ex.Message, ex); } throw new ExprValidationException("Failed to resolve type '" + propname + "'"); } } } } // validate var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.CREATETABLECOLUMN, columnExpressionType, validationContext); if (!(validated is ExprAggregateNode)) { throw new ExprValidationException("Expression '" + validated.ToExpressionStringMinPrecedenceSafe() + "' is not an aggregation"); } return((ExprAggregateNode)validated); }
public override void Accept(ExprNodeVisitorWithParent visitor) { base.Accept(visitor); ExprNodeUtility.AcceptChain(visitor, _chainSpec, this); }
public override EPPreparedExecuteIUDSingleStreamExec GetExecutor(FilterSpecCompiled filter, string aliasName) { var selectNoWildcard = NamedWindowOnMergeHelper.CompileSelectNoWildcard(UuidGenerator.Generate(), StatementSpec.SelectClauseSpec.SelectExprList); StreamTypeService streamTypeService = new StreamTypeServiceImpl(StatementContext.EngineURI, true); var exprEvaluatorContextStatement = new ExprEvaluatorContextStatement(StatementContext, true); // assign names var validationContext = new ExprValidationContext( streamTypeService, StatementContext.MethodResolutionService, null, StatementContext.TimeProvider, StatementContext.VariableService, StatementContext.TableService, exprEvaluatorContextStatement, StatementContext.EventAdapterService, StatementContext.StatementName, StatementContext.StatementId, StatementContext.Annotations, StatementContext.ContextDescriptor, StatementContext.ScriptingService, false, false, true, false, null, false); // determine whether column names are provided // if the "values" keyword was used, allow sequential automatic name assignment string[] assignedSequentialNames = null; if (StatementSpec.InsertIntoDesc.ColumnNames.IsEmpty()) { var insert = (FireAndForgetSpecInsert)StatementSpec.FireAndForgetSpec; if (insert.IsUseValuesKeyword) { assignedSequentialNames = Processor.EventTypePublic.PropertyNames; } } var count = -1; foreach (var compiled in StatementSpec.SelectClauseSpec.SelectExprList) { count++; if (compiled is SelectClauseExprCompiledSpec) { var expr = (SelectClauseExprCompiledSpec)compiled; ExprNode validatedExpression = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.SELECT, expr.SelectExpression, validationContext); expr.SelectExpression = validatedExpression; if (expr.AssignedName == null) { if (expr.ProvidedName == null) { if (assignedSequentialNames != null && count < assignedSequentialNames.Length) { expr.AssignedName = assignedSequentialNames[count]; } else { expr.AssignedName = ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(expr.SelectExpression); } } else { expr.AssignedName = expr.ProvidedName; } } } } EventType optionalInsertIntoEventType = Processor.EventTypeResultSetProcessor; var selectExprEventTypeRegistry = new SelectExprEventTypeRegistry(StatementContext.StatementName, StatementContext.StatementEventTypeRef); var insertHelper = SelectExprProcessorFactory.GetProcessor( Collections.SingletonList(0), selectNoWildcard.ToArray(), false, StatementSpec.InsertIntoDesc, optionalInsertIntoEventType, null, streamTypeService, StatementContext.EventAdapterService, StatementContext.StatementResultService, StatementContext.ValueAddEventService, selectExprEventTypeRegistry, StatementContext.MethodResolutionService, exprEvaluatorContextStatement, StatementContext.VariableService, StatementContext.ScriptingService, StatementContext.TableService, StatementContext.TimeProvider, StatementContext.EngineURI, StatementContext.StatementId, StatementContext.StatementName, StatementContext.Annotations, StatementContext.ContextDescriptor, StatementContext.ConfigSnapshot, null, StatementContext.NamedWindowMgmtService, null, null); return(new EPPreparedExecuteIUDSingleStreamExecInsert(exprEvaluatorContextStatement, insertHelper, StatementSpec.TableNodes, Services)); }
public override void AcceptChildnodes(ExprNodeVisitorWithParent visitor, ExprNode parent) { base.AcceptChildnodes(visitor, parent); ExprNodeUtility.AcceptChain(visitor, _chainSpec, this); }
public SubordInKeywordMultiTableLookupStrategyFactory(bool isNWOnTrigger, int streamCountOuter, ExprNode exprNode) { StreamCountOuter = streamCountOuter; Evaluator = exprNode.ExprEvaluator; IsNWOnTrigger = isNWOnTrigger; StrategyDesc = new LookupStrategyDesc(LookupStrategyType.INKEYWORDMULTIIDX, new String[] { ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(exprNode) }); }
public String ToQueryPlan() { return(GetType().Name + " evaluators " + ExprNodeUtility.PrintEvaluators(_evaluators)); }
public override void ToPrecedenceFreeEPL(TextWriter writer) { writer.Write("new "); writer.Write(_classIdent); ExprNodeUtility.ToExpressionStringParams(writer, this.ChildNodes); }
private static String GetPatternQuantifierExpressionText(ExprNode exprNode) { return("pattern quantifier '" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(exprNode) + "'"); }
public override void ToPrecedenceFreeEPL(TextWriter writer) { ExprNodeUtility.ToExpressionStringWFunctionName("grouping_id", ChildNodes, writer); }
/// <summary> /// Constructs indexing and lookup strategy for a given relationship that a historical stream may have with another /// stream (historical or not) that looks up into results of a poll of a historical stream. /// <para> /// The term "polled" refers to the assumed-historical stream. /// </para> /// </summary> /// <param name="queryGraph">relationship representation of where-clause filter and outer join on-expressions</param> /// <param name="polledViewType">the event type of the historical that is indexed</param> /// <param name="streamViewType">the event type of the stream looking up in indexes</param> /// <param name="polledViewStreamNum">the stream number of the historical that is indexed</param> /// <param name="streamViewStreamNum">the stream number of the historical that is looking up</param> /// <returns>indexing and lookup strategy pair</returns> public static Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy> DetermineIndexing( QueryGraph queryGraph, EventType polledViewType, EventType streamViewType, int polledViewStreamNum, int streamViewStreamNum) { var queryGraphValue = queryGraph.GetGraphValue(streamViewStreamNum, polledViewStreamNum); var hashKeysAndIndes = queryGraphValue.HashKeyProps; var rangeKeysAndIndex = queryGraphValue.RangeProps; // index and key property names var hashKeys = hashKeysAndIndes.Keys; var hashIndexes = hashKeysAndIndes.Indexed; var rangeKeys = rangeKeysAndIndex.Keys; var rangeIndexes = rangeKeysAndIndex.Indexed; // If the analysis revealed no join columns, must use the brute-force full table scan if (hashKeys.IsEmpty() && rangeKeys.IsEmpty()) { var inKeywordSingles = queryGraphValue.InKeywordSingles; if (inKeywordSingles != null && inKeywordSingles.Indexed.Length != 0) { var indexed = inKeywordSingles.Indexed[0]; var lookup = inKeywordSingles.Key[0]; var strategy = new HistoricalIndexLookupStrategyInKeywordSingle( streamViewStreamNum, lookup.KeyExprs); var indexing = new PollResultIndexingStrategyIndexSingle( polledViewStreamNum, polledViewType, indexed); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } var multis = queryGraphValue.InKeywordMulti; if (!multis.IsEmpty()) { var multi = multis[0]; var strategy = new HistoricalIndexLookupStrategyInKeywordMulti( streamViewStreamNum, multi.Key.KeyExpr); var indexing = new PollResultIndexingStrategyIndexSingleArray( polledViewStreamNum, polledViewType, ExprNodeUtility.GetIdentResolvedPropertyNames(multi.Indexed)); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>( new HistoricalIndexLookupStrategyNoIndex(), new PollResultIndexingStrategyNoIndex())); } var keyCoercionTypes = CoercionUtil.GetCoercionTypesHash( new EventType[] { streamViewType, polledViewType }, 0, 1, hashKeys, hashIndexes); if (rangeKeys.IsEmpty()) { // No coercion if (!keyCoercionTypes.IsCoerce) { if (hashIndexes.Count == 1) { var indexing = new PollResultIndexingStrategyIndexSingle( polledViewStreamNum, polledViewType, hashIndexes[0]); var strategy = new HistoricalIndexLookupStrategyIndexSingle(streamViewStreamNum, hashKeys[0]); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } else { var indexing = new PollResultIndexingStrategyIndex( polledViewStreamNum, polledViewType, hashIndexes); var strategy = new HistoricalIndexLookupStrategyIndex( streamViewType, streamViewStreamNum, hashKeys); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } } // With coercion, same lookup strategy as the index coerces if (hashIndexes.Count == 1) { var indexing = new PollResultIndexingStrategyIndexCoerceSingle( polledViewStreamNum, polledViewType, hashIndexes[0], keyCoercionTypes.CoercionTypes[0]); var strategy = new HistoricalIndexLookupStrategyIndexSingle(streamViewStreamNum, hashKeys[0]); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } else { var indexing = new PollResultIndexingStrategyIndexCoerce( polledViewStreamNum, polledViewType, hashIndexes, keyCoercionTypes.CoercionTypes); var strategy = new HistoricalIndexLookupStrategyIndex(streamViewType, streamViewStreamNum, hashKeys); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } } else { var rangeCoercionTypes = CoercionUtil.GetCoercionTypesRange( new EventType[] { streamViewType, polledViewType }, 1, rangeIndexes, rangeKeys); if (rangeKeys.Count == 1 && hashKeys.Count == 0) { var rangeCoercionType = rangeCoercionTypes.IsCoerce ? rangeCoercionTypes.CoercionTypes[0] : null; var indexing = new PollResultIndexingStrategySorted( polledViewStreamNum, polledViewType, rangeIndexes[0], rangeCoercionType); var strategy = new HistoricalIndexLookupStrategySorted(streamViewStreamNum, rangeKeys[0]); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } else { var indexing = new PollResultIndexingStrategyComposite( polledViewStreamNum, polledViewType, hashIndexes, keyCoercionTypes.CoercionTypes, rangeIndexes, rangeCoercionTypes.CoercionTypes); var strategy = new HistoricalIndexLookupStrategyComposite( streamViewStreamNum, hashKeys, keyCoercionTypes.CoercionTypes, rangeKeys, rangeCoercionTypes.CoercionTypes); return(new Pair <HistoricalIndexLookupStrategy, PollResultIndexingStrategy>(strategy, indexing)); } } }
public override void ToPrecedenceFreeEPL(TextWriter writer) { ExprNodeUtility.ToExpressionString(_chainSpec, writer, false, _functionName); }
public static ExprNode RewriteOrToInIfApplicable(ExprNode constituent) { if (!(constituent is ExprOrNode) || constituent.ChildNodes.Count < 2) { return(constituent); } // check eligibility var childNodes = constituent.ChildNodes; foreach (var child in childNodes) { if (!(child is ExprEqualsNode)) { return(constituent); } var equalsNode = (ExprEqualsNode)child; if (equalsNode.IsIs || equalsNode.IsNotEquals) { return(constituent); } } // find common-expression node ExprNode commonExpressionNode; var lhs = childNodes[0].ChildNodes[0]; var rhs = childNodes[0].ChildNodes[1]; if (ExprNodeUtility.DeepEquals(lhs, rhs, false)) { return(constituent); } if (IsExprExistsInAllEqualsChildNodes(childNodes, lhs)) { commonExpressionNode = lhs; } else if (IsExprExistsInAllEqualsChildNodes(childNodes, rhs)) { commonExpressionNode = rhs; } else { return(constituent); } // build node var @in = new ExprInNodeImpl(false); @in.AddChildNode(commonExpressionNode); for (var i = 0; i < constituent.ChildNodes.Count; i++) { var child = constituent.ChildNodes[i]; var nodeindex = ExprNodeUtility.DeepEquals(commonExpressionNode, childNodes[i].ChildNodes[0], false) ? 1 : 0; @in.AddChildNode(child.ChildNodes[nodeindex]); } // validate try { @in.ValidateWithoutContext(); } catch (ExprValidationException) { return(constituent); } return(@in); }
public override ExprNode Validate(ExprValidationContext validationContext) { ExprNodeUtility.Validate(ExprNodeOrigin.PLUGINSINGLEROWPARAM, _chainSpec, validationContext); // get first chain item var chainList = new List <ExprChainedSpec>(_chainSpec); var firstItem = chainList.DeleteAt(0); // Get the types of the parameters for the first invocation var allowWildcard = validationContext.StreamTypeService.EventTypes.Length == 1; EventType streamZeroType = null; if (validationContext.StreamTypeService.EventTypes.Length > 0) { streamZeroType = validationContext.StreamTypeService.EventTypes[0]; } var staticMethodDesc = ExprNodeUtility.ResolveMethodAllowWildcardAndStream( _clazz.FullName, null, firstItem.Name, firstItem.Parameters, validationContext.EngineImportService, validationContext.EventAdapterService, validationContext.StatementId, allowWildcard, streamZeroType, new ExprNodeUtilResolveExceptionHandlerDefault(firstItem.Name, true), _functionName, validationContext.TableService, validationContext.StreamTypeService.EngineURIQualifier); var allowValueCache = true; switch (_config.ValueCache) { case ValueCacheEnum.DISABLED: _isReturnsConstantResult = false; allowValueCache = false; break; case ValueCacheEnum.CONFIGURED: _isReturnsConstantResult = validationContext.EngineImportService.IsUdfCache && staticMethodDesc.IsAllConstants && chainList.IsEmpty(); allowValueCache = validationContext.EngineImportService.IsUdfCache; break; case ValueCacheEnum.ENABLED: _isReturnsConstantResult = staticMethodDesc.IsAllConstants && chainList.IsEmpty(); break; default: throw new IllegalStateException("Invalid value cache code " + _config.ValueCache); } // this may return a pair of null if there is no lambda or the result cannot be wrapped for lambda-function use var optionalLambdaWrap = ExprDotStaticMethodWrapFactory.Make( staticMethodDesc.ReflectionMethod, validationContext.EventAdapterService, chainList, _config.OptionalEventTypeName); var typeInfo = optionalLambdaWrap != null ? optionalLambdaWrap.TypeInfo : EPTypeHelper.SingleValue(staticMethodDesc.ReflectionMethod.ReturnType); var eval = ExprDotNodeUtility.GetChainEvaluators(-1, typeInfo, chainList, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic()).ChainWithUnpack; _evaluator = new ExprDotEvalStaticMethod( validationContext.StatementName, _clazz.FullName, staticMethodDesc.FastMethod, staticMethodDesc.ChildEvals, allowValueCache && staticMethodDesc.IsAllConstants, optionalLambdaWrap, eval, _config.IsRethrowExceptions, null); // If caching the result, evaluate now and return the result. if (_isReturnsConstantResult) { var result = _evaluator.Evaluate(new EvaluateParams(null, true, null)); _evaluator = new ProxyExprEvaluator { ProcEvaluate = args => { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().QExprPlugInSingleRow(staticMethodDesc.ReflectionMethod); InstrumentationHelper.Get().AExprPlugInSingleRow(result); } return(result); }, ReturnType = staticMethodDesc.FastMethod.ReturnType }; } return(null); }
private static FilterSpecParam HandleEqualsAndRelOp( ExprNode constituent, IDictionary <string, Pair <EventType, string> > arrayEventTypes, ExprEvaluatorContext exprEvaluatorContext, string statementName) { FilterOperator op; if (constituent is ExprEqualsNode) { var equalsNode = (ExprEqualsNode)constituent; if (!equalsNode.IsIs) { op = FilterOperator.EQUAL; if (equalsNode.IsNotEquals) { op = FilterOperator.NOT_EQUAL; } } else { op = FilterOperator.IS; if (equalsNode.IsNotEquals) { op = FilterOperator.IS_NOT; } } } else { var relNode = (ExprRelationalOpNode)constituent; switch (relNode.RelationalOpEnum) { case RelationalOpEnum.GT: op = FilterOperator.GREATER; break; case RelationalOpEnum.LT: op = FilterOperator.LESS; break; case RelationalOpEnum.LE: op = FilterOperator.LESS_OR_EQUAL; break; case RelationalOpEnum.GE: op = FilterOperator.GREATER_OR_EQUAL; break; default: throw new IllegalStateException("Operator '" + relNode.RelationalOpEnum + "' not mapped"); } } var left = constituent.ChildNodes[0]; var right = constituent.ChildNodes[1]; // check identifier and constant combination if ((ExprNodeUtility.IsConstantValueExpr(right)) && (left is ExprFilterOptimizableNode)) { var filterOptimizableNode = (ExprFilterOptimizableNode)left; if (filterOptimizableNode.IsFilterLookupEligible) { var constantNode = (ExprConstantNode)right; var lookupable = filterOptimizableNode.FilterLookupable; var constant = constantNode.GetConstantValue(exprEvaluatorContext); constant = HandleConstantsCoercion(lookupable, constant); return(new FilterSpecParamConstant(lookupable, op, constant)); } } if ((ExprNodeUtility.IsConstantValueExpr(left)) && (right is ExprFilterOptimizableNode)) { var filterOptimizableNode = (ExprFilterOptimizableNode)right; if (filterOptimizableNode.IsFilterLookupEligible) { var constantNode = (ExprConstantNode)left; var lookupable = filterOptimizableNode.FilterLookupable; var constant = constantNode.GetConstantValue(exprEvaluatorContext); constant = HandleConstantsCoercion(lookupable, constant); var opReversed = op.IsComparisonOperator() ? op.ReversedRelationalOp() : op; return(new FilterSpecParamConstant(lookupable, opReversed, constant)); } } // check identifier and expression containing other streams if ((left is ExprIdentNode) && (right is ExprIdentNode)) { var identNodeLeft = (ExprIdentNode)left; var identNodeRight = (ExprIdentNode)right; if ((identNodeLeft.StreamId == 0) && (identNodeLeft.IsFilterLookupEligible) && (identNodeRight.StreamId != 0)) { return(HandleProperty(op, identNodeLeft, identNodeRight, arrayEventTypes, statementName)); } if ((identNodeRight.StreamId == 0) && (identNodeRight.IsFilterLookupEligible) && (identNodeLeft.StreamId != 0)) { op = GetReversedOperator(constituent, op); // reverse operators, as the expression is "stream1.prop xyz stream0.prop" return(HandleProperty(op, identNodeRight, identNodeLeft, arrayEventTypes, statementName)); } } if ((left is ExprFilterOptimizableNode) && (right is ExprContextPropertyNode)) { var filterOptimizableNode = (ExprFilterOptimizableNode)left; var ctxNode = (ExprContextPropertyNode)right; var lookupable = filterOptimizableNode.FilterLookupable; if (filterOptimizableNode.IsFilterLookupEligible) { var numberCoercer = GetNumberCoercer(lookupable.ReturnType, ctxNode.ReturnType, lookupable.Expression); return(new FilterSpecParamContextProp(lookupable, op, ctxNode.PropertyName, ctxNode.Getter, numberCoercer)); } } if ((left is ExprContextPropertyNode) && (right is ExprFilterOptimizableNode)) { var filterOptimizableNode = (ExprFilterOptimizableNode)right; var ctxNode = (ExprContextPropertyNode)left; var lookupable = filterOptimizableNode.FilterLookupable; if (filterOptimizableNode.IsFilterLookupEligible) { op = GetReversedOperator(constituent, op); // reverse operators, as the expression is "stream1.prop xyz stream0.prop" var numberCoercer = GetNumberCoercer(lookupable.ReturnType, ctxNode.ReturnType, lookupable.Expression); return(new FilterSpecParamContextProp(lookupable, op, ctxNode.PropertyName, ctxNode.Getter, numberCoercer)); } } return(null); }
public override void Accept(ExprNodeVisitor visitor) { base.Accept(visitor); ExprNodeUtility.AcceptChain(visitor, _chainSpec); }
/// <summary> /// Creates a method-invocation polling view for use as a stream that calls a method, or pulls results from cache. /// </summary> /// <param name="streamNumber">the stream number</param> /// <param name="methodStreamSpec">defines the class and method to call</param> /// <param name="eventAdapterService">for creating event types and events</param> /// <param name="epStatementAgentInstanceHandle">for time-based callbacks</param> /// <param name="engineImportService">for resolving configurations</param> /// <param name="schedulingService">for scheduling callbacks in expiry-time based caches</param> /// <param name="scheduleBucket">for schedules within the statement</param> /// <param name="exprEvaluatorContext">expression evaluation context</param> /// <param name="variableService">variable service</param> /// <param name="statementContext">statement context</param> /// <param name="contextName">context name</param> /// <param name="dataCacheFactory">factory for cache</param> /// <exception cref="ExprValidationException"> /// if the expressions cannot be validated or the method descriptor /// has incorrect class and method names, or parameter number and types don't match /// </exception> /// <returns>pollable view</returns> public static HistoricalEventViewable CreatePollMethodView( int streamNumber, MethodStreamSpec methodStreamSpec, EventAdapterService eventAdapterService, EPStatementAgentInstanceHandle epStatementAgentInstanceHandle, EngineImportService engineImportService, SchedulingService schedulingService, ScheduleBucket scheduleBucket, ExprEvaluatorContext exprEvaluatorContext, VariableService variableService, string contextName, DataCacheFactory dataCacheFactory, StatementContext statementContext) { VariableMetaData variableMetaData = variableService.GetVariableMetaData(methodStreamSpec.ClassName); MethodPollingExecStrategyEnum strategy; VariableReader variableReader = null; string variableName = null; MethodInfo methodReflection = null; object invocationTarget = null; string eventTypeNameProvidedUDFOrScript = null; // see if this is a script in the from-clause ExprNodeScript scriptExpression = null; if (methodStreamSpec.ClassName == null && methodStreamSpec.MethodName != null) { var scriptsByName = statementContext.ExprDeclaredService.GetScriptsByName(methodStreamSpec.MethodName); if (scriptsByName != null) { scriptExpression = ExprDeclaredHelper.GetExistsScript( statementContext.ConfigSnapshot.EngineDefaults.Scripts.DefaultDialect, methodStreamSpec.MethodName, methodStreamSpec.Expressions, scriptsByName, statementContext.ExprDeclaredService); } } try { if (scriptExpression != null) { eventTypeNameProvidedUDFOrScript = scriptExpression.EventTypeNameAnnotation; strategy = MethodPollingExecStrategyEnum.TARGET_SCRIPT; ExprNodeUtility.ValidateSimpleGetSubtree( ExprNodeOrigin.METHODINVJOIN, scriptExpression, statementContext, null, false); } else if (variableMetaData != null) { variableName = variableMetaData.VariableName; if (variableMetaData.ContextPartitionName != null) { if (contextName == null || !contextName.Equals(variableMetaData.ContextPartitionName)) { throw new ExprValidationException( "Variable by name '" + variableMetaData.VariableName + "' has been declared for context '" + variableMetaData.ContextPartitionName + "' and can only be used within the same context"); } strategy = MethodPollingExecStrategyEnum.TARGET_VAR_CONTEXT; variableReader = null; invocationTarget = null; } else { variableReader = variableService.GetReader( methodStreamSpec.ClassName, EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID); if (variableMetaData.IsConstant) { invocationTarget = variableReader.Value; if (invocationTarget is EventBean) { invocationTarget = ((EventBean)invocationTarget).Underlying; } strategy = MethodPollingExecStrategyEnum.TARGET_CONST; } else { invocationTarget = null; strategy = MethodPollingExecStrategyEnum.TARGET_VAR; } } methodReflection = engineImportService.ResolveNonStaticMethodOverloadChecked( variableMetaData.VariableType, methodStreamSpec.MethodName); } else if (methodStreamSpec.ClassName == null) { // must be either UDF or script Pair <Type, EngineImportSingleRowDesc> udf = null; try { udf = engineImportService.ResolveSingleRow(methodStreamSpec.MethodName); } catch (EngineImportException ex) { throw new ExprValidationException( "Failed to find user-defined function '" + methodStreamSpec.MethodName + "': " + ex.Message, ex); } methodReflection = engineImportService.ResolveMethodOverloadChecked(udf.First, methodStreamSpec.MethodName); invocationTarget = null; variableReader = null; variableName = null; strategy = MethodPollingExecStrategyEnum.TARGET_CONST; eventTypeNameProvidedUDFOrScript = udf.Second.OptionalEventTypeName; } else { methodReflection = engineImportService.ResolveMethodOverloadChecked(methodStreamSpec.ClassName, methodStreamSpec.MethodName); invocationTarget = null; variableReader = null; variableName = null; strategy = MethodPollingExecStrategyEnum.TARGET_CONST; } } catch (ExprValidationException) { throw; } catch (Exception e) { throw new ExprValidationException(e.Message, e); } Type methodProviderClass = null; Type beanClass; IDictionary <string, object> oaType = null; IDictionary <string, object> mapType = null; bool isCollection = false; bool isIterator = false; EventType eventType; EventType eventTypeWhenMethodReturnsEventBeans = null; bool isStaticMethod = false; if (methodReflection != null) { methodProviderClass = methodReflection.DeclaringType; isStaticMethod = variableMetaData == null; // Determine object type returned by method beanClass = methodReflection.ReturnType; if ((beanClass == typeof(void)) || (beanClass.IsBuiltinDataType())) { throw new ExprValidationException( "Invalid return type for static method '" + methodReflection.Name + "' of class '" + methodStreamSpec.ClassName + "', expecting a class"); } if (methodReflection.ReturnType.IsArray && methodReflection.ReturnType.GetElementType() != typeof(EventBean)) { beanClass = methodReflection.ReturnType.GetElementType(); } Type collectionClass = null; Type iteratorClass = null; if (!beanClass.IsGenericDictionary()) { isCollection = beanClass.IsGenericCollection(); if (isCollection) { collectionClass = TypeHelper.GetGenericReturnType(methodReflection, true); beanClass = collectionClass; } isIterator = beanClass.IsGenericEnumerator() && !beanClass.IsGenericDictionary(); if (isIterator) { iteratorClass = TypeHelper.GetGenericReturnType(methodReflection, true); beanClass = iteratorClass; } } // If the method returns a Map, look up the map type string mapTypeName = null; if ((methodReflection.ReturnType.IsGenericStringDictionary()) || (methodReflection.ReturnType.IsArray && methodReflection.ReturnType.GetElementType().IsGenericStringDictionary()) || (isCollection && collectionClass.IsImplementsInterface(typeof(Map))) || (isIterator && iteratorClass.IsImplementsInterface(typeof(Map)))) { MethodMetadataDesc metadata; if (variableMetaData != null) { metadata = GetCheckMetadataVariable( methodStreamSpec.MethodName, variableMetaData, variableReader, engineImportService, typeof(Map)); } else { metadata = GetCheckMetadataNonVariable( methodStreamSpec.MethodName, methodStreamSpec.ClassName, engineImportService, typeof(Map)); } mapTypeName = metadata.TypeName; mapType = (IDictionary <string, object>)metadata.TypeMetadata; } // If the method returns an object[] or object[][], look up the type information string oaTypeName = null; if (methodReflection.ReturnType == typeof(object[]) || methodReflection.ReturnType == typeof(object[][]) || (isCollection && collectionClass == typeof(object[])) || (isIterator && iteratorClass == typeof(object[]))) { MethodMetadataDesc metadata; if (variableMetaData != null) { metadata = GetCheckMetadataVariable( methodStreamSpec.MethodName, variableMetaData, variableReader, engineImportService, typeof(IDictionary <string, object>)); } else { metadata = GetCheckMetadataNonVariable( methodStreamSpec.MethodName, methodStreamSpec.ClassName, engineImportService, typeof(IDictionary <string, object>)); } oaTypeName = metadata.TypeName; oaType = (IDictionary <string, object>)metadata.TypeMetadata; } // Determine event type from class and method name // If the method returns EventBean[], require the event type if ((methodReflection.ReturnType.IsArray && methodReflection.ReturnType.GetElementType() == typeof(EventBean)) || (isCollection && collectionClass == typeof(EventBean)) || (isIterator && iteratorClass == typeof(EventBean))) { string typeName = methodStreamSpec.EventTypeName == null ? eventTypeNameProvidedUDFOrScript : methodStreamSpec.EventTypeName; eventType = EventTypeUtility.RequireEventType( "Method", methodReflection.Name, eventAdapterService, typeName); eventTypeWhenMethodReturnsEventBeans = eventType; } else if (mapType != null) { eventType = eventAdapterService.AddNestableMapType( mapTypeName, mapType, null, false, true, true, false, false); } else if (oaType != null) { eventType = eventAdapterService.AddNestableObjectArrayType( oaTypeName, oaType, null, false, true, true, false, false, false, null); } else { eventType = eventAdapterService.AddBeanType(beanClass.GetDefaultTypeName(), beanClass, false, true, true); } // the @type is only allowed in conjunction with EventBean return types if (methodStreamSpec.EventTypeName != null && eventTypeWhenMethodReturnsEventBeans == null) { throw new ExprValidationException(EventTypeUtility.DisallowedAtTypeMessage()); } } else { string eventTypeName = methodStreamSpec.EventTypeName == null ? scriptExpression.EventTypeNameAnnotation : methodStreamSpec.EventTypeName; eventType = EventTypeUtility.RequireEventType( "Script", scriptExpression.Script.Name, eventAdapterService, eventTypeName); } // get configuration for cache string configName = methodProviderClass != null ? methodProviderClass.FullName : methodStreamSpec.MethodName; ConfigurationMethodRef configCache = engineImportService.GetConfigurationMethodRef(configName); if (configCache == null) { configCache = engineImportService.GetConfigurationMethodRef(configName); } ConfigurationDataCache dataCacheDesc = (configCache != null) ? configCache.DataCacheDesc : null; DataCache dataCache = dataCacheFactory.GetDataCache( dataCacheDesc, statementContext, epStatementAgentInstanceHandle, schedulingService, scheduleBucket, streamNumber); // metadata var meta = new MethodPollingViewableMeta( methodProviderClass, isStaticMethod, mapType, oaType, invocationTarget, strategy, isCollection, isIterator, variableReader, variableName, eventTypeWhenMethodReturnsEventBeans, scriptExpression); return(new MethodPollingViewable(methodStreamSpec, dataCache, eventType, exprEvaluatorContext, meta)); }
private void PopulateEvents(EventBean[] eventsPerStream, EventBean branch, int level, ICollection <EventBean[]> events, ExprEvaluatorContext exprEvaluatorContext) { try { var result = _containedEventEvals[level].GetFragment(branch, eventsPerStream, exprEvaluatorContext); if (_fragmentEventType[level].IsIndexed) { var fragments = (EventBean[])result; if (level == _lastLevel) { if (_whereClauses[level] != null) { foreach (var theEvent in fragments) { eventsPerStream[level + 1] = theEvent; if (ExprNodeUtility.ApplyFilterExpression(_whereClauses[level], eventsPerStream, exprEvaluatorContext)) { var eventsPerRow = new EventBean[_levels]; Array.Copy(eventsPerStream, 0, eventsPerRow, 0, _levels); events.Add(eventsPerRow); } } } else { foreach (var theEvent in fragments) { eventsPerStream[level + 1] = theEvent; var eventsPerRow = new EventBean[_levels]; Array.Copy(eventsPerStream, 0, eventsPerRow, 0, _levels); events.Add(eventsPerRow); } } } else { if (_whereClauses[level] != null) { foreach (var next in fragments) { eventsPerStream[level + 1] = next; if (ExprNodeUtility.ApplyFilterExpression(_whereClauses[level], eventsPerStream, exprEvaluatorContext)) { PopulateEvents(eventsPerStream, next, level + 1, events, exprEvaluatorContext); } } } else { foreach (var next in fragments) { eventsPerStream[level + 1] = next; PopulateEvents(eventsPerStream, next, level + 1, events, exprEvaluatorContext); } } } } else { var fragment = (EventBean)result; if (level == _lastLevel) { if (_whereClauses[level] != null) { eventsPerStream[level + 1] = fragment; if (ExprNodeUtility.ApplyFilterExpression(_whereClauses[level], eventsPerStream, exprEvaluatorContext)) { var eventsPerRow = new EventBean[_levels]; Array.Copy(eventsPerStream, 0, eventsPerRow, 0, _levels); events.Add(eventsPerRow); } } else { eventsPerStream[level + 1] = fragment; var eventsPerRow = new EventBean[_levels]; Array.Copy(eventsPerStream, 0, eventsPerRow, 0, _levels); events.Add(eventsPerRow); } } else { if (_whereClauses[level] != null) { eventsPerStream[level + 1] = fragment; if (ExprNodeUtility.ApplyFilterExpression(_whereClauses[level], eventsPerStream, exprEvaluatorContext)) { PopulateEvents(eventsPerStream, fragment, level + 1, events, exprEvaluatorContext); } } else { eventsPerStream[level + 1] = fragment; PopulateEvents(eventsPerStream, fragment, level + 1, events, exprEvaluatorContext); } } } } catch (Exception ex) { Log.Error("Unexpected error evaluating property expression for event of type '" + branch.EventType.Name + "' and property '" + _propertyNames[level + 1] + "': " + ex.Message, ex); } }