private static SubordinateQueryPlannerIndexPropDesc GetIndexPropDesc(IDictionary <String, SubordPropHashKey> hashProps, IDictionary <String, SubordPropRangeKey> rangeProps) { // hash property names and types var hashIndexPropsProvided = new string[hashProps.Count]; var hashIndexCoercionType = new Type[hashProps.Count]; var hashJoinedProps = new SubordPropHashKey[hashProps.Count]; var count = 0; foreach (var entry in hashProps) { hashIndexPropsProvided[count] = entry.Key; hashIndexCoercionType[count] = entry.Value.CoercionType; hashJoinedProps[count++] = entry.Value; } // range property names and types var rangeIndexPropsProvided = new string[rangeProps.Count]; var rangeIndexCoercionType = new Type[rangeProps.Count]; var rangeJoinedProps = new SubordPropRangeKey[rangeProps.Count]; count = 0; foreach (var entry in rangeProps) { rangeIndexPropsProvided[count] = entry.Key; rangeIndexCoercionType[count] = entry.Value.CoercionType; rangeJoinedProps[count++] = entry.Value; } // Add all joined fields to an array for sorting var listPair = SubordinateQueryPlannerUtil.ToListOfHashedAndBtreeProps(hashIndexPropsProvided, hashIndexCoercionType, rangeIndexPropsProvided, rangeIndexCoercionType); return(new SubordinateQueryPlannerIndexPropDesc(hashIndexPropsProvided, hashIndexCoercionType, rangeIndexPropsProvided, rangeIndexCoercionType, listPair, hashJoinedProps, rangeJoinedProps)); }
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)); }