Exemplo n.º 1
0
        private bool IsEventProviding(
            ExprNode parameter,
            ExprValidationContext validationContext)
        {
            if (parameter is ExprEnumerationForgeProvider) {
                ExprEnumerationForgeProvider provider = (ExprEnumerationForgeProvider) parameter;
                ExprEnumerationForgeDesc desc = provider.GetEnumerationForge(
                    validationContext.StreamTypeService,
                    validationContext.ContextDescriptor);

                EventType eventType = desc?.Forge.GetEventTypeSingle(validationContext.StatementRawInfo, validationContext.StatementCompileTimeService);
                return eventType != null;
            }

            ExprForge forge = parameter.Forge;
            ExprEnumerationForge enumerationForge = forge as ExprEnumerationForge;
            return enumerationForge?.GetEventTypeSingle(
                validationContext.StatementRawInfo, validationContext.StatementCompileTimeService) != null;
        }
Exemplo n.º 2
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;
        }