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; }
public IndexDetailForge( IndexMultiKey indexMultiKey, QueryPlanIndexItemForge queryPlanIndexItem) { this.indexMultiKey = indexMultiKey; this.queryPlanIndexItem = queryPlanIndexItem; }
public SubordinateQueryIndexPlan( QueryPlanIndexItemForge indexItem, IndexMultiKey indexPropKey, IList<StmtClassForgeableFactory> multiKeyForgeables) { IndexItem = indexItem; IndexPropKey = indexPropKey; MultiKeyForgeables = multiKeyForgeables; }
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); } }
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); }