Exemplo n.º 1
0
 public SubordTableLookupStrategyFactoryForgeVDW(
     string statementName,
     Attribute[] annotations,
     EventType[] outerStreams,
     IList<SubordPropHashKeyForge> hashKeys,
     CoercionDesc hashKeyCoercionTypes,
     IList<SubordPropRangeKeyForge> rangeKeys,
     CoercionDesc rangeKeyCoercionTypes,
     bool nwOnTrigger,
     SubordPropPlan joinDesc,
     bool forceTableScan,
     SubordinateQueryPlannerIndexPropListPair hashAndRanges)
 {
     _statementName = statementName;
     _annotations = annotations;
     _outerStreams = outerStreams;
     _hashKeys = hashKeys;
     _hashKeyCoercionTypes = hashKeyCoercionTypes;
     _rangeKeys = rangeKeys;
     _rangeKeyCoercionTypes = rangeKeyCoercionTypes;
     _nwOnTrigger = nwOnTrigger;
     _joinDesc = joinDesc;
     _forceTableScan = forceTableScan;
     _hashAndRanges = hashAndRanges;
 }
Exemplo n.º 2
0
 public IndexKeyInfo(IList <SubordPropHashKey> orderedKeyDesc, CoercionDesc orderedKeyCoercionTypes, IList <SubordPropRangeKey> orderedRangeDesc, CoercionDesc orderedRangeCoercionTypes)
 {
     OrderedHashDesc           = orderedKeyDesc;
     OrderedKeyCoercionTypes   = orderedKeyCoercionTypes;
     OrderedRangeDesc          = orderedRangeDesc;
     OrderedRangeCoercionTypes = orderedRangeCoercionTypes;
 }
Exemplo n.º 3
0
 public SubordSortedTableLookupStrategyFactoryForge(
     bool isNWOnTrigger,
     int numStreamsOuter,
     SubordPropRangeKeyForge rangeKey,
     CoercionDesc coercionDesc)
 {
     this._isNwOnTrigger = isNWOnTrigger;
     this._numStreamsOuter = numStreamsOuter;
     this._rangeKey = rangeKey;
     this._coercionDesc = coercionDesc;
 }
Exemplo n.º 4
0
 public SubordTableLookupStrategyFactoryVDW(string statementName, string statementId, Attribute[] annotations, EventType[] outerStreams, IList <SubordPropHashKey> hashKeys, CoercionDesc hashKeyCoercionTypes, IList <SubordPropRangeKey> rangeKeys, CoercionDesc rangeKeyCoercionTypes, bool nwOnTrigger, SubordPropPlan joinDesc, bool forceTableScan, SubordinateQueryPlannerIndexPropListPair hashAndRanges)
 {
     this.statementName         = statementName;
     this.statementId           = statementId;
     this.annotations           = annotations;
     this.outerStreams          = outerStreams;
     this.hashKeys              = hashKeys;
     this.hashKeyCoercionTypes  = hashKeyCoercionTypes;
     this.rangeKeys             = rangeKeys;
     this.rangeKeyCoercionTypes = rangeKeyCoercionTypes;
     this.nwOnTrigger           = nwOnTrigger;
     this.joinDesc              = joinDesc;
     this.forceTableScan        = forceTableScan;
     this.hashAndRanges         = hashAndRanges;
 }
Exemplo n.º 5
0
 public PropertySortedFactoryFactoryForge(
     int indexedStreamNum,
     int? subqueryNum,
     bool isFireAndForget,
     string indexedProp,
     EventType eventType,
     CoercionDesc coercionDesc,
     DataInputOutputSerdeForge serde)
     : base(indexedStreamNum, subqueryNum, isFireAndForget)
 {
     this.indexedProp = indexedProp;
     this.eventType = eventType;
     this.coercionDesc = coercionDesc;
     this.serde = serde;
 }
Exemplo n.º 6
0
 public PropertyHashedFactoryFactoryForge(
     int indexedStreamNum,
     int? subqueryNum,
     bool isFireAndForget,
     string[] indexedProps,
     EventType eventType,
     bool unique,
     CoercionDesc hashCoercionDesc,
     MultiKeyClassRef multiKeyClassRef)
     : base(indexedStreamNum, subqueryNum, isFireAndForget)
 {
     this.indexedProps = indexedProps;
     this.eventType = eventType;
     this.unique = unique;
     this.hashCoercionDesc = hashCoercionDesc;
     this.multiKeyClassRef = multiKeyClassRef;
 }
        public SubordTableLookupStrategyVirtualDW(
            String namedWindowName,
            VirtualDataWindowLookup externalIndex,
            IList <SubordPropHashKey> hashKeys,
            CoercionDesc hashKeyCoercionTypes,
            IList <SubordPropRangeKey> rangeKeys,
            CoercionDesc rangeKeyCoercionTypes,
            bool nwOnTrigger,
            int numOuterStreams)
        {
            _namedWindowName = namedWindowName;
            _externalIndex   = externalIndex;
            _evaluators      = new ExternalEvaluator[hashKeys.Count + rangeKeys.Count];
            _nwOnTrigger     = nwOnTrigger;
            _eventsLocal     = new EventBean[numOuterStreams + 1];

            var count = 0;

            foreach (var hashKey in hashKeys)
            {
                var evaluator = hashKey.HashKey.KeyExpr.ExprEvaluator;
                _evaluators[count] = new ExternalEvaluatorHashRelOp(evaluator, hashKeyCoercionTypes.CoercionTypes[count]);
                count++;
            }
            for (var i = 0; i < rangeKeys.Count; i++)
            {
                SubordPropRangeKey rangeKey = rangeKeys[i];
                if (rangeKey.RangeInfo.RangeType.IsRange())
                {
                    var range          = (QueryGraphValueEntryRangeIn)rangeKey.RangeInfo;
                    var evaluatorStart = range.ExprStart.ExprEvaluator;
                    var evaluatorEnd   = range.ExprEnd.ExprEvaluator;
                    _evaluators[count] = new ExternalEvaluatorBtreeRange(evaluatorStart, evaluatorEnd, rangeKeyCoercionTypes.CoercionTypes[i]);
                }
                else
                {
                    var relOp     = (QueryGraphValueEntryRangeRelOp)rangeKey.RangeInfo;
                    var evaluator = relOp.Expression.ExprEvaluator;
                    _evaluators[count] = new ExternalEvaluatorHashRelOp(evaluator, rangeKeyCoercionTypes.CoercionTypes[i]);
                }
                count++;
            }
        }
 public SubordHashedTableLookupStrategyFactoryForge(
     bool isNWOnTrigger,
     int numStreamsOuter,
     IList<SubordPropHashKeyForge> hashKeys,
     CoercionDesc hashKeyCoercionTypes,
     bool isStrictKeys,
     string[] hashStrictKeys,
     int[] keyStreamNumbers,
     IList<EventType> outerStreamTypesZeroIndexed,
     MultiKeyClassRef hashMultikeyClasses)
 {
     this.isNWOnTrigger = isNWOnTrigger;
     _numStreamsOuter = numStreamsOuter;
     _hashKeys = hashKeys;
     _hashKeyCoercionTypes = hashKeyCoercionTypes;
     _isStrictKeys = isStrictKeys;
     _hashStrictKeys = hashStrictKeys;
     _keyStreamNumbers = keyStreamNumbers;
     _outerStreamTypesZeroIndexed = outerStreamTypesZeroIndexed;
     _hashMultikeyClasses = hashMultikeyClasses;
 }
Exemplo n.º 9
0
        public SubordTableLookupStrategy GetSubordinateLookupStrategy(
            String accessedByStatementName,
            int accessedByStatementId,
            Attribute[] accessedByStmtAnnotations,
            EventType[] outerStreamTypes,
            IList <SubordPropHashKey> hashKeys,
            CoercionDesc hashKeyCoercionTypes,
            IList <SubordPropRangeKey> rangeKeys,
            CoercionDesc rangeKeyCoercionTypes,
            bool nwOnTrigger,
            EventTable eventTable,
            SubordPropPlan joinDesc,
            bool forceTableScan)
        {
            var noopTable = (VirtualDWEventTable)eventTable;

            for (var i = 0; i < noopTable.BtreeAccess.Count; i++)
            {
                noopTable.BtreeAccess[i].Operator = rangeKeys[i].RangeInfo.RangeType.GetStringOp().FromOpString();
            }

            // allocate a number within the statement
            if (_lastAccessedByStatementName == null || !_lastAccessedByStatementName.Equals(accessedByStatementName))
            {
                _lastAccessedByNum = 0;
            }
            _lastAccessedByNum++;

            var context = new VirtualDataWindowLookupContextSPI(
                accessedByStatementName, accessedByStatementId, accessedByStmtAnnotations, false, _namedWindowName,
                noopTable.HashAccess, noopTable.BtreeAccess, joinDesc, forceTableScan, outerStreamTypes,
                accessedByStatementName, _lastAccessedByNum);
            var index = _dataExternal.GetLookup(context);

            CheckIndex(index);
            return(new SubordTableLookupStrategyVirtualDW(
                       _namedWindowName, index, hashKeys, hashKeyCoercionTypes, rangeKeys, rangeKeyCoercionTypes, nwOnTrigger,
                       outerStreamTypes.Length));
        }
Exemplo n.º 10
0
        public static SubordinateQueryPlanDesc PlanSubquery(EventType[] outerStreams,
                                                            SubordPropPlan joinDesc,
                                                            bool isNWOnTrigger,
                                                            bool forceTableScan,
                                                            IndexHint optionalIndexHint,
                                                            bool indexShare,
                                                            int subqueryNumber,
                                                            bool isVirtualDataWindow,
                                                            EventTableIndexMetadata indexMetadata,
                                                            ICollection <string> optionalUniqueKeyProps,
                                                            bool onlyUseExistingIndexes,
                                                            string statementName,
                                                            string statementId,
                                                            Attribute[] annotations)
        {
            if (isVirtualDataWindow)
            {
                var indexProps = GetIndexPropDesc(joinDesc.HashProps, joinDesc.RangeProps);
                var lookupStrategyFactoryVdw = new SubordTableLookupStrategyFactoryVDW(statementName, statementId, annotations,
                                                                                       outerStreams,
                                                                                       indexProps.HashJoinedProps,
                                                                                       new CoercionDesc(false, indexProps.HashIndexCoercionType),
                                                                                       indexProps.RangeJoinedProps,
                                                                                       new CoercionDesc(false, indexProps.RangeIndexCoercionType),
                                                                                       isNWOnTrigger,
                                                                                       joinDesc, forceTableScan, indexProps.ListPair);
                return(new SubordinateQueryPlanDesc(lookupStrategyFactoryVdw, null));
            }

            var          hashKeys              = Collections.GetEmptyList <SubordPropHashKey>();
            CoercionDesc hashKeyCoercionTypes  = null;
            var          rangeKeys             = Collections.GetEmptyList <SubordPropRangeKey>();
            CoercionDesc rangeKeyCoercionTypes = null;

            ExprNode[] inKeywordSingleIdxKeys = null;
            ExprNode   inKeywordMultiIdxKey   = null;

            SubordinateQueryIndexDesc[] indexDescs;
            if (joinDesc.InKeywordSingleIndex != null)
            {
                var single    = joinDesc.InKeywordSingleIndex;
                var keyInfo   = new SubordPropHashKey(new QueryGraphValueEntryHashKeyedExpr(single.Expressions[0], false), null, single.CoercionType);
                var indexDesc = FindOrSuggestIndex(
                    Collections.SingletonMap(single.IndexedProp, keyInfo),
                    Collections.GetEmptyMap <string, SubordPropRangeKey>(), optionalIndexHint, indexShare, subqueryNumber,
                    indexMetadata, optionalUniqueKeyProps, onlyUseExistingIndexes);
                if (indexDesc == null)
                {
                    return(null);
                }
                var desc = new SubordinateQueryIndexDesc(indexDesc.IndexKeyInfo, indexDesc.IndexName, indexDesc.IndexMultiKey, indexDesc.QueryPlanIndexItem);
                indexDescs             = new SubordinateQueryIndexDesc[] { desc };
                inKeywordSingleIdxKeys = single.Expressions;
            }
            else if (joinDesc.InKeywordMultiIndex != null)
            {
                var multi = joinDesc.InKeywordMultiIndex;

                indexDescs = new SubordinateQueryIndexDesc[multi.IndexedProp.Length];
                for (var i = 0; i < multi.IndexedProp.Length; i++)
                {
                    var keyInfo   = new SubordPropHashKey(new QueryGraphValueEntryHashKeyedExpr(multi.Expression, false), null, multi.CoercionType);
                    var indexDesc = FindOrSuggestIndex(
                        Collections.SingletonMap(multi.IndexedProp[i], keyInfo),
                        Collections.GetEmptyMap <string, SubordPropRangeKey>(), optionalIndexHint, indexShare, subqueryNumber,
                        indexMetadata, optionalUniqueKeyProps, onlyUseExistingIndexes);
                    if (indexDesc == null)
                    {
                        return(null);
                    }
                    indexDescs[i] = indexDesc;
                }
                inKeywordMultiIdxKey = multi.Expression;
            }
            else
            {
                var indexDesc = FindOrSuggestIndex(joinDesc.HashProps,
                                                   joinDesc.RangeProps, optionalIndexHint, false, subqueryNumber,
                                                   indexMetadata, optionalUniqueKeyProps, onlyUseExistingIndexes);
                if (indexDesc == null)
                {
                    return(null);
                }
                var indexKeyInfo = indexDesc.IndexKeyInfo;
                hashKeys              = indexKeyInfo.OrderedHashDesc;
                hashKeyCoercionTypes  = indexKeyInfo.OrderedKeyCoercionTypes;
                rangeKeys             = indexKeyInfo.OrderedRangeDesc;
                rangeKeyCoercionTypes = indexKeyInfo.OrderedRangeCoercionTypes;
                var desc = new SubordinateQueryIndexDesc(indexDesc.IndexKeyInfo, indexDesc.IndexName, indexDesc.IndexMultiKey, indexDesc.QueryPlanIndexItem);
                indexDescs = new SubordinateQueryIndexDesc[] { desc };
            }

            if (forceTableScan)
            {
                return(null);
            }

            var lookupStrategyFactory = SubordinateTableLookupStrategyUtil.GetLookupStrategy(outerStreams,
                                                                                             hashKeys, hashKeyCoercionTypes, rangeKeys, rangeKeyCoercionTypes, inKeywordSingleIdxKeys, inKeywordMultiIdxKey, isNWOnTrigger);

            return(new SubordinateQueryPlanDesc(lookupStrategyFactory, indexDescs));
        }
Exemplo n.º 11
0
        public static SubordTableLookupStrategyFactory GetLookupStrategy(
            EventType[] outerStreamTypesZeroIndexed,
            IList <SubordPropHashKey> hashKeys,
            CoercionDesc hashKeyCoercionTypes,
            IList <SubordPropRangeKey> rangeKeys,
            CoercionDesc rangeKeyCoercionTypes,
            ExprNode[] inKeywordSingleIdxKeys,
            ExprNode inKeywordMultiIdxKey,
            bool isNWOnTrigger)
        {
            var isStrictKeys = SubordPropUtil.IsStrictKeyJoin(hashKeys);

            string[] hashStrictKeys       = null;
            int[]    hashStrictKeyStreams = null;
            if (isStrictKeys)
            {
                hashStrictKeyStreams = SubordPropUtil.GetKeyStreamNums(hashKeys);
                hashStrictKeys       = SubordPropUtil.GetKeyProperties(hashKeys);
            }

            int numStreamsTotal = outerStreamTypesZeroIndexed.Length + 1;
            SubordTableLookupStrategyFactory lookupStrategy;

            if (inKeywordSingleIdxKeys != null)
            {
                lookupStrategy = new SubordInKeywordSingleTableLookupStrategyFactory(isNWOnTrigger, numStreamsTotal, inKeywordSingleIdxKeys);
            }
            else if (inKeywordMultiIdxKey != null)
            {
                lookupStrategy = new SubordInKeywordMultiTableLookupStrategyFactory(isNWOnTrigger, numStreamsTotal, inKeywordMultiIdxKey);
            }
            else if (hashKeys.IsEmpty() && rangeKeys.IsEmpty())
            {
                lookupStrategy = new SubordFullTableScanLookupStrategyFactory();
            }
            else if (hashKeys.Count > 0 && rangeKeys.IsEmpty())
            {
                if (hashKeys.Count == 1)
                {
                    if (!hashKeyCoercionTypes.IsCoerce)
                    {
                        if (isStrictKeys)
                        {
                            lookupStrategy = new SubordIndexedTableLookupStrategySinglePropFactory(
                                isNWOnTrigger, outerStreamTypesZeroIndexed, hashStrictKeyStreams[0], hashStrictKeys[0]);
                        }
                        else
                        {
                            lookupStrategy = new SubordIndexedTableLookupStrategySingleExprFactory(
                                isNWOnTrigger, numStreamsTotal, hashKeys[0]);
                        }
                    }
                    else
                    {
                        lookupStrategy = new SubordIndexedTableLookupStrategySingleCoercingFactory(
                            isNWOnTrigger, numStreamsTotal, hashKeys[0], hashKeyCoercionTypes.CoercionTypes[0]);
                    }
                }
                else
                {
                    if (!hashKeyCoercionTypes.IsCoerce)
                    {
                        if (isStrictKeys)
                        {
                            lookupStrategy = new SubordIndexedTableLookupStrategyPropFactory(
                                isNWOnTrigger, outerStreamTypesZeroIndexed, hashStrictKeyStreams, hashStrictKeys);
                        }
                        else
                        {
                            lookupStrategy = new SubordIndexedTableLookupStrategyExprFactory(
                                isNWOnTrigger, numStreamsTotal, hashKeys);
                        }
                    }
                    else
                    {
                        lookupStrategy = new SubordIndexedTableLookupStrategyCoercingFactory(
                            isNWOnTrigger, numStreamsTotal, hashKeys, hashKeyCoercionTypes.CoercionTypes);
                    }
                }
            }
            else if (hashKeys.Count == 0 && rangeKeys.Count == 1)
            {
                lookupStrategy = new SubordSortedTableLookupStrategyFactory(isNWOnTrigger, numStreamsTotal, rangeKeys[0]);
            }
            else
            {
                lookupStrategy = new SubordCompositeTableLookupStrategyFactory(
                    isNWOnTrigger, numStreamsTotal, hashKeys, hashKeyCoercionTypes.CoercionTypes,
                    rangeKeys, rangeKeyCoercionTypes.CoercionTypes);
            }
            return(lookupStrategy);
        }
Exemplo n.º 12
0
        public static SubordTableLookupStrategyFactoryForge GetLookupStrategy(
            IList<EventType> outerStreamTypesZeroIndexed,
            IList<SubordPropHashKeyForge> hashKeys,
            CoercionDesc hashKeyCoercionTypes,
            MultiKeyClassRef hashMultikeyClasses,
            IList<SubordPropRangeKeyForge> rangeKeys,
            CoercionDesc rangeKeyCoercionTypes,
            IList<ExprNode> inKeywordSingleIdxKeys,
            ExprNode inKeywordMultiIdxKey,
            bool isNWOnTrigger)
        {
            bool isStrictKeys = SubordPropUtil.IsStrictKeyJoin(hashKeys);
            string[] hashStrictKeys = null;
            int[] hashStrictKeyStreams = null;
            if (isStrictKeys) {
                hashStrictKeyStreams = SubordPropUtil.GetKeyStreamNums(hashKeys);
                hashStrictKeys = SubordPropUtil.GetKeyProperties(hashKeys);
            }

            var numStreamsTotal = outerStreamTypesZeroIndexed.Count + 1;
            SubordTableLookupStrategyFactoryForge lookupStrategy;
            if (inKeywordSingleIdxKeys != null) {
                lookupStrategy = new SubordInKeywordSingleTableLookupStrategyFactoryForge(
                    isNWOnTrigger,
                    numStreamsTotal,
                    inKeywordSingleIdxKeys);
            }
            else if (inKeywordMultiIdxKey != null) {
                lookupStrategy = new SubordInKeywordMultiTableLookupStrategyFactoryForge(
                    isNWOnTrigger,
                    numStreamsTotal,
                    inKeywordMultiIdxKey);
            }
            else if (hashKeys.IsEmpty() && rangeKeys.IsEmpty()) {
                lookupStrategy = new SubordFullTableScanLookupStrategyFactoryForge();
            }
            else if (hashKeys.Count > 0 && rangeKeys.IsEmpty()) {
                lookupStrategy = new SubordHashedTableLookupStrategyFactoryForge(
                    isNWOnTrigger,
                    numStreamsTotal,
                    hashKeys,
                    hashKeyCoercionTypes,
                    isStrictKeys,
                    hashStrictKeys,
                    hashStrictKeyStreams,
                    outerStreamTypesZeroIndexed,
                    hashMultikeyClasses);
            }
            else if (hashKeys.Count == 0 && rangeKeys.Count == 1) {
                lookupStrategy = new SubordSortedTableLookupStrategyFactoryForge(
                    isNWOnTrigger,
                    numStreamsTotal,
                    rangeKeys[0],
                    rangeKeyCoercionTypes);
            }
            else {
                lookupStrategy = new SubordCompositeTableLookupStrategyFactoryForge(
                    isNWOnTrigger,
                    numStreamsTotal,
                    hashKeys,
                    hashKeyCoercionTypes.CoercionTypes,
                    hashMultikeyClasses,
                    rangeKeys,
                    rangeKeyCoercionTypes.CoercionTypes);
            }

            return lookupStrategy;
        }
Exemplo n.º 13
0
        public static SubordinateQueryPlan PlanSubquery(
            EventType[] outerStreams,
            SubordPropPlan joinDesc,
            bool isNWOnTrigger,
            bool forceTableScan,
            IndexHint optionalIndexHint,
            bool indexShare,
            int subqueryNumber,
            bool isVirtualDataWindow,
            EventTableIndexMetadata indexMetadata,
            ISet<string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes,
            EventType eventTypeIndexed,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (isVirtualDataWindow) {
                var indexProps = GetIndexPropDesc(joinDesc.HashProps, joinDesc.RangeProps);
                var lookupStrategyFactoryX = new SubordTableLookupStrategyFactoryForgeVDW(
                    statementRawInfo.StatementName,
                    statementRawInfo.Annotations,
                    outerStreams,
                    indexProps.HashJoinedProps,
                    new CoercionDesc(false, indexProps.HashIndexCoercionType),
                    indexProps.RangeJoinedProps,
                    new CoercionDesc(false, indexProps.RangeIndexCoercionType),
                    isNWOnTrigger,
                    joinDesc,
                    forceTableScan,
                    indexProps.ListPair);
                var forge = new SubordinateQueryPlanDescForge(lookupStrategyFactoryX, null);
                return new SubordinateQueryPlan(forge, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            if (joinDesc.CustomIndexOps != null && !joinDesc.CustomIndexOps.IsEmpty()) {
                foreach (var op
                    in joinDesc.CustomIndexOps) {
                    foreach (var index in indexMetadata.Indexes) {
                        if (IsCustomIndexMatch(index, op)) {
                            var provisionDesc =
                                index.Value.OptionalQueryPlanIndexItem.AdvancedIndexProvisionDesc;
                            var lookupStrategyFactoryX =
                                provisionDesc.Factory.Forge.GetSubordinateLookupStrategy(
                                    op.Key.OperationName,
                                    op.Value.PositionalExpressions,
                                    isNWOnTrigger,
                                    outerStreams.Length);
                            var provisionCompileTime =
                                provisionDesc.ToCompileTime(eventTypeIndexed, statementRawInfo, services);
                            var indexItemForge = new QueryPlanIndexItemForge(
                                new string[0],
                                new Type[0],
                                new string[0],
                                new Type[0],
                                false,
                                provisionCompileTime,
                                eventTypeIndexed);
                            var indexDesc = new SubordinateQueryIndexDescForge(
                                null,
                                index.Value.OptionalIndexName,
                                index.Value.OptionalIndexModuleName,
                                index.Key,
                                indexItemForge);
                            var forge = new SubordinateQueryPlanDescForge(lookupStrategyFactoryX, new SubordinateQueryIndexDescForge[]{indexDesc});
                            return new SubordinateQueryPlan(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                        }
                    }
                }
            }

            var hashKeys = Collections.GetEmptyList<SubordPropHashKeyForge>();
            CoercionDesc hashKeyCoercionTypes = null;
            var rangeKeys = Collections.GetEmptyList<SubordPropRangeKeyForge>();
            CoercionDesc rangeKeyCoercionTypes = null;
            IList<ExprNode> inKeywordSingleIdxKeys = null;
            ExprNode inKeywordMultiIdxKey = null;

            SubordinateQueryIndexDescForge[] indexDescs;
            var additionalForgeables = new List<StmtClassForgeableFactory>();
            MultiKeyClassRef multiKeyClasses = null;
            if (joinDesc.InKeywordSingleIndex != null) {
                var single = joinDesc.InKeywordSingleIndex;
                var keyInfo = new SubordPropHashKeyForge(
                    new QueryGraphValueEntryHashKeyedForgeExpr(single.Expressions[0], false),
                    null,
                    single.CoercionType);
                var index = FindOrSuggestIndex(
                    Collections.SingletonMap(single.IndexedProp, keyInfo),
                    EmptyDictionary<string, SubordPropRangeKeyForge>.Instance,
                    optionalIndexHint,
                    indexShare,
                    subqueryNumber,
                    indexMetadata,
                    optionalUniqueKeyProps,
                    onlyUseExistingIndexes,
                    eventTypeIndexed,
                    statementRawInfo,
                    services);
                
                if (index == null) {
                    return null;
                }

                var indexDesc = index.Forge;
                var desc = new SubordinateQueryIndexDescForge(
                    indexDesc.OptionalIndexKeyInfo,
                    indexDesc.IndexName,
                    indexDesc.IndexModuleName,
                    indexDesc.IndexMultiKey,
                    indexDesc.OptionalQueryPlanIndexItem);
                indexDescs = new[] {desc};
                inKeywordSingleIdxKeys = single.Expressions;
                additionalForgeables.AddAll(index.MultiKeyForgeables);
            }
            else if (joinDesc.InKeywordMultiIndex != null) {
                var multi = joinDesc.InKeywordMultiIndex;

                indexDescs = new SubordinateQueryIndexDescForge[multi.IndexedProp.Length];
                for (var i = 0; i < multi.IndexedProp.Length; i++) {
                    var keyInfo = new SubordPropHashKeyForge(
                        new QueryGraphValueEntryHashKeyedForgeExpr(multi.Expression, false),
                        null,
                        multi.CoercionType);
                    var index = FindOrSuggestIndex(
                        Collections.SingletonMap(multi.IndexedProp[i], keyInfo),
                        EmptyDictionary<string, SubordPropRangeKeyForge>.Instance,
                        optionalIndexHint,
                        indexShare,
                        subqueryNumber,
                        indexMetadata,
                        optionalUniqueKeyProps,
                        onlyUseExistingIndexes,
                        eventTypeIndexed,
                        statementRawInfo,
                        services);
                    var indexDesc = index.Forge;
                    additionalForgeables.AddAll(index.MultiKeyForgeables);
                    if (indexDesc == null) {
                        return null;
                    }

                    indexDescs[i] = indexDesc;
                }

                inKeywordMultiIdxKey = multi.Expression;
            }
            else {
                var index = FindOrSuggestIndex(
                    joinDesc.HashProps,
                    joinDesc.RangeProps,
                    optionalIndexHint,
                    false,
                    subqueryNumber,
                    indexMetadata,
                    optionalUniqueKeyProps,
                    onlyUseExistingIndexes,
                    eventTypeIndexed,
                    statementRawInfo,
                    services);
                if (index == null) {
                    return null;
                }
                var indexDesc = index.Forge;
                additionalForgeables.AddRange(index.MultiKeyForgeables);
                var indexKeyInfo = indexDesc.OptionalIndexKeyInfo;

                hashKeys = indexKeyInfo.OrderedHashDesc;
                hashKeyCoercionTypes = indexKeyInfo.OrderedKeyCoercionTypes;
                rangeKeys = indexKeyInfo.OrderedRangeDesc;
                rangeKeyCoercionTypes = indexKeyInfo.OrderedRangeCoercionTypes;
                var desc = new SubordinateQueryIndexDescForge(
                    indexDesc.OptionalIndexKeyInfo,
                    indexDesc.IndexName,
                    indexDesc.IndexModuleName,
                    indexDesc.IndexMultiKey,
                    indexDesc.OptionalQueryPlanIndexItem);
                indexDescs = new[] {desc};
                
                if (indexDesc.OptionalQueryPlanIndexItem == null) {
                    var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashKeyCoercionTypes.CoercionTypes, true, statementRawInfo, services.SerdeResolver);
                    multiKeyClasses = multiKeyPlan.ClassRef;
                    additionalForgeables.AddRange(multiKeyPlan.MultiKeyForgeables);
                } else {
                    multiKeyClasses = indexDesc.OptionalQueryPlanIndexItem.HashMultiKeyClasses;
                }
            }

            if (forceTableScan) {
                return null;
            }

            var lookupStrategyFactory = SubordinateTableLookupStrategyUtil.GetLookupStrategy(
                outerStreams,
                hashKeys,
                hashKeyCoercionTypes,
                multiKeyClasses,
                rangeKeys,
                rangeKeyCoercionTypes,
                inKeywordSingleIdxKeys,
                inKeywordMultiIdxKey,
                isNWOnTrigger);
            var forgeX = new SubordinateQueryPlanDescForge(lookupStrategyFactory, indexDescs);
            return new SubordinateQueryPlan(forgeX, additionalForgeables);
        }
        /// <summary>
        ///     Constructs indexing and lookup strategy for a given relationship that a historical stream may have with another
        ///     stream (historical or not) that looks up into results of a poll of a historical stream.
        ///     <para />
        ///     The term "polled" refers to the assumed-historical stream.
        /// </summary>
        /// <param name="queryGraph">relationship representation of where-clause filter and outer join on-expressions</param>
        /// <param name="polledViewType">the event type of the historical that is indexed</param>
        /// <param name="streamViewType">the event type of the stream looking up in indexes</param>
        /// <param name="polledViewStreamNum">the stream number of the historical that is indexed</param>
        /// <param name="streamViewStreamNum">the stream number of the historical that is looking up</param>
        /// <param name="raw"></param>
        /// <param name="serdeResolver"></param>
        /// <returns>indexing and lookup strategy pair</returns>
        public static JoinSetComposerPrototypeHistoricalDesc DetermineIndexing(
            QueryGraphForge queryGraph,
            EventType polledViewType,
            EventType streamViewType,
            int polledViewStreamNum,
            int streamViewStreamNum,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var queryGraphValue = queryGraph.GetGraphValue(streamViewStreamNum, polledViewStreamNum);
            var hashKeysAndIndes = queryGraphValue.HashKeyProps;
            var rangeKeysAndIndex = queryGraphValue.RangeProps;

            // index and key property names
            var hashKeys = hashKeysAndIndes.Keys;
            var hashIndexes = hashKeysAndIndes.Indexed;
            var rangeKeys = rangeKeysAndIndex.Keys;
            var rangeIndexes = rangeKeysAndIndex.Indexed;

            // If the analysis revealed no join columns, must use the brute-force full table scan
            if (hashKeys.IsEmpty() && rangeKeys.IsEmpty()) {
                var inKeywordSingles = queryGraphValue.InKeywordSingles;
                if (inKeywordSingles != null && inKeywordSingles.Indexed.Length != 0) {
                    var indexed = inKeywordSingles.Indexed[0];
                    var lookup = inKeywordSingles.Key[0];
                    var strategy =
                        new HistoricalIndexLookupStrategyInKeywordSingleForge(streamViewStreamNum, lookup.KeyExprs);
                    var indexing = new PollResultIndexingStrategyHashForge(
                        polledViewStreamNum,
                        polledViewType,
                        new string[]{ indexed },
                        null,
                        null);
                    return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
                }

                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty()) {
                    var multi = multis[0];
                    var strategy =
                        new HistoricalIndexLookupStrategyInKeywordMultiForge(streamViewStreamNum, multi.Key.KeyExpr);
                    var indexing =
                        new PollResultIndexingStrategyInKeywordMultiForge(
                            polledViewStreamNum,
                            polledViewType,
                            ExprNodeUtilityQuery.GetIdentResolvedPropertyNames(multi.Indexed));
                    return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
                }

                return new JoinSetComposerPrototypeHistoricalDesc(
                    HistoricalIndexLookupStrategyNoIndexForge.INSTANCE,
                    PollResultIndexingStrategyNoIndexForge.INSTANCE,
                    EmptyList<StmtClassForgeableFactory>.Instance);
            }

            CoercionDesc keyCoercionTypes = CoercionUtil.GetCoercionTypesHash(
                new[] {streamViewType, polledViewType},
                0,
                1,
                hashKeys,
                hashIndexes);

            if (rangeKeys.IsEmpty()) {
                var hashEvals = QueryGraphValueEntryHashKeyedForge.GetForges(hashKeys.ToArray());
                var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashEvals, false, raw, serdeResolver);
                var lookup = new HistoricalIndexLookupStrategyHashForge(
                    streamViewStreamNum, hashEvals, keyCoercionTypes.CoercionTypes, multiKeyPlan.ClassRef);
                var indexing = new PollResultIndexingStrategyHashForge(
                    polledViewStreamNum,
                    polledViewType,
                    hashIndexes,
                    keyCoercionTypes.CoercionTypes,
                    multiKeyPlan.ClassRef);
                return new JoinSetComposerPrototypeHistoricalDesc(lookup, indexing, multiKeyPlan.MultiKeyForgeables);
            }

            CoercionDesc rangeCoercionTypes = CoercionUtil.GetCoercionTypesRange(
                new[] {streamViewType, polledViewType},
                1,
                rangeIndexes,
                rangeKeys);

            if (rangeKeys.Count == 1 && hashKeys.Count == 0) {
                var rangeCoercionType = rangeCoercionTypes.CoercionTypes[0];
                var indexing = new PollResultIndexingStrategySortedForge(
                    polledViewStreamNum,
                    polledViewType,
                    rangeIndexes[0],
                    rangeCoercionType);
                var lookup = new HistoricalIndexLookupStrategySortedForge(
                    streamViewStreamNum,
                    rangeKeys[0],
                    rangeCoercionType);
                return new JoinSetComposerPrototypeHistoricalDesc(lookup, indexing, EmptyList<StmtClassForgeableFactory>.Instance);
            }
            else {
                var hashEvals = QueryGraphValueEntryHashKeyedForge.GetForges(hashKeys.ToArray());
                var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(hashEvals, false, raw, serdeResolver);
                var strategy = new HistoricalIndexLookupStrategyCompositeForge(
                    streamViewStreamNum,
                    hashEvals,
                    multiKeyPlan.ClassRef,
                    rangeKeys.ToArray());
                var indexing = new PollResultIndexingStrategyCompositeForge(
                    polledViewStreamNum,
                    polledViewType,
                    hashIndexes,
                    keyCoercionTypes.CoercionTypes,
                    multiKeyPlan.ClassRef,
                    rangeIndexes,
                    rangeCoercionTypes.CoercionTypes);
                return new JoinSetComposerPrototypeHistoricalDesc(strategy, indexing, multiKeyPlan.MultiKeyForgeables);
            }
        }