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);
        }
示例#3
0
 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));
        }
示例#8
0
        /// <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);
            }
        }
示例#9
0
        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));
        }
示例#10
0
        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);
            }
        }
示例#11
0
        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);
        }
示例#12
0
 public String ToQueryPlan()
 {
     return("in-keyword multi-indexed single keyed lookup " + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(KeyExpr));
 }
示例#13
0
        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);
 }
示例#16
0
        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) });
 }
示例#19
0
 public String ToQueryPlan()
 {
     return(GetType().Name + " evaluators " + ExprNodeUtility.PrintEvaluators(_evaluators));
 }
示例#20
0
 public override void ToPrecedenceFreeEPL(TextWriter writer)
 {
     writer.Write("new ");
     writer.Write(_classIdent);
     ExprNodeUtility.ToExpressionStringParams(writer, this.ChildNodes);
 }
示例#21
0
 private static String GetPatternQuantifierExpressionText(ExprNode exprNode)
 {
     return("pattern quantifier '" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(exprNode) + "'");
 }
示例#22
0
 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);
            }
        }