示例#1
0
        public static bool IsPotentialSelfJoin(StatementSpecCompiled spec)
        {
            // Include create-context as nested contexts that have pattern-initiated sub-contexts may change filters during execution
            if (spec.Raw.CreateContextDesc != null && spec.Raw.CreateContextDesc.ContextDetail is ContextNested) {
                return true;
            }

            // if order-by is specified, ans since multiple output rows may produce, ensure dispatch
            if (spec.Raw.OrderByList.Count > 0) {
                return true;
            }

            foreach (var streamSpec in spec.StreamSpecs) {
                if (streamSpec is PatternStreamSpecCompiled) {
                    return true;
                }
            }

            // not a self join
            if (spec.StreamSpecs.Length <= 1 && spec.SubselectNodes.Count == 0) {
                return false;
            }

            // join - determine types joined
            IList<EventType> filteredTypes = new List<EventType>();

            // consider subqueryes
            var optSubselectTypes = PopulateSubqueryTypes(spec.SubselectNodes);

            var hasFilterStream = false;
            foreach (var streamSpec in spec.StreamSpecs) {
                if (streamSpec is FilterStreamSpecCompiled) {
                    var type = ((FilterStreamSpecCompiled) streamSpec).FilterSpecCompiled.FilterForEventType;
                    filteredTypes.Add(type);
                    hasFilterStream = true;
                }
            }

            if (filteredTypes.Count == 1 && optSubselectTypes.IsEmpty()) {
                return false;
            }

            // pattern-only streams are not self-joins
            if (!hasFilterStream) {
                return false;
            }

            // is type overlap in filters
            for (var i = 0; i < filteredTypes.Count; i++) {
                for (var j = i + 1; j < filteredTypes.Count; j++) {
                    var typeOne = filteredTypes[i];
                    var typeTwo = filteredTypes[j];
                    if (typeOne == typeTwo) {
                        return true;
                    }

                    if (typeOne.SuperTypes != null) {
                        foreach (var typeOneSuper in typeOne.SuperTypes) {
                            if (typeOneSuper == typeTwo) {
                                return true;
                            }
                        }
                    }

                    if (typeTwo.SuperTypes != null) {
                        foreach (var typeTwoSuper in typeTwo.SuperTypes) {
                            if (typeOne == typeTwoSuper) {
                                return true;
                            }
                        }
                    }
                }
            }

            // analyze subselect types
            if (!optSubselectTypes.IsEmpty()) {
                foreach (var typeOne in filteredTypes) {
                    if (optSubselectTypes.Contains(typeOne)) {
                        return true;
                    }

                    if (typeOne.SuperTypes != null) {
                        foreach (var typeOneSuper in typeOne.SuperTypes) {
                            if (optSubselectTypes.Contains(typeOneSuper)) {
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
示例#2
0
        public static StatementSpecCompiledDesc 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>();
            IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(2);

            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;
                }
                
                var streamSpec = (FilterStreamSpecRaw) spec.StreamSpecs[0];
                if (streamSpec.RawFilterSpec.OptionalPropertyEvalSpec != null) {
                    disqualified = true;
                }

                if (!disqualified) {
                    spec.WhereClause = null;
                    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());
            }

            // Expand match-recognize patterns
            if (spec.MatchRecognizeSpec != null) {
                RowRecogExprNode expandedPatternNode;
                try {
                    var copier = new ExpressionCopier(
                        spec, statementRawInfo.OptionalContextDescriptor, compileTimeServices, visitor);
                    expandedPatternNode = RowRecogPatternExpandUtil.Expand(spec.MatchRecognizeSpec.Pattern, copier);
                } catch (ExprValidationException ex) {
                    throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
                }
                spec.MatchRecognizeSpec.Pattern = expandedPatternNode;
            }
            
            if (isSubquery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Invalid nested subquery, subquery-within-subquery is not supported",
                    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) {
                var raw = subselect.StatementSpecRaw;
                var desc = Compile(
                    raw,
                    compilable,
                    true,
                    isOnDemandQuery,
                    annotations,
                    Collections.GetEmptyList<ExprSubselectNode>(),
                    Collections.GetEmptyList<ExprTableAccessNode>(),
                    statementRawInfo,
                    compileTimeServices);
                additionalForgeables.AddAll(desc.AdditionalForgeables);
                subselect.SetStatementSpecCompiled(desc.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 desc = StreamSpecCompiler.Compile(
                        rawSpec,
                        eventTypeReferences,
                        spec.InsertIntoDesc != null,
                        spec.StreamSpecs.Count > 1,
                        false,
                        spec.OnTriggerDesc != null,
                        rawSpec.OptionalStreamName,
                        streamNum,
                        statementRawInfo,
                        compileTimeServices);
                    additionalForgeables.AddAll(desc.AdditionalForgeables);
                    compiledStreams.Add(desc.StreamSpecCompiled);
                }
            }
            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());
            }

            var compiled = new StatementSpecCompiled(
                spec,
                compiledStreams.ToArray(),
                selectClauseCompiled,
                annotations,
                groupByRollupExpressions,
                subselectNodes,
                visitor.DeclaredExpressions,
                tableAccessNodes);

            return new StatementSpecCompiledDesc(compiled, additionalForgeables);
        }