private EventTableIndexMetadataEntry GetIndexEntry(EPServiceProvider epService, bool namedWindow, string name) { var descOne = new IndexedPropDesc("col0", typeof(string)); var index = new IndexMultiKey(false, Collections.List(descOne), Collections. GetEmptyList<IndexedPropDesc>(), null); var meta = GetIndexMetaRepo(epService, namedWindow, name); return meta.Indexes.Get(index); }
public string[][] GetUniqueIndexes(NamedWindowProcessorInstance processorInstance) { IList <string[]> unique = null; if (processorInstance != null) { var indexDescriptors = processorInstance.IndexDescriptors; foreach (var index in indexDescriptors) { if (!index.IsUnique) { continue; } var uniqueKeys = IndexedPropDesc.GetIndexProperties(index.HashIndexedProps); if (unique == null) { unique = new List <string[]>(); } unique.Add(uniqueKeys); } } if (_optionalUniqueKeyProps != null) { if (unique == null) { unique = new List <string[]>(); } unique.Add(_optionalUniqueKeyProps.ToArray()); } if (unique == null) { return(null); } return(unique.ToArray()); }
public static string[][] GetUniqueness( EventTableIndexMetadata indexMetadata, string[] optionalViewUniqueness) { IList<string[]> unique = null; foreach (var index in indexMetadata.Indexes.Keys) { if (!index.IsUnique) { continue; } var uniqueKeys = IndexedPropDesc.GetIndexProperties(index.HashIndexedProps); if (unique == null) { unique = new List<string[]>(); } unique.Add(uniqueKeys); } if (optionalViewUniqueness != null) { if (unique == null) { unique = new List<string[]>(); } unique.Add(optionalViewUniqueness); } return unique?.ToArray(); }
private EventTableIndexMetadataEntry GetIndexEntry(bool namedWindow) { var descOne = new IndexedPropDesc("col0", typeof(string)); var index = new IndexMultiKey(false, Collections.SingletonList(descOne), Collections.GetEmptyList <IndexedPropDesc>()); var meta = GetIndexMetaRepo(namedWindow); return(meta.Indexes.Get(index)); }
private static void ValidateBuiltin( CreateIndexItem columnDesc, EventType eventType, IList<IndexedPropDesc> hashProps, IList<IndexedPropDesc> btreeProps, ISet<string> indexedColumns) { if (columnDesc.Expressions.IsEmpty()) { throw new ExprValidationException("Invalid empty list of index expressions"); } if (columnDesc.Expressions.Count > 1) { throw new ExprValidationException( "Invalid multiple index expressions for index type '" + columnDesc.IndexType + "'"); } ExprNode expression = columnDesc.Expressions[0]; if (!(expression is ExprIdentNode)) { throw new ExprValidationException( "Invalid index expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expression) + "'"); } var identNode = (ExprIdentNode) expression; if (identNode.FullUnresolvedName.Contains(".")) { throw new ExprValidationException( "Invalid index expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expression) + "'"); } var columnName = identNode.FullUnresolvedName; Type type = Boxing.GetBoxedType(eventType.GetPropertyType(columnName)); if (type == null) { throw new ExprValidationException("Property named '" + columnName + "' not found"); } if (!indexedColumns.Add(columnName)) { throw new ExprValidationException( "Property named '" + columnName + "' has been declared more then once"); } var desc = new IndexedPropDesc(columnName, type); string indexType = columnDesc.IndexType; if (indexType.Equals(CreateIndexType.HASH.GetName(), StringComparison.InvariantCultureIgnoreCase)) { hashProps.Add(desc); } else { btreeProps.Add(desc); } }
private static EventTableIndexMetadataEntry GetIndexEntry( RegressionEnvironment env, bool namedWindow, string name) { var descOne = new IndexedPropDesc("col0", typeof(string)); var index = new IndexMultiKey( false, Arrays.AsList(descOne), Collections.GetEmptyList<IndexedPropDesc>(), null); var meta = GetIndexMetaRepo(env, namedWindow, name); return meta.Indexes.Get(index); }
public int Compare( IndexMultiKey o1, IndexMultiKey o2) { var indexedProps1 = IndexedPropDesc.GetIndexProperties(o1.HashIndexedProps); var indexedProps2 = IndexedPropDesc.GetIndexProperties(o2.HashIndexedProps); if (indexedProps1.Length > indexedProps2.Length) { return 1; // sort desc by count columns } if (indexedProps1.Length == indexedProps2.Length) { return 0; } return -1; }
private static bool IsExactMatch( IndexMultiKey existing, bool unique, IList<IndexedPropDesc> hashProps, IList<IndexedPropDesc> btreeProps) { if (existing.IsUnique != unique) { return false; } if (!IndexedPropDesc.Compare(existing.HashIndexedProps, hashProps)) { return false; } if (!IndexedPropDesc.Compare(existing.RangeIndexedProps, btreeProps)) { return false; } return true; }
public CodegenExpression Make( CodegenMethodScope parent, SAIFFInitializeSymbol symbols, CodegenClassScope classScope) { var hashes = new ExprNode[_hashKeys.Count]; var hashTypes = new Type[_hashKeys.Count]; for (var i = 0; i < _hashKeys.Count; i++) { hashes[i] = _hashKeys[i].HashKey.KeyExpr; hashTypes[i] = _hashKeyCoercionTypes.CoercionTypes[i]; } var ranges = new QueryGraphValueEntryRangeForge[_rangeKeys.Count]; var rangesTypes = new Type[_rangeKeys.Count]; for (var i = 0; i < _rangeKeys.Count; i++) { ranges[i] = _rangeKeys[i].RangeInfo; rangesTypes[i] = _rangeKeyCoercionTypes.CoercionTypes[i]; } var builder = new SAIFFInitializeBuilder( typeof(SubordTableLookupStrategyFactoryVDW), GetType(), "lookup", parent, symbols, classScope); builder .Expression("indexHashedProps", IndexedPropDesc.MakeArray(_hashAndRanges.HashedProps)) .Expression("indexBtreeProps", IndexedPropDesc.MakeArray(_hashAndRanges.BtreeProps)) .Constant("IsNwOnTrigger", _nwOnTrigger) .Constant("NumOuterStreams", _outerStreams.Length) .Expression( "hashEvals", ExprNodeUtilityCodegen.CodegenEvaluators(hashes, builder.Method(), GetType(), classScope)) .Constant("HashCoercionTypes", hashTypes) .Expression( "rangeEvals", QueryGraphValueEntryRangeForge.MakeArray(ranges, builder.Method(), symbols, classScope)) .Constant("RangeCoercionTypes", rangesTypes); return builder.Build(); }
private static bool IndexHashIsProvided( IndexedPropDesc hashPropIndexed, IList<IndexedPropDesc> hashPropsProvided) { foreach (var hashPropProvided in hashPropsProvided) { var nameMatch = hashPropProvided.IndexPropName.Equals(hashPropIndexed.IndexPropName); var typeMatch = true; if (hashPropProvided.CoercionType != null && !TypeHelper.IsSubclassOrImplementsInterface( hashPropProvided.CoercionType.GetBoxedType(), hashPropIndexed.CoercionType.GetBoxedType())) { typeMatch = false; } if (nameMatch && typeMatch) { return true; } } return false; }
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); }
public void Init() { // add index multi-key for implicit primary-key index if (KeyColumns == null || KeyColumns.Length == 0) { return; } var props = new IndexedPropDesc[KeyColumns.Length]; for (var i = 0; i < props.Length; i++) { props[i] = new IndexedPropDesc(KeyColumns[i], KeyTypes[i]); } KeyIndexMultiKey = new IndexMultiKey(true, props, new IndexedPropDesc[0], null); try { IndexMetadata.AddIndexExplicit(true, KeyIndexMultiKey, TableName, TableModuleName, null, ""); } catch (ExprValidationException e) { throw new EPException("Failed to add primary key index: " + e.Message, e); } }
public static ICollection <EventBean> Snapshot( FilterSpecCompiled optionalFilter, Attribute[] annotations, VirtualDWView virtualDataWindow, EventTableIndexRepository indexRepository, bool queryPlanLogging, ILog queryPlanLogDestination, string objectName, AgentInstanceContext agentInstanceContext) { if (optionalFilter == null || optionalFilter.Parameters.Length == 0) { if (virtualDataWindow != null) { var pair = virtualDataWindow.GetFireAndForgetDesc(Collections.GetEmptySet <string>(), Collections.GetEmptySet <string>()); return(virtualDataWindow.GetFireAndForgetData(pair.Second, new object[0], new RangeIndexLookupValue[0], annotations)); } return(null); } // Determine what straight-equals keys and which ranges are available. // Widening/Coercion is part of filter spec compile. ISet <string> keysAvailable = new HashSet <string>(); ISet <string> rangesAvailable = new HashSet <string>(); if (optionalFilter.Parameters.Length == 1) { foreach (FilterSpecParam param in optionalFilter.Parameters[0]) { if (!(param is FilterSpecParamConstant || param is FilterSpecParamRange || param is FilterSpecParamIn)) { continue; } if (param.FilterOperator == FilterOperator.EQUAL || param.FilterOperator == FilterOperator.IS || param.FilterOperator == FilterOperator.IN_LIST_OF_VALUES) { keysAvailable.Add(param.Lookupable.Expression); } else if (param.FilterOperator.IsRangeOperator() || param.FilterOperator.IsInvertedRangeOperator() || param.FilterOperator.IsComparisonOperator()) { rangesAvailable.Add(param.Lookupable.Expression); } else if (param.FilterOperator.IsRangeOperator()) { rangesAvailable.Add(param.Lookupable.Expression); } } } // Find an index that matches the needs Pair <IndexMultiKey, EventTableAndNamePair> tablePair; if (virtualDataWindow != null) { var tablePairNoName = virtualDataWindow.GetFireAndForgetDesc(keysAvailable, rangesAvailable); tablePair = new Pair <IndexMultiKey, EventTableAndNamePair>(tablePairNoName.First, new EventTableAndNamePair(tablePairNoName.Second, null)); } else { var indexHint = IndexHint.GetIndexHint(annotations); IList <IndexHintInstruction> optionalIndexHintInstructions = null; if (indexHint != null) { optionalIndexHintInstructions = indexHint.InstructionsFireAndForget; } tablePair = indexRepository.FindTable(keysAvailable, rangesAvailable, optionalIndexHintInstructions); } var hook = QueryPlanIndexHookUtil.GetHook(annotations); if (queryPlanLogging && (queryPlanLogDestination.IsInfoEnabled || hook != null)) { var prefix = "Fire-and-forget from " + objectName + " "; var indexName = tablePair != null && tablePair.Second != null ? tablePair.Second.IndexName : null; var indexText = indexName != null ? "index " + indexName + " " : "full table scan "; indexText += "(snapshot only, for join see separate query plan)"; if (tablePair == null) { queryPlanLogDestination.Info(prefix + indexText); } else { queryPlanLogDestination.Info(prefix + indexText + tablePair.Second.EventTable.ToQueryPlan()); } if (hook != null) { hook.FireAndForget(new QueryPlanIndexDescFAF( new IndexNameAndDescPair[] { new IndexNameAndDescPair(indexName, tablePair != null ? tablePair.Second.EventTable.ProviderClass.Name : null) })); } } if (tablePair == null) { return(null); // indicates table scan } // Compile key sets which contain key index lookup values var keyIndexProps = IndexedPropDesc.GetIndexProperties(tablePair.First.HashIndexedProps); var hasKeyWithInClause = false; var keyValues = new object[keyIndexProps.Length]; for (var keyIndex = 0; keyIndex < keyIndexProps.Length; keyIndex++) { foreach (var param in optionalFilter.Parameters[0]) { if (param.Lookupable.Expression.Equals(keyIndexProps[keyIndex])) { if (param.FilterOperator == FilterOperator.IN_LIST_OF_VALUES) { var keyValuesList = ((MultiKeyUntyped)param.GetFilterValue(null, agentInstanceContext)).Keys; if (keyValuesList.Length == 0) { continue; } else if (keyValuesList.Length == 1) { keyValues[keyIndex] = keyValuesList[0]; } else { keyValues[keyIndex] = keyValuesList; hasKeyWithInClause = true; } } else { keyValues[keyIndex] = param.GetFilterValue(null, agentInstanceContext); } break; } } } // Analyze ranges - these may include key lookup value (EQUALS semantics) var rangeIndexProps = IndexedPropDesc.GetIndexProperties(tablePair.First.RangeIndexedProps); RangeIndexLookupValue[] rangeValues; if (rangeIndexProps.Length > 0) { rangeValues = CompileRangeLookupValues(rangeIndexProps, optionalFilter.Parameters[0], agentInstanceContext); } else { rangeValues = new RangeIndexLookupValue[0]; } var eventTable = tablePair.Second.EventTable; var indexMultiKey = tablePair.First; // table lookup without in-clause if (!hasKeyWithInClause) { return(FafTableLookup(virtualDataWindow, indexMultiKey, eventTable, keyValues, rangeValues, annotations)); } // table lookup with in-clause: determine combinations var combinations = new object[keyIndexProps.Length][]; for (var i = 0; i < keyValues.Length; i++) { if (keyValues[i] is object[]) { combinations[i] = (object[])keyValues[i]; } else { combinations[i] = new object[] { keyValues[i] }; } } // enumerate combinations var enumeration = new CombinationEnumeration(combinations); var events = new HashSet <EventBean>(); for (; enumeration.MoveNext();) { object[] keys = enumeration.Current; var result = FafTableLookup(virtualDataWindow, indexMultiKey, eventTable, keys, rangeValues, annotations); events.AddAll(result); } return(events); }
/// <summary> /// Create the table lookup plan for a from-stream to look up in an indexed stream /// using the columns supplied in the query graph and looking at the actual indexes available /// and their index number. /// </summary> /// <param name="queryGraph">contains properties joining the 2 streams</param> /// <param name="currentLookupStream">stream to use key values from</param> /// <param name="indexedStream">stream to look up in</param> /// <param name="indexSpecs">index specification defining indexes to be created for stream</param> /// <param name="typesPerStream">event types for each stream</param> /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns> public static TableLookupPlan CreateLookupPlan(QueryGraph queryGraph, int currentLookupStream, int indexedStream, QueryPlanIndex indexSpecs, EventType[] typesPerStream, TableMetadata indexedStreamTableMeta) { var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream); var hashKeyProps = queryGraphValue.HashKeyProps; var hashPropsKeys = hashKeyProps.Keys; var hashIndexProps = hashKeyProps.Indexed.ToArray(); var rangeProps = queryGraphValue.RangeProps; var rangePropsKeys = rangeProps.Keys; var rangeIndexProps = rangeProps.Indexed.ToArray(); var pairIndexHashRewrite = indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps); var indexNum = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First; // handle index redirection towards unique index if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null) { var indexes = pairIndexHashRewrite.Second; var newHashIndexProps = new string[indexes.Length]; IList <QueryGraphValueEntryHashKeyed> newHashKeys = new List <QueryGraphValueEntryHashKeyed>(); for (var i = 0; i < indexes.Length; i++) { newHashIndexProps[i] = hashIndexProps[indexes[i]]; newHashKeys.Add(hashPropsKeys[indexes[i]]); } hashIndexProps = newHashIndexProps; hashPropsKeys = newHashKeys; rangeIndexProps = new string[0]; rangePropsKeys = Collections.GetEmptyList <QueryGraphValueEntryRange>(); } // no direct hash or range lookups if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) { // handle single-direction 'in' keyword var singles = queryGraphValue.InKeywordSingles; if (!singles.Key.IsEmpty()) { QueryGraphValueEntryInKeywordSingleIdx single = null; indexNum = null; if (indexedStreamTableMeta != null) { var indexes = singles.Indexed; var count = 0; foreach (var index in indexes) { Pair <IndexMultiKey, EventTableIndexEntryBase> indexPairFound = EventTableIndexUtil.FindIndexBestAvailable( indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes, Collections.SingletonSet(index), Collections.GetEmptySet <string>(), null); if (indexPairFound != null) { indexNum = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName); single = singles.Key[count]; } count++; } } else { single = singles.Key[0]; var pairIndex = indexSpecs.GetIndexNum(new string[] { singles.Indexed[0] }, null); indexNum = pairIndex.First; } if (indexNum != null) { return(new InKeywordTableLookupPlanSingleIdx(currentLookupStream, indexedStream, indexNum, single.KeyExprs)); } } // handle multi-direction 'in' keyword var multis = queryGraphValue.InKeywordMulti; if (!multis.IsEmpty()) { if (indexedStreamTableMeta != null) { return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta)); } QueryGraphValuePairInKWMultiIdx multi = multis[0]; var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length]; var foundAll = true; for (var i = 0; i < multi.Indexed.Length; i++) { var identNode = (ExprIdentNode)multi.Indexed[i]; var pairIndex = indexSpecs.GetIndexNum(new string[] { identNode.ResolvedPropertyName }, null); if (pairIndex == null) { foundAll = false; } else { indexNameArray[i] = pairIndex.First; } } if (foundAll) { return(new InKeywordTableLookupPlanMultiIdx(currentLookupStream, indexedStream, indexNameArray, multi.Key.KeyExpr)); } } // We don't use a keyed index but use the full stream set as the stream does not have any indexes // If no such full set index exists yet, add to specs if (indexedStreamTableMeta != null) { return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta)); } if (indexNum == null) { indexNum = new TableLookupIndexReqKey(indexSpecs.AddIndex(null, null)); } return(new FullTableScanLookupPlan(currentLookupStream, indexedStream, indexNum)); } if (indexNum == null) { throw new IllegalStateException("Failed to query plan as index for " + hashIndexProps.Render() + " and " + rangeIndexProps.Render() + " in the index specification"); } if (indexedStreamTableMeta != null) { var indexPairFound = EventTableIndexUtil.FindIndexBestAvailable(indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes, ToSet(hashIndexProps), ToSet(rangeIndexProps), null); if (indexPairFound != null) { var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(indexPairFound.First, hashIndexProps, GetHashKeyFuncsAsSubProp(hashPropsKeys), rangeIndexProps, GetRangeFuncsAsSubProp(rangePropsKeys)); if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce || indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce) { return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta)); } hashPropsKeys = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc); hashIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps); rangePropsKeys = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc); rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps); indexNum = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName); // the plan will be created below if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) { return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta)); } } else { return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta)); } } // straight keyed-index lookup if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0) { TableLookupPlan tableLookupPlan; if (hashPropsKeys.Count == 1) { tableLookupPlan = new IndexedTableLookupPlanSingle(currentLookupStream, indexedStream, indexNum, hashPropsKeys[0]); } else { tableLookupPlan = new IndexedTableLookupPlanMulti(currentLookupStream, indexedStream, indexNum, hashPropsKeys); } // Determine coercion required var coercionTypes = CoercionUtil.GetCoercionTypesHash(typesPerStream, currentLookupStream, indexedStream, hashPropsKeys, hashIndexProps); if (coercionTypes.IsCoerce) { // check if there already are coercion types for this index var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps); if (existCoercionTypes != null) { for (var i = 0; i < existCoercionTypes.Length; i++) { coercionTypes.CoercionTypes[i] = TypeHelper.GetCompareToCoercionType(existCoercionTypes[i], coercionTypes.CoercionTypes[i]); } } indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes); } return(tableLookupPlan); } // sorted index lookup if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1) { QueryGraphValueEntryRange range = rangePropsKeys[0]; return(new SortedTableLookupPlan(currentLookupStream, indexedStream, indexNum, range)); } // composite range and index lookup else { return(new CompositeTableLookupPlan(currentLookupStream, indexedStream, indexNum, hashPropsKeys, rangePropsKeys)); } }
/// <summary> /// Create the table lookup plan for a from-stream to look up in an indexed stream /// using the columns supplied in the query graph and looking at the actual indexes available /// and their index number. /// </summary> /// <param name="queryGraph">contains properties joining the 2 streams</param> /// <param name="currentLookupStream">stream to use key values from</param> /// <param name="indexedStream">stream to look up in</param> /// <param name="indexSpecs">index specification defining indexes to be created for stream</param> /// <param name="typesPerStream">event types for each stream</param> /// <param name="indexedStreamTableMeta">table info</param> /// <param name="indexedStreamIsVDW">vdw indicators</param> /// <param name="raw">raw statement information</param> /// <param name="serdeResolver">serde resolver</param> /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns> public static TableLookupPlanDesc CreateLookupPlan( QueryGraphForge queryGraph, int currentLookupStream, int indexedStream, bool indexedStreamIsVDW, QueryPlanIndexForge indexSpecs, EventType[] typesPerStream, TableMetaData indexedStreamTableMeta, StatementRawInfo raw, SerdeCompileTimeResolver serdeResolver) { var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream); var hashKeyProps = queryGraphValue.HashKeyProps; var hashPropsKeys = hashKeyProps.Keys; var hashIndexProps = hashKeyProps.Indexed; var rangeProps = queryGraphValue.RangeProps; var rangePropsKeys = rangeProps.Keys; var rangeIndexProps = rangeProps.Indexed; var pairIndexHashRewrite = indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps); var indexNum = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First; // handle index redirection towards unique index if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null) { var indexes = pairIndexHashRewrite.Second; var newHashIndexProps = new string[indexes.Length]; IList<QueryGraphValueEntryHashKeyedForge> newHashKeys = new List<QueryGraphValueEntryHashKeyedForge>(); for (var i = 0; i < indexes.Length; i++) { newHashIndexProps[i] = hashIndexProps[indexes[i]]; newHashKeys.Add(hashPropsKeys[indexes[i]]); } hashIndexProps = newHashIndexProps; hashPropsKeys = newHashKeys; rangeIndexProps = new string[0]; rangePropsKeys = Collections.GetEmptyList<QueryGraphValueEntryRangeForge>(); } // no direct hash or range lookups if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) { // handle single-direction 'in' keyword var singles = queryGraphValue.InKeywordSingles; if (!singles.Key.IsEmpty()) { QueryGraphValueEntryInKeywordSingleIdxForge single = null; indexNum = null; if (indexedStreamTableMeta != null) { var indexes = singles.Indexed; var count = 0; foreach (var index in indexes) { var indexPairFound = EventTableIndexUtil.FindIndexBestAvailable( indexedStreamTableMeta.IndexMetadata.Indexes, Collections.SingletonSet(index), Collections.GetEmptySet<string>(), null); if (indexPairFound != null) { indexNum = new TableLookupIndexReqKey( indexPairFound.Second.OptionalIndexName, indexPairFound.Second.OptionalIndexModuleName, indexedStreamTableMeta.TableName); single = singles.Key[count]; } count++; } } else { single = singles.Key[0]; var pairIndex = indexSpecs.GetIndexNum( new[] {singles.Indexed[0]}, new string[0]); indexNum = pairIndex.First; } if (indexNum != null) { var forge = new InKeywordTableLookupPlanSingleIdxForge( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum, single.KeyExprs); return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance); } } // handle multi-direction 'in' keyword var multis = queryGraphValue.InKeywordMulti; if (!multis.IsEmpty()) { if (indexedStreamTableMeta != null) { return GetFullTableScanTable( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexedStreamTableMeta); } var multi = multis[0]; var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length]; var foundAll = true; for (var i = 0; i < multi.Indexed.Length; i++) { var identNode = (ExprIdentNode) multi.Indexed[i]; var pairIndex = indexSpecs.GetIndexNum( new[] {identNode.ResolvedPropertyName}, new string[0]); if (pairIndex == null) { foundAll = false; } else { indexNameArray[i] = pairIndex.First; } } if (foundAll) { var forge = new InKeywordTableLookupPlanMultiIdxForge( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNameArray, multi.Key.KeyExpr); return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance); } } // We don't use a keyed index but use the full stream set as the stream does not have any indexes // If no such full set index exists yet, add to specs if (indexedStreamTableMeta != null) { return GetFullTableScanTable( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexedStreamTableMeta); } if (indexNum == null) { indexNum = new TableLookupIndexReqKey( indexSpecs.AddIndex(new string[0], new Type[0], typesPerStream[indexedStream]), null); } var forgeX = new FullTableScanLookupPlanForge(currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum); return new TableLookupPlanDesc(forgeX, EmptyList<StmtClassForgeableFactory>.Instance); } if (indexNum == null) { throw new IllegalStateException( "Failed to query plan as index for " + hashIndexProps.RenderAny() + " and " + rangeIndexProps.RenderAny() + " in the index specification"); } if (indexedStreamTableMeta != null) { var indexPairFound = EventTableIndexUtil.FindIndexBestAvailable( indexedStreamTableMeta.IndexMetadata.Indexes, ToSet(hashIndexProps), ToSet(rangeIndexProps), null); if (indexPairFound != null) { var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo( indexPairFound.First, hashIndexProps, GetHashKeyFuncsAsSubProp(hashPropsKeys), rangeIndexProps, GetRangeFuncsAsSubProp(rangePropsKeys)); if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce || indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce) { return GetFullTableScanTable( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexedStreamTableMeta); } hashPropsKeys = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc); hashIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps); rangePropsKeys = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc); rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps); indexNum = new TableLookupIndexReqKey( indexPairFound.Second.OptionalIndexName, indexPairFound.Second.OptionalIndexModuleName, indexedStreamTableMeta.TableName); // the plan will be created below if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) { return GetFullTableScanTable( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexedStreamTableMeta); } } else { return GetFullTableScanTable( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexedStreamTableMeta); } } // straight keyed-index lookup if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0) { // Determine coercion required var coercionTypes = CoercionUtil.GetCoercionTypesHash( typesPerStream, currentLookupStream, indexedStream, hashPropsKeys, hashIndexProps); if (coercionTypes.IsCoerce) { // check if there already are coercion types for this index var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps); if (existCoercionTypes != null) { for (var i = 0; i < existCoercionTypes.Length; i++) { coercionTypes.CoercionTypes[i] = existCoercionTypes[i] .GetCompareToCoercionType(coercionTypes.CoercionTypes[i]); } } if (!indexSpecs.Items.IsEmpty()) { indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes); } } var coercionTypesArray = coercionTypes.CoercionTypes; MultiKeyClassRef tableLookupMultiKey = null; IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance; if (indexNum.TableName != null) { var tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesArray, true, raw, serdeResolver); tableLookupMultiKey = tableMultiKeyPlan.ClassRef; additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables; } var forge = new IndexedTableLookupPlanHashedOnlyForge( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum, hashPropsKeys.ToArray(), indexSpecs, coercionTypesArray, tableLookupMultiKey); return new TableLookupPlanDesc(forge, additionalForgeables); } // sorted index lookup var coercionTypesRange = CoercionUtil.GetCoercionTypesRange( typesPerStream, indexedStream, rangeIndexProps, rangePropsKeys); var coercionTypesHash = CoercionUtil.GetCoercionTypesHash( typesPerStream, currentLookupStream, indexedStream, hashPropsKeys, hashIndexProps); if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1) { var range = rangePropsKeys[0]; Type coercionType = null; if (coercionTypesRange.IsCoerce) { coercionType = coercionTypesRange.CoercionTypes[0]; } SortedTableLookupPlanForge forge = new SortedTableLookupPlanForge( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum, range, coercionType); return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance); } else { MultiKeyClassRef tableLookupMultiKey = null; IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance; if (indexNum.TableName != null) { MultiKeyPlan tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesHash.CoercionTypes, true, raw, serdeResolver); tableLookupMultiKey = tableMultiKeyPlan.ClassRef; additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables; } // composite range and index lookup CompositeTableLookupPlanForge forge = new CompositeTableLookupPlanForge( currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum, hashPropsKeys, coercionTypesHash.CoercionTypes, rangePropsKeys, coercionTypesRange.CoercionTypes, indexSpecs, tableLookupMultiKey); return new TableLookupPlanDesc(forge, additionalForgeables); } }