private static RangeIndexLookupValue[] CompileRangeLookupValues(string[] rangeIndexProps, FilterSpecParam[] parameters, AgentInstanceContext agentInstanceContext) { var result = new RangeIndexLookupValue[rangeIndexProps.Length]; for (var rangeIndex = 0; rangeIndex < rangeIndexProps.Length; rangeIndex++) { foreach (var param in parameters) { if (!(param.Lookupable.Expression.Equals(rangeIndexProps[rangeIndex]))) { continue; } if (param.FilterOperator == FilterOperator.EQUAL || param.FilterOperator == FilterOperator.IS) { result[rangeIndex] = new RangeIndexLookupValueEquals(param.GetFilterValue(null, agentInstanceContext)); } else if (param.FilterOperator.IsRangeOperator() || param.FilterOperator.IsInvertedRangeOperator()) { QueryGraphRangeEnum opAdd = param.FilterOperator.MapFrom(); result[rangeIndex] = new RangeIndexLookupValueRange(param.GetFilterValue(null, agentInstanceContext), opAdd, true); } else if (param.FilterOperator.IsComparisonOperator()) { var existing = result[rangeIndex]; QueryGraphRangeEnum opAdd = param.FilterOperator.MapFrom(); if (existing == null) { result[rangeIndex] = new RangeIndexLookupValueRange(param.GetFilterValue(null, agentInstanceContext), opAdd, true); } else { if (!(existing is RangeIndexLookupValueRange)) { continue; } var existingRange = (RangeIndexLookupValueRange)existing; var opExist = existingRange.Operator; var desc = QueryGraphRangeUtil.GetCanConsolidate(opExist, opAdd); if (desc != null) { var doubleRange = GetDoubleRange(desc.IsReverse, existing.Value, param.GetFilterValue(null, agentInstanceContext)); result[rangeIndex] = new RangeIndexLookupValueRange(doubleRange, desc.RangeType, false); } } } } } return(result); }
public static SubordPropPlan GetJoinProps( ExprNode filterExpr, int outsideStreamCount, EventType[] allStreamTypesZeroIndexed, ExcludePlanHint excludePlanHint) { // No filter expression means full table scan if (filterExpr == null) { return new SubordPropPlan(); } // analyze query graph var queryGraph = new QueryGraphForge(outsideStreamCount + 1, excludePlanHint, true); FilterExprAnalyzer.Analyze(filterExpr, queryGraph, false); // Build a list of streams and indexes var joinProps = new LinkedHashMap<string, SubordPropHashKeyForge>(); var rangeProps = new LinkedHashMap<string, SubordPropRangeKeyForge>(); IDictionary<QueryGraphValueEntryCustomKeyForge, QueryGraphValueEntryCustomOperationForge> customIndexOps = EmptyDictionary<QueryGraphValueEntryCustomKeyForge, QueryGraphValueEntryCustomOperationForge>.Instance; for (var stream = 0; stream < outsideStreamCount; stream++) { var lookupStream = stream + 1; var queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0); var hashKeysAndIndexes = queryGraphValue.HashKeyProps; // determine application functions foreach (var item in queryGraphValue.Items) { if (item.Entry is QueryGraphValueEntryCustomForge) { if (customIndexOps.IsEmpty()) { customIndexOps = new Dictionary<QueryGraphValueEntryCustomKeyForge, QueryGraphValueEntryCustomOperationForge>(); } var custom = (QueryGraphValueEntryCustomForge) item.Entry; custom.MergeInto(customIndexOps); } } // handle key-lookups var keyPropertiesJoin = hashKeysAndIndexes.Keys; var indexPropertiesJoin = hashKeysAndIndexes.Indexed; if (!keyPropertiesJoin.IsEmpty()) { if (keyPropertiesJoin.Count != indexPropertiesJoin.Length) { throw new IllegalStateException( "Invalid query key and index property collection for stream " + stream); } for (var i = 0; i < keyPropertiesJoin.Count; i++) { QueryGraphValueEntryHashKeyedForge keyDesc = keyPropertiesJoin[i]; var compareNode = keyDesc.KeyExpr; var keyPropType = compareNode.Forge.EvaluationType.GetBoxedType(); var indexedPropType = allStreamTypesZeroIndexed[0] .GetPropertyType(indexPropertiesJoin[i]) .GetBoxedType(); var coercionType = indexedPropType; if (keyPropType != indexedPropType) { coercionType = keyPropType.GetCompareToCoercionType(indexedPropType); } SubordPropHashKeyForge desc; if (keyPropertiesJoin[i] is QueryGraphValueEntryHashKeyedForgeExpr) { var keyExpr = (QueryGraphValueEntryHashKeyedForgeExpr) keyPropertiesJoin[i]; var keyStreamNum = keyExpr.IsRequiresKey ? (int?) stream : null; desc = new SubordPropHashKeyForge(keyDesc, keyStreamNum, coercionType); } else { var prop = (QueryGraphValueEntryHashKeyedForgeProp) keyDesc; desc = new SubordPropHashKeyForge(prop, stream, coercionType); } joinProps.Put(indexPropertiesJoin[i], desc); } } // handle range lookups var rangeKeysAndIndexes = queryGraphValue.RangeProps; var rangeIndexes = rangeKeysAndIndexes.Indexed; var rangeDescs = rangeKeysAndIndexes.Keys; if (rangeDescs.IsEmpty()) { continue; } // get all ranges lookups var count = -1; foreach (var rangeDesc in rangeDescs) { count++; var rangeIndexProp = rangeIndexes[count]; var subqRangeDesc = rangeProps.Get(rangeIndexProp); // other streams may specify the start or end endpoint of a range, therefore this operation can be additive if (subqRangeDesc != null) { if (subqRangeDesc.RangeInfo.Type.IsRange()) { continue; } // see if we can make this additive by using a range var relOpOther = (QueryGraphValueEntryRangeRelOpForge) subqRangeDesc.RangeInfo; var relOpThis = (QueryGraphValueEntryRangeRelOpForge) rangeDesc; var opsDesc = QueryGraphRangeUtil.GetCanConsolidate(relOpThis.Type, relOpOther.Type); if (opsDesc != null) { ExprNode start; ExprNode end; if (!opsDesc.IsReverse) { start = relOpOther.Expression; end = relOpThis.Expression; } else { start = relOpThis.Expression; end = relOpOther.Expression; } var allowRangeReversal = relOpOther.IsBetweenPart && relOpThis.IsBetweenPart; var rangeIn = new QueryGraphValueEntryRangeInForge( opsDesc.Type, start, end, allowRangeReversal); var indexedPropType = allStreamTypesZeroIndexed[0] .GetPropertyType(rangeIndexProp) .GetBoxedType(); var coercionType = indexedPropType; var proposedType = CoercionUtil.GetCoercionTypeRangeIn( indexedPropType, rangeIn.ExprStart, rangeIn.ExprEnd); if (proposedType != null && proposedType != indexedPropType) { coercionType = proposedType; } subqRangeDesc = new SubordPropRangeKeyForge(rangeIn, coercionType); rangeProps.Put(rangeIndexProp, subqRangeDesc); } // ignore continue; } // an existing entry has not been found if (rangeDesc.Type.IsRange()) { var rangeIn = (QueryGraphValueEntryRangeInForge) rangeDesc; var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType(); var coercionType = indexedPropType; var proposedType = CoercionUtil.GetCoercionTypeRangeIn( indexedPropType, rangeIn.ExprStart, rangeIn.ExprEnd); if (proposedType != null && proposedType != indexedPropType) { coercionType = proposedType; } subqRangeDesc = new SubordPropRangeKeyForge(rangeDesc, coercionType); } else { var relOp = (QueryGraphValueEntryRangeRelOpForge) rangeDesc; var keyPropType = relOp.Expression.Forge.EvaluationType; var indexedPropType = allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType(); var coercionType = indexedPropType; if (keyPropType != indexedPropType) { coercionType = keyPropType.GetCompareToCoercionType(indexedPropType); } subqRangeDesc = new SubordPropRangeKeyForge(rangeDesc, coercionType); } rangeProps.Put(rangeIndexProp, subqRangeDesc); } } SubordPropInKeywordSingleIndex inKeywordSingleIdxProp = null; SubordPropInKeywordMultiIndex inKeywordMultiIdxProp = null; if (joinProps.IsEmpty() && rangeProps.IsEmpty()) { for (var stream = 0; stream < outsideStreamCount; stream++) { var lookupStream = stream + 1; var queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0); var inkwSingles = queryGraphValue.InKeywordSingles; if (inkwSingles.Indexed.Length != 0) { ExprNode[] keys = inkwSingles.Key[0].KeyExprs; var key = inkwSingles.Indexed[0]; if (inKeywordSingleIdxProp != null) { continue; } var coercionType = keys[0].Forge.EvaluationType; // for in-comparison the same type is required inKeywordSingleIdxProp = new SubordPropInKeywordSingleIndex(key, coercionType, keys); } var inkwMultis = queryGraphValue.InKeywordMulti; if (!inkwMultis.IsEmpty()) { QueryGraphValuePairInKWMultiIdx multi = inkwMultis[0]; inKeywordMultiIdxProp = new SubordPropInKeywordMultiIndex( ExprNodeUtilityQuery.GetIdentResolvedPropertyNames(multi.Indexed), multi.Indexed[0].Forge.EvaluationType, multi.Key.KeyExpr); } if (inKeywordSingleIdxProp != null && inKeywordMultiIdxProp != null) { inKeywordMultiIdxProp = null; } } } return new SubordPropPlan( joinProps, rangeProps, inKeywordSingleIdxProp, inKeywordMultiIdxProp, customIndexOps); }