예제 #1
0
 public SubordinateQueryIndexSuggest(
     SubordinateQueryIndexDescForge forge,
     IList<StmtClassForgeableFactory> multiKeyForgeables)
 {
     Forge = forge;
     MultiKeyForgeables = multiKeyForgeables;
 }
예제 #2
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);
        }
예제 #3
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);
        }