Esempio n. 1
0
        /// <summary>
        /// Check if the expression is minimal: does not have a subselect, aggregation and does not need view resources
        /// </summary>
        /// <param name="expression">to inspect</param>
        /// <returns>null if minimal, otherwise name of offending sub-expression</returns>
        public static string IsMinimalExpression(ExprNode expression)
        {
            ExprNodeSubselectDeclaredDotVisitor subselectVisitor = new ExprNodeSubselectDeclaredDotVisitor();
            expression.Accept(subselectVisitor);
            if (subselectVisitor.Subselects.Count > 0) {
                return "a subselect";
            }

            ExprNodeViewResourceVisitor viewResourceVisitor = new ExprNodeViewResourceVisitor();
            expression.Accept(viewResourceVisitor);
            if (viewResourceVisitor.ExprNodes.Count > 0) {
                return "a function that requires view resources (prior, prev)";
            }

            IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>();
            ExprAggregateNodeUtil.GetAggregatesBottomUp(expression, aggregateNodes);
            if (!aggregateNodes.IsEmpty()) {
                return "an aggregation function";
            }

            return null;
        }
Esempio n. 2
0
        public static StatementSpecCompiled Compile(
            StatementSpecRaw spec,
            Compilable compilable,
            bool isSubquery,
            bool isOnDemandQuery,
            Attribute[] annotations,
            IList<ExprSubselectNode> subselectNodes,
            IList<ExprTableAccessNode> tableAccessNodes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            IList<StreamSpecCompiled> compiledStreams;
            ISet<string> eventTypeReferences = new HashSet<string>();

            if (!isOnDemandQuery && spec.FireAndForgetSpec != null) {
                throw new StatementSpecCompileException(
                    "Provided EPL expression is an on-demand query expression (not a continuous query)",
                    compilable.ToEPL());
            }

            // If not using a join and not specifying a data window, make the where-clause, if present, the filter of the stream
            // if selecting using filter spec, and not subquery in where clause
            if (spec.StreamSpecs.Count == 1 &&
                spec.StreamSpecs[0] is FilterStreamSpecRaw &&
                spec.StreamSpecs[0].ViewSpecs.Length == 0 &&
                spec.WhereClause != null &&
                spec.OnTriggerDesc == null &&
                !isSubquery &&
                !isOnDemandQuery &&
                (tableAccessNodes == null || tableAccessNodes.IsEmpty())) {
                bool disqualified;
                ExprNode whereClause = spec.WhereClause;

                var visitorX = new ExprNodeSubselectDeclaredDotVisitor();
                whereClause.Accept(visitorX);
                disqualified = visitorX.Subselects.Count > 0 ||
                               HintEnum.DISABLE_WHEREEXPR_MOVETO_FILTER.GetHint(annotations) != null;

                if (!disqualified) {
                    var viewResourceVisitor = new ExprNodeViewResourceVisitor();
                    whereClause.Accept(viewResourceVisitor);
                    disqualified = viewResourceVisitor.ExprNodes.Count > 0;
                }

                if (!disqualified) {
                    spec.WhereClause = null;
                    var streamSpec = (FilterStreamSpecRaw) spec.StreamSpecs[0];
                    streamSpec.RawFilterSpec.FilterExpressions.Add(whereClause);
                }
            }

            // compile select-clause
            var selectClauseCompiled = CompileSelectClause(spec.SelectClauseSpec);

            // Determine subselects in filter streams, these may need special handling for locking
            var visitor = new ExprNodeSubselectDeclaredDotVisitor();
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkStreamSpecs(spec, visitor);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                subselectNode.IsFilterStreamSubselect = true;
            }

            // Determine subselects for compilation, and lambda-expression shortcut syntax for named windows
            visitor.Reset();
            GroupByClauseExpressions groupByRollupExpressions;
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(spec, visitor);

                var expressionCopier = new ExpressionCopier(
                    spec,
                    statementRawInfo.OptionalContextDescriptor,
                    compileTimeServices,
                    visitor);
                groupByRollupExpressions = GroupByExpressionHelper.GetGroupByRollupExpressions(
                    spec.GroupByExpressions,
                    spec.SelectClauseSpec,
                    spec.HavingClause,
                    spec.OrderByList,
                    expressionCopier);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            if (isSubquery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Invalid nested subquery, subquery-within-subquery is not supported",
                    compilable.ToEPL());
            }

            if (isOnDemandQuery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Subqueries are not a supported feature of on-demand queries",
                    compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                if (!subselectNodes.Contains(subselectNode)) {
                    subselectNodes.Add(subselectNode);
                }
            }

            // Compile subselects found
            var subselectNumber = 0;
            foreach (var subselect in subselectNodes) {
                StatementSpecRaw raw = subselect.StatementSpecRaw;
                var compiled = Compile(
                    raw,
                    compilable,
                    true,
                    isOnDemandQuery,
                    annotations,
                    Collections.GetEmptyList<ExprSubselectNode>(),
                    Collections.GetEmptyList<ExprTableAccessNode>(),
                    statementRawInfo,
                    compileTimeServices);
                subselect.SetStatementSpecCompiled(compiled, subselectNumber);
                subselectNumber++;
            }

            // Set table-access number
            var tableAccessNumber = 0;
            foreach (var tableAccess in tableAccessNodes) {
                tableAccess.TableAccessNumber = tableAccessNumber;
                tableAccessNumber++;
            }

            // compile each stream used
            try {
                compiledStreams = new List<StreamSpecCompiled>(spec.StreamSpecs.Count);
                var streamNum = 0;
                foreach (var rawSpec in spec.StreamSpecs) {
                    streamNum++;
                    var compiled = StreamSpecCompiler.Compile(
                        rawSpec,
                        eventTypeReferences,
                        spec.InsertIntoDesc != null,
                        spec.StreamSpecs.Count > 1,
                        false,
                        spec.OnTriggerDesc != null,
                        rawSpec.OptionalStreamName,
                        streamNum,
                        statementRawInfo,
                        compileTimeServices);
                    compiledStreams.Add(compiled);
                }
            }
            catch (ExprValidationException ex) {
                if (ex.Message == null) {
                    throw new StatementSpecCompileException(
                        "Unexpected exception compiling statement, please consult the log file and report the exception",
                        ex,
                        compilable.ToEPL());
                }

                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (EPException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (Exception ex) {
                var text = "Unexpected error compiling statement";
                Log.Error(text, ex);
                throw new StatementSpecCompileException(
                    text + ": " + ex.GetType().Name + ":" + ex.Message,
                    ex,
                    compilable.ToEPL());
            }

            return new StatementSpecCompiled(
                spec,
                compiledStreams.ToArray(),
                selectClauseCompiled,
                annotations,
                groupByRollupExpressions,
                subselectNodes,
                visitor.DeclaredExpressions,
                tableAccessNodes);
        }