Example #1
0
        /// <summary>
        ///     Walks the chain of lookups and constructs lookup strategy and plan specification based
        ///     on the index specifications.
        /// </summary>
        /// <param name="lookupStream">the stream to construct the query plan for</param>
        /// <param name="bestChain">the chain that the lookup follows to make best use of indexes</param>
        /// <param name="queryGraph">the repository for key properties to indexes</param>
        /// <param name="indexSpecsPerStream">specifications of indexes</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <param name="isHistorical">indicator for each stream if it is a historical streams or not</param>
        /// <param name="historicalStreamIndexLists">index management, populated for the query plan</param>
        /// <param name="tablesPerStream">tables</param>
        /// <param name="streamJoinAnalysisResult">stream join analysis</param>
        /// <param name="raw">raw statement information</param>
        /// <param name="serdeResolver">serde resolver</param>
        /// <returns>NestedIterationNode with lookups attached underneath</returns>
        public static QueryPlanNodeForgeDesc CreateStreamPlan(
            int lookupStream,
            int[] bestChain,
            QueryGraphForge queryGraph,
            QueryPlanIndexForge[] indexSpecsPerStream,
            EventType[] typesPerStream,
            bool[] isHistorical,
            HistoricalStreamIndexListForge[] historicalStreamIndexLists,
            TableMetaData[] tablesPerStream,
            StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var nestedIterNode = new NestedIterationNodeForge(bestChain);
            var currentLookupStream = lookupStream;
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            // Walk through each successive lookup
            for (var i = 0; i < bestChain.Length; i++) {
                var indexedStream = bestChain[i];

                QueryPlanNodeForge node;
                if (isHistorical[indexedStream]) {
                    if (historicalStreamIndexLists[indexedStream] == null) {
                        historicalStreamIndexLists[indexedStream] = new HistoricalStreamIndexListForge(
                            indexedStream,
                            typesPerStream,
                            queryGraph);
                    }

                    historicalStreamIndexLists[indexedStream].AddIndex(currentLookupStream);
                    node = new HistoricalDataPlanNodeForge(
                        indexedStream,
                        lookupStream,
                        currentLookupStream,
                        typesPerStream.Length,
                        null);
                }
                else {
                    var tableLookupPlan = CreateLookupPlan(
                        queryGraph,
                        currentLookupStream,
                        indexedStream,
                        streamJoinAnalysisResult.IsVirtualDW(indexedStream),
                        indexSpecsPerStream[indexedStream],
                        typesPerStream,
                        tablesPerStream[indexedStream],
                        raw,
                        serdeResolver);
                    node = new TableLookupNodeForge(tableLookupPlan.Forge);
                    additionalForgeables.AddAll(tableLookupPlan.AdditionalForgeables);
                }

                nestedIterNode.AddChildNode(node);

                currentLookupStream = bestChain[i];
            }

            return new QueryPlanNodeForgeDesc(nestedIterNode, additionalForgeables);
        }
        /// <summary>
        /// Build query plan.
        /// </summary>
        /// <param name="queryGraph">navigability info</param>
        /// <param name="optionalOuterJoinType">outer join type, null if not an outer join</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <param name="streamJoinAnalysisResult">stream join analysis</param>
        /// <returns>query plan</returns>
        public static QueryPlanForgeDesc Build(
            EventType[] typesPerStream,
            QueryGraphForge queryGraph,
            OuterJoinType? optionalOuterJoinType,
            StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult,
            StatementRawInfo raw)
        {
            var uniqueIndexProps = streamJoinAnalysisResult.UniqueKeys;
            var tablesPerStream = streamJoinAnalysisResult.TablesPerStream;
            var additionalForgeable = new List<StmtClassForgeableFactory>();

            var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec(
                queryGraph,
                typesPerStream,
                uniqueIndexProps);

            var execNodeSpecs = new QueryPlanNodeForge[2];
            var lookupPlans = new TableLookupPlanForge[2];

            // plan lookup from 1 to zero
            TableLookupPlanDesc plan1to0 = NStreamQueryPlanBuilder.CreateLookupPlan(
                queryGraph,
                1,
                0,
                streamJoinAnalysisResult.IsVirtualDW(0),
                indexSpecs[0],
                typesPerStream,
                tablesPerStream[0],
                raw,
                SerdeCompileTimeResolverNonHA.INSTANCE);
            lookupPlans[1] = plan1to0.Forge;
            additionalForgeable.AddAll(plan1to0.AdditionalForgeables);

            // plan lookup from zero to 1
            TableLookupPlanDesc plan0to1 = NStreamQueryPlanBuilder.CreateLookupPlan(
                queryGraph,
                0,
                1,
                streamJoinAnalysisResult.IsVirtualDW(1),
                indexSpecs[1],
                typesPerStream,
                tablesPerStream[1],
                raw,
                SerdeCompileTimeResolverNonHA.INSTANCE);
            lookupPlans[0] = plan0to1.Forge;
            additionalForgeable.AddAll(plan0to1.AdditionalForgeables);

            execNodeSpecs[0] = new TableLookupNodeForge(lookupPlans[0]);
            execNodeSpecs[1] = new TableLookupNodeForge(lookupPlans[1]);

            if (optionalOuterJoinType != null) {
                if ((optionalOuterJoinType.Equals(OuterJoinType.LEFT)) ||
                    (optionalOuterJoinType.Equals(OuterJoinType.FULL))) {
                    execNodeSpecs[0] = new TableOuterLookupNodeForge(lookupPlans[0]);
                }

                if ((optionalOuterJoinType.Equals(OuterJoinType.RIGHT)) ||
                    (optionalOuterJoinType.Equals(OuterJoinType.FULL))) {
                    execNodeSpecs[1] = new TableOuterLookupNodeForge(lookupPlans[1]);
                }
            }

            var forge = new QueryPlanForge(indexSpecs, execNodeSpecs);
            return new QueryPlanForgeDesc(forge, additionalForgeable);
        }
        private static LookupInstructionPlanDesc BuildLookupInstructions(
            int rootStreamNum,
            IDictionary<int, int[]> substreamsPerStream,
            bool[] requiredPerStream,
            string[] streamNames,
            QueryGraphForge queryGraph,
            QueryPlanIndexForge[] indexSpecs,
            EventType[] typesPerStream,
            OuterJoinDesc[] outerJoinDescList,
            bool[] isHistorical,
            HistoricalStreamIndexListForge[] historicalStreamIndexLists,
            TableMetaData[] tablesPerStream,
            StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            var result = new List<LookupInstructionPlanForge>();
            var additionalForgeables = new List<StmtClassForgeableFactory>();
            
            foreach (var fromStream in substreamsPerStream.Keys) {
                var substreams = substreamsPerStream.Get(fromStream);

                // for streams with no substreams we don't need to look up
                if (substreams.Length == 0) {
                    continue;
                }

                var plans = new TableLookupPlanForge[substreams.Length];
                var historicalPlans = new HistoricalDataPlanNodeForge[substreams.Length];

                for (var i = 0; i < substreams.Length; i++) {
                    var toStream = substreams[i];

                    if (isHistorical[toStream]) {
                        // There may not be an outer-join descriptor, use if provided to build the associated expression
                        ExprNode outerJoinExpr = null;
                        if (outerJoinDescList.Length > 0) {
                            OuterJoinDesc outerJoinDesc;
                            if (toStream == 0) {
                                outerJoinDesc = outerJoinDescList[0];
                            }
                            else {
                                outerJoinDesc = outerJoinDescList[toStream - 1];
                            }

                            outerJoinExpr = outerJoinDesc.MakeExprNode(statementRawInfo, services);
                        }

                        if (historicalStreamIndexLists[toStream] == null) {
                            historicalStreamIndexLists[toStream] = new HistoricalStreamIndexListForge(
                                toStream,
                                typesPerStream,
                                queryGraph);
                        }

                        historicalStreamIndexLists[toStream].AddIndex(fromStream);
                        historicalPlans[i] = new HistoricalDataPlanNodeForge(
                            toStream,
                            rootStreamNum,
                            fromStream,
                            typesPerStream.Length,
                            outerJoinExpr == null ? null : outerJoinExpr.Forge);
                    }
                    else {
                        TableLookupPlanDesc planDesc = NStreamQueryPlanBuilder.CreateLookupPlan(
                            queryGraph,
                            fromStream,
                            toStream,
                            streamJoinAnalysisResult.IsVirtualDW(toStream),
                            indexSpecs[toStream],
                            typesPerStream,
                            tablesPerStream[toStream],
                            statementRawInfo,
                            SerdeCompileTimeResolverNonHA.INSTANCE);
                        plans[i] = planDesc.Forge;
                        additionalForgeables.AddAll(planDesc.AdditionalForgeables);
                    }
                }

                var fromStreamName = streamNames[fromStream];
                var instruction = new LookupInstructionPlanForge(
                    fromStream,
                    fromStreamName,
                    substreams,
                    plans,
                    historicalPlans,
                    requiredPerStream);
                result.Add(instruction);
            }

            return new LookupInstructionPlanDesc(result, additionalForgeables);
        }