/// <summary>Ctor.</summary>
 /// <param name="eventTableIndexMetadata">metadata for index</param>
 public EventTableIndexRepository(EventTableIndexMetadata eventTableIndexMetadata)
 {
     _tables = new List <EventTable>();
     _tableIndexesRefCount    = new Dictionary <IndexMultiKey, EventTableIndexRepositoryEntry>();
     _explicitIndexes         = new Dictionary <string, EventTable>();
     _eventTableIndexMetadata = eventTableIndexMetadata;
     _transIndexesRefCount    = new TransformDictionary <
         IndexMultiKey, EventTableIndexEntryBase,
         IndexMultiKey, EventTableIndexRepositoryEntry>(
         _tableIndexesRefCount,
         kOut => kOut,
         kIn => kIn,
         vOut => vOut,
         vIn => (EventTableIndexRepositoryEntry)vIn);
 }
        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));
            }
        }
Beispiel #3
0
 public static void AddIndexMetaAndRef(SubordinateQueryIndexDesc[] indexDescs, EventTableIndexMetadata repo, string statementName)
 {
     foreach (var desc in indexDescs)
     {
         if (desc.IndexName != null)
         {
             repo.AddIndexReference(desc.IndexName, statementName);
         }
         else
         {
             repo.AddIndex(false, desc.IndexMultiKey, null, statementName, false, desc.QueryPlanIndexItem);
             repo.AddIndexReference(desc.IndexMultiKey, statementName);
         }
     }
 }
        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));
        }
        private static SubordinateQueryIndexDesc FindOrSuggestIndex(
            IDictionary <String, SubordPropHashKey> hashProps,
            IDictionary <String, SubordPropRangeKey> rangeProps,
            IndexHint optionalIndexHint,
            bool isIndexShare,
            int subqueryNumber,
            EventTableIndexMetadata indexMetadata,
            ICollection <string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes)
        {
            var indexProps          = GetIndexPropDesc(hashProps, rangeProps);
            var hashedAndBtreeProps = indexProps.ListPair;

            // Get or create the table for this index (exact match or property names, type of index and coercion type is expected)
            IndexKeyInfo       indexKeyInfo; // how needs all of IndexKeyInfo+QueryPlanIndexItem+IndexMultiKey
            IndexMultiKey      indexMultiKey;
            string             indexName     = null;
            QueryPlanIndexItem planIndexItem = null;

            if (hashedAndBtreeProps.HashedProps.IsEmpty() && hashedAndBtreeProps.BtreeProps.IsEmpty())
            {
                return(null);
            }

            Pair <IndexMultiKey, string>             existing = null;
            Pair <QueryPlanIndexItem, IndexMultiKey> planned  = null;

            // consider index hints
            IList <IndexHintInstruction> optionalIndexHintInstructions = null;

            if (optionalIndexHint != null)
            {
                optionalIndexHintInstructions = optionalIndexHint.GetInstructionsSubquery(subqueryNumber);
            }

            var indexFoundPair = EventTableIndexUtil.FindIndexConsiderTyping(indexMetadata.Indexes, hashedAndBtreeProps.HashedProps, hashedAndBtreeProps.BtreeProps, optionalIndexHintInstructions);

            if (indexFoundPair != null)
            {
                var hintIndex = indexMetadata.Indexes.Get(indexFoundPair);
                existing = new Pair <IndexMultiKey, string>(indexFoundPair, hintIndex.OptionalIndexName);
            }

            // nothing found: plan one
            if (existing == null && !onlyUseExistingIndexes)
            {
                // not found, see if the item is declared unique
                var proposedHashedProps = hashedAndBtreeProps.HashedProps;
                var proposedBtreeProps  = hashedAndBtreeProps.BtreeProps;

                // match against unique-key properties when suggesting an index
                var unique = false;
                var coerce = !isIndexShare;
                if (optionalUniqueKeyProps != null && !optionalUniqueKeyProps.IsEmpty())
                {
                    IList <IndexedPropDesc> newHashProps = new List <IndexedPropDesc>();
                    foreach (var uniqueKey in optionalUniqueKeyProps)
                    {
                        var found = false;
                        foreach (var hashProp in hashedAndBtreeProps.HashedProps)
                        {
                            if (hashProp.IndexPropName.Equals(uniqueKey))
                            {
                                newHashProps.Add(hashProp);
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            newHashProps = null;
                            break;
                        }
                    }
                    if (newHashProps != null)
                    {
                        proposedHashedProps = newHashProps;
                        proposedBtreeProps  = Collections.GetEmptyList <IndexedPropDesc>();
                        unique = true;
                        coerce = false;
                    }
                }

                planned = PlanIndex(unique, proposedHashedProps, proposedBtreeProps, coerce);
            }

            // compile index information
            if (existing == null && planned == null)
            {
                return(null);
            }
            // handle existing
            if (existing != null)
            {
                indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(existing.First,
                                                                               indexProps.HashIndexPropsProvided, indexProps.HashJoinedProps,
                                                                               indexProps.RangeIndexPropsProvided, indexProps.RangeJoinedProps);
                indexName     = existing.Second;
                indexMultiKey = existing.First;
            }
            // handle planned
            else
            {
                indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(planned.Second,
                                                                               indexProps.HashIndexPropsProvided, indexProps.HashJoinedProps,
                                                                               indexProps.RangeIndexPropsProvided, indexProps.RangeJoinedProps);
                indexMultiKey = planned.Second;
                planIndexItem = planned.First;
            }

            return(new SubordinateQueryIndexDesc(indexKeyInfo, indexName, indexMultiKey, planIndexItem));
        }