public JoinSetComposerPrototypeImpl(string statementName,
                                     string statementId,
                                     OuterJoinDesc[] outerJoinDescList,
                                     ExprNode optionalFilterNode,
                                     EventType[] streamTypes,
                                     string[] streamNames,
                                     StreamJoinAnalysisResult streamJoinAnalysisResult,
                                     Attribute[] annotations,
                                     HistoricalViewableDesc historicalViewableDesc,
                                     ExprEvaluatorContext exprEvaluatorContext,
                                     QueryPlanIndex[] indexSpecs,
                                     QueryPlan queryPlan,
                                     HistoricalStreamIndexList[] historicalStreamIndexLists,
                                     bool joinRemoveStream,
                                     bool isOuterJoins,
                                     TableService tableService)
 {
     _statementName            = statementName;
     _statementId              = statementId;
     _outerJoinDescList        = outerJoinDescList;
     _optionalFilterNode       = optionalFilterNode;
     _streamTypes              = streamTypes;
     _streamNames              = streamNames;
     _streamJoinAnalysisResult = streamJoinAnalysisResult;
     _annotations              = annotations;
     _historicalViewableDesc   = historicalViewableDesc;
     _exprEvaluatorContext     = exprEvaluatorContext;
     _indexSpecs = indexSpecs;
     _queryPlan  = queryPlan;
     _historicalStreamIndexLists = historicalStreamIndexLists;
     _joinRemoveStream           = joinRemoveStream;
     _isOuterJoins = isOuterJoins;
     _tableService = tableService;
 }
Example #2
0
        /// <summary>
        /// Builds join tuple composer.
        /// </summary>
        /// <param name="statementName">Name of the statement.</param>
        /// <param name="statementId">The statement identifier.</param>
        /// <param name="outerJoinDescList">list of descriptors for outer join criteria</param>
        /// <param name="optionalFilterNode">filter tree for analysis to build indexes for fast access</param>
        /// <param name="streamTypes">types of streams</param>
        /// <param name="streamNames">names of streams</param>
        /// <param name="streamJoinAnalysisResult">The stream join analysis result.</param>
        /// <param name="queryPlanLogging">if set to <c>true</c> [query plan logging].</param>
        /// <param name="statementContext">The statement context.</param>
        /// <param name="historicalViewableDesc">The historical viewable desc.</param>
        /// <param name="exprEvaluatorContext">The expr evaluator context.</param>
        /// <param name="selectsRemoveStream">if set to <c>true</c> [selects remove stream].</param>
        /// <param name="hasAggregations">if set to <c>true</c> [has aggregations].</param>
        /// <param name="tableService">The table service.</param>
        /// <param name="isOnDemandQuery">if set to <c>true</c> [is on demand query].</param>
        /// <param name="allowIndexInit">if set to <c>true</c> [allow index initialize].</param>
        /// <returns>
        /// composer implementation
        /// </returns>
        /// <throws>com.espertech.esper.epl.expression.core.ExprValidationException is thrown to indicate thatvalidation of view use in joins failed.
        /// {D255958A-8513-4226-94B9-080D98F904A1}</throws>
        public static JoinSetComposerPrototype MakeComposerPrototype(string statementName, int statementId, OuterJoinDesc[] outerJoinDescList, ExprNode optionalFilterNode, EventType[] streamTypes, string[] streamNames, StreamJoinAnalysisResult streamJoinAnalysisResult, bool queryPlanLogging, StatementContext statementContext, HistoricalViewableDesc historicalViewableDesc, ExprEvaluatorContext exprEvaluatorContext, bool selectsRemoveStream, bool hasAggregations, TableService tableService, bool isOnDemandQuery, bool allowIndexInit)
        {
            // Determine if there is a historical stream, and what dependencies exist
            var historicalDependencyGraph = new DependencyGraph(streamTypes.Length, false);

            for (var i = 0; i < streamTypes.Length; i++)
            {
                if (historicalViewableDesc.Historical[i])
                {
                    var streamsThisStreamDependsOn = historicalViewableDesc.DependenciesPerHistorical[i];
                    historicalDependencyGraph.AddDependency(i, streamsThisStreamDependsOn);
                }
            }

            if (log.IsDebugEnabled)
            {
                log.Debug("Dependency graph: " + historicalDependencyGraph);
            }

            // Handle a join with a database or other historical data source for 2 streams
            if ((historicalViewableDesc.HasHistorical) && (streamTypes.Length == 2))
            {
                return(MakeComposerHistorical2Stream(outerJoinDescList, optionalFilterNode, streamTypes, historicalViewableDesc, queryPlanLogging, exprEvaluatorContext, statementContext, streamNames, allowIndexInit));
            }

            var isOuterJoins = !OuterJoinDesc.ConsistsOfAllInnerJoins(outerJoinDescList);

            // Query graph for graph relationships between streams/historicals
            // For outer joins the query graph will just contain outer join relationships
            var hint       = ExcludePlanHint.GetHint(streamNames, statementContext);
            var queryGraph = new QueryGraph(streamTypes.Length, hint, false);

            if (outerJoinDescList.Length > 0)
            {
                OuterJoinAnalyzer.Analyze(outerJoinDescList, queryGraph);
                if (log.IsDebugEnabled)
                {
                    log.Debug(".makeComposer After outer join queryGraph=\n" + queryGraph);
                }
            }

            // Let the query graph reflect the where-clause
            if (optionalFilterNode != null)
            {
                // Analyze relationships between streams using the optional filter expression.
                // Relationships are properties in AND and EQUALS nodes of joins.
                FilterExprAnalyzer.Analyze(optionalFilterNode, queryGraph, isOuterJoins);
                if (log.IsDebugEnabled)
                {
                    log.Debug(".makeComposer After filter expression queryGraph=\n" + queryGraph);
                }

                // Add navigation entries based on key and index property equivalency (a=b, b=c follows a=c)
                QueryGraph.FillEquivalentNav(streamTypes, queryGraph);
                if (log.IsDebugEnabled)
                {
                    log.Debug(".makeComposer After fill equiv. nav. queryGraph=\n" + queryGraph);
                }
            }

            // Historical index lists
            var historicalStreamIndexLists = new HistoricalStreamIndexList[streamTypes.Length];

            var queryPlan = QueryPlanBuilder.GetPlan(streamTypes, outerJoinDescList, queryGraph, streamNames,
                                                     historicalViewableDesc, historicalDependencyGraph, historicalStreamIndexLists,
                                                     streamJoinAnalysisResult, queryPlanLogging, statementContext.Annotations, exprEvaluatorContext);

            // remove unused indexes - consider all streams or all unidirectional
            var usedIndexes = new HashSet <TableLookupIndexReqKey>();
            var indexSpecs  = queryPlan.IndexSpecs;

            for (var streamNum = 0; streamNum < queryPlan.ExecNodeSpecs.Length; streamNum++)
            {
                var planNode = queryPlan.ExecNodeSpecs[streamNum];
                if (planNode != null)
                {
                    planNode.AddIndexes(usedIndexes);
                }
            }
            foreach (var indexSpec in indexSpecs)
            {
                if (indexSpec == null)
                {
                    continue;
                }
                var items      = indexSpec.Items;
                var indexNames = items.Keys.ToArray();
                foreach (var indexName in indexNames)
                {
                    if (!usedIndexes.Contains(indexName))
                    {
                        items.Remove(indexName);
                    }
                }
            }

            var hook = QueryPlanIndexHookUtil.GetHook(statementContext.Annotations);

            if (queryPlanLogging && (QueryPlanLog.IsInfoEnabled || hook != null))
            {
                QueryPlanLog.Info("Query plan: " + queryPlan.ToQueryPlan());
                if (hook != null)
                {
                    hook.Join(queryPlan);
                }
            }

            // register index-use references for tables
            if (!isOnDemandQuery)
            {
                foreach (var usedIndex in usedIndexes)
                {
                    if (usedIndex.TableName != null)
                    {
                        tableService.GetTableMetadata(usedIndex.TableName).AddIndexReference(usedIndex.Name, statementName);
                    }
                }
            }

            var joinRemoveStream = selectsRemoveStream || hasAggregations;

            return(new JoinSetComposerPrototypeImpl(
                       statementName,
                       statementId,
                       outerJoinDescList,
                       optionalFilterNode,
                       streamTypes,
                       streamNames,
                       streamJoinAnalysisResult,
                       statementContext.Annotations,
                       historicalViewableDesc,
                       exprEvaluatorContext,
                       indexSpecs,
                       queryPlan,
                       historicalStreamIndexLists,
                       joinRemoveStream,
                       isOuterJoins,
                       tableService,
                       statementContext.EventTableIndexService));
        }
Example #3
0
        private static JoinSetComposerPrototype MakeComposerHistorical2Stream(OuterJoinDesc[] outerJoinDescList, ExprNode optionalFilterNode, EventType[] streamTypes, HistoricalViewableDesc historicalViewableDesc, bool queryPlanLogging, ExprEvaluatorContext exprEvaluatorContext, StatementContext statementContext, string[] streamNames, bool allowIndexInit)
        {
            var polledViewNum = 0;
            var streamViewNum = 1;

            if (historicalViewableDesc.Historical[1])
            {
                streamViewNum = 0;
                polledViewNum = 1;
            }

            // if all-historical join, check dependency
            var isAllHistoricalNoSubordinate = false;

            if ((historicalViewableDesc.Historical[0]) && historicalViewableDesc.Historical[1])
            {
                var graph = new DependencyGraph(2, false);
                graph.AddDependency(0, historicalViewableDesc.DependenciesPerHistorical[0]);
                graph.AddDependency(1, historicalViewableDesc.DependenciesPerHistorical[1]);
                if (graph.FirstCircularDependency != null)
                {
                    throw new ExprValidationException("Circular dependency detected between historical streams");
                }

                // if both streams are independent
                if (graph.RootNodes.Count == 2)
                {
                    isAllHistoricalNoSubordinate = true;     // No parameters used by either historical
                }
                else
                {
                    if ((graph.GetDependenciesForStream(0).Count == 0))
                    {
                        streamViewNum = 0;
                        polledViewNum = 1;
                    }
                    else
                    {
                        streamViewNum = 1;
                        polledViewNum = 0;
                    }
                }
            }

            // Build an outer join expression node
            var      isOuterJoin         = false;
            var      isInnerJoinOnly     = false;
            ExprNode outerJoinEqualsNode = null;

            if (outerJoinDescList.Length > 0)
            {
                var outerJoinDesc = outerJoinDescList[0];
                isInnerJoinOnly = outerJoinDesc.OuterJoinType == OuterJoinType.INNER;

                if (outerJoinDesc.OuterJoinType.Equals(OuterJoinType.FULL))
                {
                    isOuterJoin = true;
                }
                else if ((outerJoinDesc.OuterJoinType.Equals(OuterJoinType.LEFT)) &&
                         (streamViewNum == 0))
                {
                    isOuterJoin = true;
                }
                else if ((outerJoinDesc.OuterJoinType.Equals(OuterJoinType.RIGHT)) &&
                         (streamViewNum == 1))
                {
                    isOuterJoin = true;
                }

                outerJoinEqualsNode = outerJoinDesc.MakeExprNode(exprEvaluatorContext);
            }

            // Determine filter for indexing purposes
            ExprNode filterForIndexing = null;

            if ((outerJoinEqualsNode != null) && (optionalFilterNode != null) && isInnerJoinOnly)      // both filter and outer join, add
            {
                filterForIndexing = new ExprAndNodeImpl();
                filterForIndexing.AddChildNode(optionalFilterNode);
                filterForIndexing.AddChildNode(outerJoinEqualsNode);
            }
            else if ((outerJoinEqualsNode == null) && (optionalFilterNode != null))
            {
                filterForIndexing = optionalFilterNode;
            }
            else if (outerJoinEqualsNode != null)
            {
                filterForIndexing = outerJoinEqualsNode;
            }

            var indexStrategies =
                DetermineIndexing(filterForIndexing, streamTypes[polledViewNum], streamTypes[streamViewNum], polledViewNum, streamViewNum, statementContext, streamNames);

            var hook = QueryPlanIndexHookUtil.GetHook(statementContext.Annotations);

            if (queryPlanLogging && (QueryPlanLog.IsInfoEnabled || hook != null))
            {
                QueryPlanLog.Info("historical lookup strategy: " + indexStrategies.First.ToQueryPlan());
                QueryPlanLog.Info("historical index strategy: " + indexStrategies.Second.ToQueryPlan());
                if (hook != null)
                {
                    hook.Historical(new QueryPlanIndexDescHistorical(indexStrategies.First.GetType().Name, indexStrategies.Second.GetType().Name));
                }
            }

            return(new JoinSetComposerPrototypeHistorical2StreamImpl(
                       optionalFilterNode,
                       streamTypes,
                       exprEvaluatorContext,
                       polledViewNum,
                       streamViewNum,
                       isOuterJoin,
                       outerJoinEqualsNode,
                       indexStrategies,
                       isAllHistoricalNoSubordinate,
                       outerJoinDescList,
                       allowIndexInit));
        }