private static List<StmtClassForgeableFactory> PlanMultikeys(
            QueryPlanIndexForge[] indexSpecs,
            StatementRawInfo raw,
            StatementCompileTimeServices compileTimeServices)
        {
            List<StmtClassForgeableFactory> multiKeyForgeables = new List<StmtClassForgeableFactory>();
            foreach (QueryPlanIndexForge spec in indexSpecs) {
                if (spec == null) {
                    continue;
                }
                foreach (var entry in spec.Items) {
                    QueryPlanIndexItemForge forge = entry.Value;

                    MultiKeyPlan plan = MultiKeyPlanner.PlanMultiKey(
                        forge.HashTypes, false, raw, compileTimeServices.SerdeResolver);
                    multiKeyForgeables.AddAll(plan.MultiKeyForgeables);
                    forge.HashMultiKeyClasses = plan.ClassRef;

                    DataInputOutputSerdeForge[] rangeSerdes = new DataInputOutputSerdeForge[forge.RangeTypes.Length];
                    for (int i = 0; i < forge.RangeTypes.Length; i++) {
                        rangeSerdes[i] = compileTimeServices.SerdeResolver.SerdeForIndexBtree(forge.RangeTypes[i], raw);
                    }
                    forge.RangeSerdes = rangeSerdes;
                }
            }
            return multiKeyForgeables;
        }
Exemple #2
0
 public IndexDetailForge(
     IndexMultiKey indexMultiKey,
     QueryPlanIndexItemForge queryPlanIndexItem)
 {
     this.indexMultiKey = indexMultiKey;
     this.queryPlanIndexItem = queryPlanIndexItem;
 }
Exemple #3
0
 public SubordinateQueryIndexPlan(
     QueryPlanIndexItemForge indexItem,
     IndexMultiKey indexPropKey,
     IList<StmtClassForgeableFactory> multiKeyForgeables)
 {
     IndexItem = indexItem;
     IndexPropKey = indexPropKey;
     MultiKeyForgeables = multiKeyForgeables;
 }
Exemple #4
0
 public SubordinateQueryIndexDescForge(
     IndexKeyInfo optionalIndexKeyInfo,
     string indexName,
     string indexModuleName,
     IndexMultiKey indexMultiKey,
     QueryPlanIndexItemForge optionalQueryPlanIndexItem)
 {
     OptionalIndexKeyInfo = optionalIndexKeyInfo;
     IndexName = indexName;
     IndexModuleName = indexModuleName;
     IndexMultiKey = indexMultiKey;
     OptionalQueryPlanIndexItem = optionalQueryPlanIndexItem;
 }
        private static void CheckDuplicateOrAdd(
            QueryPlanIndexItemForge proposed,
            IList<QueryPlanIndexItemForge> indexesSet)
        {
            var found = false;
            foreach (var index in indexesSet) {
                if (proposed.EqualsCompareSortedProps(index)) {
                    found = true;
                    break;
                }
            }

            if (!found) {
                indexesSet.Add(proposed);
            }
        }
Exemple #6
0
 public StatementAgentInstanceFactoryCreateIndexForge(
     EventType eventType,
     string indexName,
     string indexModuleName,
     QueryPlanIndexItemForge explicitIndexDesc,
     IndexMultiKey imk,
     NamedWindowMetaData namedWindow,
     TableMetaData table)
 {
     this.eventType = eventType;
     this.indexName = indexName;
     this.indexModuleName = indexModuleName;
     this.explicitIndexDesc = explicitIndexDesc;
     this.imk = imk;
     this.namedWindow = namedWindow;
     this.table = table;
 }
 private static void CompareIndexItem(
     int stream,
     int num,
     QueryPlanIndexItemForge expectedIndex,
     QueryPlanIndexItemForge actualIndex)
 {
     if (!expectedIndex.EqualsCompareSortedProps(actualIndex)) {
         Assert.Fail(
             "At stream " +
             stream +
             " index " +
             num +
             "\nExpected:\n" +
             expectedIndex +
             "\n" +
             "Received:\n" +
             actualIndex +
             "\n");
     }
 }
        private static SubordinateQueryIndexPlan PlanIndex(
            bool unique,
            IList<IndexedPropDesc> hashProps,
            IList<IndexedPropDesc> btreeProps,
            EventType eventTypeIndexed,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // not resolved as full match and not resolved as unique index match, allocate
            var indexPropKey = new IndexMultiKey(unique, hashProps, btreeProps, null);

            var indexedPropDescs = hashProps.ToArray();
            var indexProps = IndexedPropDesc.GetIndexProperties(indexedPropDescs);
            var indexCoercionTypes = IndexedPropDesc.GetCoercionTypes(indexedPropDescs);

            var rangePropDescs = btreeProps.ToArray();
            var rangeProps = IndexedPropDesc.GetIndexProperties(rangePropDescs);
            var rangeCoercionTypes = IndexedPropDesc.GetCoercionTypes(rangePropDescs);

            var indexItem = new QueryPlanIndexItemForge(
                indexProps,
                indexCoercionTypes,
                rangeProps,
                rangeCoercionTypes,
                unique,
                null,
                eventTypeIndexed);
            
            
            var multiKeyPlan = MultiKeyPlanner.PlanMultiKey(indexCoercionTypes, true, raw, services.SerdeResolver);
            indexItem.HashMultiKeyClasses = multiKeyPlan.ClassRef;

            var rangeSerdes = new DataInputOutputSerdeForge[rangeCoercionTypes.Length];
            for (var i = 0; i < rangeCoercionTypes.Length; i++) {
                rangeSerdes[i] = services.SerdeResolver.SerdeForIndexBtree(rangeCoercionTypes[i], raw);
            }
            indexItem.RangeSerdes = rangeSerdes;

            return new SubordinateQueryIndexPlan(indexItem, indexPropKey, multiKeyPlan.MultiKeyForgeables);
        }
        /// <summary>
        ///     Build index specification from navigability info.
        ///     <para />
        ///     Looks at each stream and determines which properties in the stream must be indexed
        ///     in order for other streams to look up into the stream. Determines the unique set of properties
        ///     to avoid building duplicate indexes on the same set of properties.
        /// </summary>
        /// <param name="queryGraph">navigability info</param>
        /// <param name="typePerStream">type info</param>
        /// <param name="indexedStreamsUniqueProps">per-stream unique props</param>
        /// <returns>query index specs for each stream</returns>
        public static QueryPlanIndexForge[] BuildIndexSpec(
            QueryGraphForge queryGraph,
            EventType[] typePerStream,
            string[][][] indexedStreamsUniqueProps)
        {
            var numStreams = queryGraph.NumStreams;
            var indexSpecs = new QueryPlanIndexForge[numStreams];

            // For each stream compile a list of index property sets.
            for (var streamIndexed = 0; streamIndexed < numStreams; streamIndexed++) {
                IList<QueryPlanIndexItemForge> indexesSet = new List<QueryPlanIndexItemForge>();

                // Look at the index from the viewpoint of the stream looking up in the index
                for (var streamLookup = 0; streamLookup < numStreams; streamLookup++) {
                    if (streamIndexed == streamLookup) {
                        continue;
                    }

                    var value = queryGraph.GetGraphValue(streamLookup, streamIndexed);
                    var hashKeyAndIndexProps = value.HashKeyProps;

                    // Sort index properties, but use the sorted properties only to eliminate duplicates
                    var hashIndexProps = hashKeyAndIndexProps.Indexed;
                    var hashKeyProps = hashKeyAndIndexProps.Keys;
                    var indexCoercionTypes = CoercionUtil.GetCoercionTypesHash(
                        typePerStream,
                        streamLookup,
                        streamIndexed,
                        hashKeyProps,
                        hashIndexProps);
                    var hashCoercionTypeArr = indexCoercionTypes.CoercionTypes;

                    var rangeAndIndexProps = value.RangeProps;
                    var rangeIndexProps = rangeAndIndexProps.Indexed;
                    var rangeKeyProps = rangeAndIndexProps.Keys;
                    var rangeCoercionTypes = CoercionUtil.GetCoercionTypesRange(
                        typePerStream,
                        streamIndexed,
                        rangeIndexProps,
                        rangeKeyProps);
                    var rangeCoercionTypeArr = rangeCoercionTypes.CoercionTypes;

                    if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) {
                        var singles = value.InKeywordSingles;
                        if (!singles.Key.IsEmpty()) {
                            var indexedProp = singles.Indexed[0];
                            var indexedType = typePerStream[streamIndexed].GetPropertyType(indexedProp);
                            var indexItem = new QueryPlanIndexItemForge(
                                new[] {indexedProp},
                                new[] {indexedType},
                                new string[0],
                                new Type[0],
                                false,
                                null,
                                typePerStream[streamIndexed]);
                            CheckDuplicateOrAdd(indexItem, indexesSet);
                        }

                        var multis = value.InKeywordMulti;
                        if (!multis.IsEmpty()) {
                            QueryGraphValuePairInKWMultiIdx multi = multis[0];
                            foreach (var propIndexed in multi.Indexed) {
                                var identNode = (ExprIdentNode) propIndexed;
                                var type = identNode.Forge.EvaluationType;
                                var indexItem = new QueryPlanIndexItemForge(
                                    new[] {identNode.ResolvedPropertyName},
                                    new[] {type},
                                    new string[0],
                                    new Type[0],
                                    false,
                                    null,
                                    typePerStream[streamIndexed]);
                                CheckDuplicateOrAdd(indexItem, indexesSet);
                            }
                        }

                        continue;
                    }

                    // reduce to any unique index if applicable
                    var unique = false;
                    var reduced = QueryPlanIndexUniqueHelper.ReduceToUniqueIfPossible(
                        hashIndexProps,
                        hashCoercionTypeArr,
                        hashKeyProps,
                        indexedStreamsUniqueProps[streamIndexed]);
                    if (reduced != null) {
                        hashIndexProps = reduced.PropertyNames;
                        hashCoercionTypeArr = reduced.CoercionTypes;
                        unique = true;
                        rangeIndexProps = new string[0];
                        rangeCoercionTypeArr = new Type[0];
                    }

                    var proposed = new QueryPlanIndexItemForge(
                        hashIndexProps,
                        hashCoercionTypeArr,
                        rangeIndexProps,
                        rangeCoercionTypeArr,
                        unique,
                        null,
                        typePerStream[streamIndexed]);
                    CheckDuplicateOrAdd(proposed, indexesSet);
                }

                // create full-table-scan
                if (indexesSet.IsEmpty()) {
                    indexesSet.Add(
                        new QueryPlanIndexItemForge(
                            new string[0],
                            new Type[0],
                            new string[0],
                            new Type[0],
                            false,
                            null,
                            typePerStream[streamIndexed]));
                }

                indexSpecs[streamIndexed] = QueryPlanIndexForge.MakeIndex(indexesSet);
            }

            return indexSpecs;
        }
        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);
        }
        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);
        }