public static SubordinateWMatchExprQueryPlanResult PlanOnExpression(
            ExprNode joinExpr,
            EventType filterEventType,
            IndexHint optionalIndexHint,
            bool isIndexShare,
            int subqueryNumber,
            ExcludePlanHint excludePlanHint,
            bool isVirtualDataWindow,
            EventTableIndexMetadata indexMetadata,
            EventType eventTypeIndexed,
            ICollection <string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes,
            string statementName,
            string statementId,
            Attribute[] annotations)
        {
            var allStreamsZeroIndexed = new EventType[] { eventTypeIndexed, filterEventType };
            var outerStreams          = new EventType[] { filterEventType };
            var joinedPropPlan        = QueryPlanIndexBuilder.GetJoinProps(joinExpr, 1, allStreamsZeroIndexed, excludePlanHint);

            // No join expression means all
            if (joinExpr == null && !isVirtualDataWindow)
            {
                return(new SubordinateWMatchExprQueryPlanResult(new SubordWMatchExprLookupStrategyFactoryAllUnfiltered(), null));
            }

            var queryPlanDesc = PlanSubquery(outerStreams, joinedPropPlan, true, false, optionalIndexHint, isIndexShare, subqueryNumber,
                                             isVirtualDataWindow, indexMetadata, optionalUniqueKeyProps, onlyUseExistingIndexes, statementName, statementId, annotations);

            if (queryPlanDesc == null)
            {
                return(new SubordinateWMatchExprQueryPlanResult(new SubordWMatchExprLookupStrategyFactoryAllFiltered(joinExpr.ExprEvaluator), null));
            }

            if (joinExpr == null)     // it can be null when using virtual data window
            {
                return(new SubordinateWMatchExprQueryPlanResult(
                           new SubordWMatchExprLookupStrategyFactoryIndexedUnfiltered(queryPlanDesc.LookupStrategyFactory), queryPlanDesc.IndexDescs));
            }
            else
            {
                return(new SubordinateWMatchExprQueryPlanResult(
                           new SubordWMatchExprLookupStrategyFactoryIndexedFiltered(joinExpr.ExprEvaluator, queryPlanDesc.LookupStrategyFactory), queryPlanDesc.IndexDescs));
            }
        }
        public static SubordinateWMatchExprQueryPlanResult PlanOnExpression(
            ExprNode joinExpr,
            EventType filterEventType,
            IndexHint optionalIndexHint,
            bool isIndexShare,
            int subqueryNumber,
            ExcludePlanHint excludePlanHint,
            bool isVirtualDataWindow,
            EventTableIndexMetadata indexMetadata,
            EventType eventTypeIndexed,
            ISet<string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            var allStreamsZeroIndexed = new EventType[] {eventTypeIndexed, filterEventType};
            var outerStreams = new EventType[] {filterEventType};
            var joinedPropPlan = QueryPlanIndexBuilder.GetJoinProps(
                joinExpr,
                1,
                allStreamsZeroIndexed,
                excludePlanHint);

            // No join expression means all
            if (joinExpr == null && !isVirtualDataWindow) {
                var forgeX = new SubordinateWMatchExprQueryPlanForge(new SubordWMatchExprLookupStrategyAllUnfilteredForge(), null);
                return new SubordinateWMatchExprQueryPlanResult(forgeX, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            var queryPlan = PlanSubquery(
                outerStreams,
                joinedPropPlan,
                true,
                false,
                optionalIndexHint,
                isIndexShare,
                subqueryNumber,
                isVirtualDataWindow,
                indexMetadata,
                optionalUniqueKeyProps,
                onlyUseExistingIndexes,
                eventTypeIndexed,
                statementRawInfo,
                compileTimeServices);

            if (queryPlan == null) {
                var forgeX = new SubordinateWMatchExprQueryPlanForge(new SubordWMatchExprLookupStrategyAllFilteredForge(joinExpr), null);
                return new SubordinateWMatchExprQueryPlanResult(forgeX, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            var queryPlanDesc = queryPlan.Forge;
            SubordinateWMatchExprQueryPlanForge forge;
            if (joinExpr == null) {   // it can be null when using virtual data window
                forge = new SubordinateWMatchExprQueryPlanForge(
                    new SubordWMatchExprLookupStrategyIndexedUnfilteredForge(queryPlanDesc.LookupStrategyFactory), queryPlanDesc.IndexDescs);
            } else {
                var filteredForge =
                    new SubordWMatchExprLookupStrategyIndexedFilteredForge(joinExpr.Forge, queryPlanDesc.LookupStrategyFactory);
                forge = new SubordinateWMatchExprQueryPlanForge(filteredForge, queryPlanDesc.IndexDescs);
            }

            return new SubordinateWMatchExprQueryPlanResult(forge, queryPlan.AdditionalForgeables);
        }