Пример #1
0
 public override void Accept(ExprNodeVisitorWithParent visitor)
 {
     base.Accept(visitor);
     if (ChildNodes.Length == 0) {
         ExpressionBodyCopy.Accept(visitor);
     }
 }
Пример #2
0
 public override void AcceptChildnodes(
     ExprNodeVisitorWithParent visitor,
     ExprNode parent)
 {
     base.AcceptChildnodes(visitor, parent);
     if (visitor.IsVisit(this) && ChildNodes.Length == 0) {
         ExpressionBodyCopy.Accept(visitor);
     }
 }
Пример #3
0
 public void AcceptNoVisitParams(ExprNodeVisitorWithParent visitor) {
     base.Accept(visitor);
     if (ChildNodes.Length == 0) {
         ExpressionBodyCopy.Accept(visitor);
     }
 }
Пример #4
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            var prototype = PrototypeWVisibility;
            if (prototype.IsAlias) {
                try {
                    ExpressionBodyCopy = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.ALIASEXPRBODY,
                        ExpressionBodyCopy,
                        validationContext);
                }
                catch (ExprValidationException ex) {
                    var message = "Error validating expression alias '" + prototype.Name + "': " + ex.Message;
                    throw new ExprValidationException(message, ex);
                }

                forge = ExpressionBodyCopy.Forge;
                return null;
            }

            if (forge != null) {
                return null; // already evaluated
            }

            if (ChildNodes.Length > 0) {
                throw new IllegalStateException("Execution node has its own child nodes");
            }

            // validate chain
            IList<ExprNode> validated = new List<ExprNode>();
            foreach (var expr in ChainParameters) {
                validated.Add(
                    ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.DECLAREDEXPRPARAM,
                        expr,
                        validationContext));
            }

            ChainParameters = validated;

            // validate parameter count
            CheckParameterCount();

            // create context for expression body
            var eventTypes = new EventType[prototype.ParametersNames.Length];
            var streamNames = new string[prototype.ParametersNames.Length];
            var isIStreamOnly = new bool[prototype.ParametersNames.Length];
            var streamsIdsPerStream = new int[prototype.ParametersNames.Length];
            var allStreamIdsMatch = true;

            for (var i = 0; i < prototype.ParametersNames.Length; i++) {
                var parameter = ChainParameters[i];
                streamNames[i] = prototype.ParametersNames[i];

                if (parameter is ExprStreamUnderlyingNode) {
                    var und = (ExprStreamUnderlyingNode) parameter;
                    eventTypes[i] = validationContext.StreamTypeService.EventTypes[und.StreamId];
                    isIStreamOnly[i] = validationContext.StreamTypeService.IStreamOnly[und.StreamId];
                    streamsIdsPerStream[i] = und.StreamId;
                }
                else if (parameter is ExprWildcard) {
                    if (validationContext.StreamTypeService.EventTypes.Length != 1) {
                        throw new ExprValidationException(
                            "Expression '" +
                            prototype.Name +
                            "' only allows a wildcard parameter if there is a single stream available, please use a stream or tag name instead");
                    }

                    eventTypes[i] = validationContext.StreamTypeService.EventTypes[0];
                    isIStreamOnly[i] = validationContext.StreamTypeService.IStreamOnly[0];
                    streamsIdsPerStream[i] = 0;
                }
                else {
                    throw new ExprValidationException(
                        "Expression '" + prototype.Name + "' requires a stream name as a parameter");
                }

                if (streamsIdsPerStream[i] != i) {
                    allStreamIdsMatch = false;
                }
            }

            var streamTypeService = validationContext.StreamTypeService;
            var copyTypes = new StreamTypeServiceImpl(
                eventTypes,
                streamNames,
                isIStreamOnly,
                streamTypeService.IsOnDemandStreams,
                streamTypeService.IsOptionalStreams);
            copyTypes.RequireStreamNames = true;

            // validate expression body in this context
            try {
                var expressionBodyContext = new ExprValidationContext(copyTypes, validationContext);
                ExpressionBodyCopy = ExprNodeUtilityValidate.GetValidatedSubtree(
                    ExprNodeOrigin.DECLAREDEXPRBODY,
                    ExpressionBodyCopy,
                    expressionBodyContext);
            }
            catch (ExprValidationException ex) {
                var message = "Error validating expression declaration '" + prototype.Name + "': " + ex.Message;
                throw new ExprValidationException(message, ex);
            }

            // analyze child node
            var summaryVisitor = new ExprNodeSummaryVisitor();
            ExpressionBodyCopy.Accept(summaryVisitor);
            var isCache = !(summaryVisitor.HasAggregation || summaryVisitor.HasPreviousPrior);
            isCache &= validationContext.StatementCompileTimeService.Configuration.Compiler.Execution
                .IsEnabledDeclaredExprValueCache;

            // determine a suitable evaluation
            var audit = AuditEnum.EXPRDEF.GetAudit(validationContext.Annotations) != null;
            var statementName = validationContext.StatementName;
            if (ExpressionBodyCopy.Forge.ForgeConstantType.IsConstant) {
                // pre-evaluated
                forge = new ExprDeclaredForgeConstant(
                    this,
                    ExpressionBodyCopy.Forge.EvaluationType,
                    prototype,
                    ExpressionBodyCopy.Forge.ExprEvaluator.Evaluate(null, true, null),
                    audit,
                    statementName);
            }
            else if (prototype.ParametersNames.Length == 0 ||
                     allStreamIdsMatch && prototype.ParametersNames.Length == streamTypeService.EventTypes.Length) {
                forge = new ExprDeclaredForgeNoRewrite(this, ExpressionBodyCopy.Forge, isCache, audit, statementName);
            }
            else {
                forge = new ExprDeclaredForgeRewrite(
                    this,
                    ExpressionBodyCopy.Forge,
                    isCache,
                    streamsIdsPerStream,
                    audit,
                    statementName);
            }

            return null;
        }
Пример #5
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            this.exprValidationContext = validationContext;

            var prototype = PrototypeWVisibility;
            if (prototype.IsAlias) {
                if (!ChainParameters.IsEmpty()) {
                    throw new ExprValidationException("Expression '" + prototype.Name + " is an expression-alias and does not allow parameters");
                }
                try {
                    ExpressionBodyCopy = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.ALIASEXPRBODY,
                        ExpressionBodyCopy,
                        validationContext);
                }
                catch (ExprValidationException ex) {
                    var message = "Failed to validate expression alias '" + prototype.Name + "': " + ex.Message;
                    throw new ExprValidationException(message, ex);
                }

                forge = ExpressionBodyCopy.Forge;
                return null;
            }

            if (forge != null) {
                return null; // already evaluated
            }

            if (ChildNodes.Length > 0) {
                throw new IllegalStateException("Execution node has its own child nodes");
            }

            // validate chain
            IList<ExprNode> validated = new List<ExprNode>();
            foreach (var expr in ChainParameters) {
                validated.Add(
                    ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.DECLAREDEXPRPARAM,
                        expr,
                        validationContext));
            }

            ChainParameters = validated;

            // validate parameter count
            CheckParameterCount();

            // collect event and value (non-event) parameters
            List<int> valueParameters = new List<int>();
            List<int> eventParameters = new List<int>();
            for (int i = 0; i < prototype.ParametersNames.Length; i++) {
                ExprNode parameter = ChainParameters[i];
                if (parameter is ExprWildcard) {
                    if (validationContext.StreamTypeService.EventTypes.Length != 1) {
                        throw new ExprValidationException("Expression '" + prototype.Name + "' only allows a wildcard parameter if there is a single stream available, please use a stream or tag name instead");
                    }
                }
                if (IsEventProviding(parameter, validationContext)) {
                    eventParameters.Add(i);
                } else {
                    valueParameters.Add(i);
                }
            }

            // determine value event type for holding non-event parameter values, if any
            ObjectArrayEventType valueEventType = null;
            List<ExprNode> valueExpressions = new List<ExprNode>(valueParameters.Count);
            if (!valueParameters.IsEmpty()) {
                var valuePropertyTypes = new LinkedHashMap<string, object>();
                foreach (int index in valueParameters) {
                    String name = prototype.ParametersNames[index];
                    ExprNode expr = ChainParameters[index];
                    var result = Boxing.GetBoxedType(expr.Forge.EvaluationType);
                    valuePropertyTypes.Put(name, result);
                    valueExpressions.Add(expr);
                }

                valueEventType = ExprDotNodeUtility.MakeTransientOAType(
                    PrototypeWVisibility.Name,
                    valuePropertyTypes,
                    validationContext.StatementRawInfo,
                    validationContext.StatementCompileTimeService);
            }

            // create context for expression body
            int numEventTypes = eventParameters.Count + (valueEventType == null ? 0 : 1);
            EventType[] eventTypes = new EventType[numEventTypes];
            String[] streamNames = new String[numEventTypes];
            bool[] isIStreamOnly = new bool[numEventTypes];
            ExprEnumerationForge[] eventEnumerationForges = new ExprEnumerationForge[numEventTypes];
            allStreamIdsMatch = true;

            int offsetEventType = 0;
            if (valueEventType != null) {
                offsetEventType = 1;
                eventTypes[0] = valueEventType;
                streamNames[0] = INTERNAL_VALUE_STREAMNAME;
                isIStreamOnly[0] = true;
                allStreamIdsMatch = false;
            }

            bool forceOptionalStream = false;
            foreach (int index in eventParameters) {
                ExprNode parameter = ChainParameters[index];
                streamNames[offsetEventType] = prototype.ParametersNames[index];
                int streamId;
                bool istreamOnlyFlag;
                ExprEnumerationForge forge;

                if (parameter is ExprEnumerationForgeProvider) {
                    ExprEnumerationForgeProvider enumerationForgeProvider = (ExprEnumerationForgeProvider) parameter;
                    ExprEnumerationForgeDesc desc = enumerationForgeProvider.GetEnumerationForge(
                        validationContext.StreamTypeService, validationContext.ContextDescriptor);
                    forge = desc.Forge;
                    streamId = desc.DirectIndexStreamNumber;
                    istreamOnlyFlag = desc.IsIstreamOnly;
                } else {
                    forge = (ExprEnumerationForge) parameter.Forge;
                    istreamOnlyFlag = false;
                    streamId = -1;
                    forceOptionalStream = true; // since they may return null, i.e. subquery returning no row or multiple rows etc.
                }

                isIStreamOnly[offsetEventType] = istreamOnlyFlag;
                eventEnumerationForges[offsetEventType] = forge;
                eventTypes[offsetEventType] = forge.GetEventTypeSingle(validationContext.StatementRawInfo, validationContext.StatementCompileTimeService);

                if (streamId != index) {
                    allStreamIdsMatch = false;
                }
                offsetEventType++;
            }

            var streamTypeService = validationContext.StreamTypeService;
            var optionalStream = forceOptionalStream || streamTypeService.IsOptionalStreams;
            var copyTypes = new StreamTypeServiceImpl(
                eventTypes,
                streamNames,
                isIStreamOnly,
                streamTypeService.IsOnDemandStreams,
                optionalStream);

            copyTypes.RequireStreamNames = true;

            // validate expression body in this context
            try {
                var expressionBodyContext = new ExprValidationContext(copyTypes, validationContext);
                ExpressionBodyCopy = ExprNodeUtilityValidate.GetValidatedSubtree(
                    ExprNodeOrigin.DECLAREDEXPRBODY,
                    ExpressionBodyCopy,
                    expressionBodyContext);
            }
            catch (ExprValidationException ex) {
                var message = "Failed to validate expression declaration '" + prototype.Name + "': " + ex.Message;
                throw new ExprValidationException(message, ex);
            }

            // analyze child node
            var summaryVisitor = new ExprNodeSummaryVisitor();
            ExpressionBodyCopy.Accept(summaryVisitor);
            var isCache = !(summaryVisitor.HasAggregation || summaryVisitor.HasPreviousPrior);
            isCache &= validationContext.StatementCompileTimeService.Configuration.Compiler.Execution
                .IsEnabledDeclaredExprValueCache;

            // determine a suitable evaluation
            var audit = AuditEnum.EXPRDEF.GetAudit(validationContext.Annotations) != null;
            var statementName = validationContext.StatementName;
            if (ExpressionBodyCopy.Forge.ForgeConstantType.IsConstant) {
                // pre-evaluated
                forge = new ExprDeclaredForgeConstant(
                    this,
                    ExpressionBodyCopy.Forge.EvaluationType,
                    prototype,
                    ExpressionBodyCopy.Forge.ExprEvaluator.Evaluate(null, true, null),
                    audit,
                    statementName);
            }
            else if (valueEventType == null &&
                     prototype.ParametersNames.Length == 0 ||
                     allStreamIdsMatch && prototype.ParametersNames.Length == streamTypeService.EventTypes.Length) {
                forge = new ExprDeclaredForgeNoRewrite(
                    this, ExpressionBodyCopy.Forge, isCache, audit, statementName);
            }
            else if (valueEventType == null) {
                forge = new ExprDeclaredForgeRewrite(
                    this, ExpressionBodyCopy.Forge, isCache, eventEnumerationForges, audit, statementName);
            }
            else {
                // cache is always false
                forge = new ExprDeclaredForgeRewriteWValue(
                    this, ExpressionBodyCopy.Forge, false, audit, statementName, eventEnumerationForges, valueEventType, valueExpressions);
            }

            return null;
        }