Esempio n. 1
0
        private static SubordinateQueryPlannerIndexPropDesc GetIndexPropDesc(
            IDictionary<string, SubordPropHashKeyForge> hashProps,
            IDictionary<string, SubordPropRangeKeyForge> rangeProps)
        {
            // hash property names and types
            var hashIndexPropsProvided = new string[hashProps.Count];
            var hashIndexCoercionType = new Type[hashProps.Count];
            var hashJoinedProps = new SubordPropHashKeyForge[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 SubordPropRangeKeyForge[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);
        }
Esempio n. 2
0
        private static SubordinateQueryIndexSuggest FindOrSuggestIndex(
            IDictionary<string, SubordPropHashKeyForge> hashProps,
            IDictionary<string, SubordPropRangeKeyForge> rangeProps,
            IndexHint optionalIndexHint,
            bool isIndexShare,
            int subqueryNumber,
            EventTableIndexMetadata indexMetadata,
            ISet<string> optionalUniqueKeyProps,
            bool onlyUseExistingIndexes,
            EventType eventTypeIndexed,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            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;
            string indexModuleName = null;
            QueryPlanIndexItemForge planIndexItem = null;

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

            Pair<IndexMultiKey, NameAndModule> existing = null;
            SubordinateQueryIndexPlan 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, NameAndModule>(
                    indexFoundPair,
                    new NameAndModule(hintIndex.OptionalIndexName, hintIndex.OptionalIndexModuleName));
            }

            // 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 = new EmptyList<IndexedPropDesc>();
                        unique = true;
                        coerce = false;
                    }
                }

                planned = PlanIndex(unique, proposedHashedProps, proposedBtreeProps, eventTypeIndexed, raw, services);
            }

            // compile index information
            if (existing == null && planned == null) {
                return null;
            }

            // handle existing
            IList<StmtClassForgeableFactory> multiKeyForgeables;
            if (existing != null) {
                indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(
                    existing.First,
                    indexProps.HashIndexPropsProvided,
                    indexProps.HashJoinedProps,
                    indexProps.RangeIndexPropsProvided,
                    indexProps.RangeJoinedProps);
                indexName = existing.Second.Name;
                indexModuleName = existing.Second.ModuleName;
                indexMultiKey = existing.First;
                multiKeyForgeables = EmptyList<StmtClassForgeableFactory>.Instance;
            }
            else {
                // handle planned
                indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(
                    planned.IndexPropKey,
                    indexProps.HashIndexPropsProvided,
                    indexProps.HashJoinedProps,
                    indexProps.RangeIndexPropsProvided,
                    indexProps.RangeJoinedProps);
                indexMultiKey = planned.IndexPropKey;
                planIndexItem = planned.IndexItem;
                multiKeyForgeables = planned.MultiKeyForgeables;
            }

            var forge = new SubordinateQueryIndexDescForge(indexKeyInfo, indexName, indexModuleName, indexMultiKey, planIndexItem);
            return new SubordinateQueryIndexSuggest(forge, multiKeyForgeables);
        }