private static IList<FilterSpecParam> ComputePermutation( FilterParamExprMap filterParamExprMap, object[] permutation, FilterParamExprMap[][] orNodesMaps, FilterSpecCompilerArgs args) { var mapAll = new FilterParamExprMap(); mapAll.Add(filterParamExprMap); // combine for (int orNodeNum = 0; orNodeNum < permutation.Length; orNodeNum++) { var orChildNodeNum = permutation[orNodeNum].AsInt(); FilterParamExprMap mapOrSub = orNodesMaps[orNodeNum][orChildNodeNum]; mapAll.Add(mapOrSub); } // consolidate across FilterSpecCompilerConsolidateUtil.Consolidate(mapAll, args.StatementName); IList<FilterSpecParam> filterParams = new List<FilterSpecParam>(); filterParams.AddAll(mapAll.FilterParams); int countUnassigned = mapAll.CountUnassignedExpressions(); if (countUnassigned == 0) { return filterParams; } FilterSpecParamExprNode node = MakeRemainingNode(mapAll.UnassignedExpressions, args); filterParams.Add(node); return filterParams; }
internal static IList<FilterSpecParam>[] PlanFilterParameters( IList<ExprNode> validatedNodes, FilterSpecCompilerArgs args) { if (validatedNodes.IsEmpty()) { return AllocateListArray(0); } var filterParamExprMap = new FilterParamExprMap(); // Make filter parameter for each expression node, if it can be optimized DecomposePopulateConsolidate(filterParamExprMap, validatedNodes, args); // Use all filter parameter and unassigned expressions IList<FilterSpecParam> filterParams = new List<FilterSpecParam>(); filterParams.AddAll(filterParamExprMap.FilterParams); int countUnassigned = filterParamExprMap.CountUnassignedExpressions(); // we are done if there are no remaining nodes if (countUnassigned == 0) { return AllocateListArraySizeOne(filterParams); } // determine max-width int filterServiceMaxFilterWidth = args.ConfigurationInformation.EngineDefaults.ExecutionConfig.FilterServiceMaxFilterWidth; HintAttribute hint = HintEnum.MAX_FILTER_WIDTH.GetHint(args.Annotations); if (hint != null) { string hintValue = HintEnum.MAX_FILTER_WIDTH.GetHintAssignedValue(hint); filterServiceMaxFilterWidth = int.Parse(hintValue); } IList<FilterSpecParam>[] plan = null; if (filterServiceMaxFilterWidth > 0) { plan = PlanRemainingNodesIfFeasible(filterParamExprMap, args, filterServiceMaxFilterWidth); } if (plan != null) { return plan; } // handle no-plan FilterSpecParamExprNode node = MakeRemainingNode(filterParamExprMap.UnassignedExpressions, args); filterParams.Add(node); return AllocateListArraySizeOne(filterParams); }
// remove duplicate propertyName + filterOperator items making a judgement to optimize or simply remove the optimized form private static void Consolidate(IList <FilterSpecParam> items, FilterParamExprMap filterParamExprMap, string statementName) { var op = items[0].FilterOperator; if (op == FilterOperator.NOT_EQUAL) { HandleConsolidateNotEqual(items, filterParamExprMap, statementName); } else { // for all others we simple remove the second optimized form (filter param with same prop name and filter op) // and thus the boolean expression that started this is included for (var i = 1; i < items.Count; i++) { filterParamExprMap.RemoveValue(items[i]); } } }
public static void Consolidate(FilterParamExprMap filterParamExprMap, string statementName) { // consolidate or place in a boolean expression (by removing filter spec param from the map) // any filter parameter that feature the same property name and filter operator, // i.e. we are looking for "a!=5 and a!=6" to transform to "a not in (5,6)" which can match faster // considering that "a not in (5,6) and a not in (7,8)" is "a not in (5, 6, 7, 8)" therefore // we need to consolidate until there is no more work to do IDictionary <Pair <FilterSpecLookupable, FilterOperator>, IList <FilterSpecParam> > mapOfParams = new Dictionary <Pair <FilterSpecLookupable, FilterOperator>, IList <FilterSpecParam> >(); bool haveConsolidated; do { haveConsolidated = false; mapOfParams.Clear(); // sort into buckets of propertyName + filterOperator combination foreach (var currentParam in filterParamExprMap.FilterParams) { var lookupable = currentParam.Lookupable; var op = currentParam.FilterOperator; var key = new Pair <FilterSpecLookupable, FilterOperator>(lookupable, op); var existingParam = mapOfParams.Get(key); if (existingParam == null) { existingParam = new List <FilterSpecParam>(); mapOfParams.Put(key, existingParam); } existingParam.Add(currentParam); } foreach (var entry in mapOfParams.Values) { if (entry.Count > 1) { haveConsolidated = true; Consolidate(entry, filterParamExprMap, statementName); } } }while(haveConsolidated); }
private static void DecomposePopulateConsolidate( FilterParamExprMap filterParamExprMap, IList<ExprNode> validatedNodes, FilterSpecCompilerArgs args) { IList<ExprNode> constituents = DecomposeCheckAggregation(validatedNodes); // Make filter parameter for each expression node, if it can be optimized foreach (ExprNode constituent in constituents) { FilterSpecParam param = FilterSpecCompilerMakeParamUtil.MakeFilterParam( constituent, args.ArrayEventTypes, args.ExprEvaluatorContext, args.StatementName); filterParamExprMap.Put(constituent, param); // accepts null values as the expression may not be optimized } // Consolidate entries as possible, i.e. (a != 5 and a != 6) is (a not in (5,6)) // Removes duplicates for same property and same filter operator for filter service index optimizations FilterSpecCompilerConsolidateUtil.Consolidate(filterParamExprMap, args.StatementName); }
// consolidate "val != 3 and val != 4 and val != 5" // to "val not in (3, 4, 5)" private static void HandleConsolidateNotEqual(IList <FilterSpecParam> parameters, FilterParamExprMap filterParamExprMap, string statementName) { IList <FilterSpecParamInValue> values = new List <FilterSpecParamInValue>(); ExprNode lastNotEqualsExprNode = null; foreach (var param in parameters) { if (param is FilterSpecParamConstant) { var constantParam = (FilterSpecParamConstant)param; var constant = constantParam.FilterConstant; values.Add(new InSetOfValuesConstant(constant)); } else if (param is FilterSpecParamEventProp) { var eventProp = (FilterSpecParamEventProp)param; values.Add(new InSetOfValuesEventProp(eventProp.ResultEventAsName, eventProp.ResultEventProperty, eventProp.IsMustCoerce, TypeHelper.GetBoxedType(eventProp.CoercionType))); } else if (param is FilterSpecParamEventPropIndexed) { var eventProp = (FilterSpecParamEventPropIndexed)param; values.Add(new InSetOfValuesEventPropIndexed(eventProp.ResultEventAsName, eventProp.ResultEventIndex, eventProp.ResultEventProperty, eventProp.IsMustCoerce, TypeHelper.GetBoxedType(eventProp.CoercionType), statementName)); } else { throw new ArgumentException("Unknown filter parameter:" + param.ToString()); } lastNotEqualsExprNode = filterParamExprMap.RemoveEntry(param); } var paramIn = new FilterSpecParamIn(parameters[0].Lookupable, FilterOperator.NOT_IN_LIST_OF_VALUES, values); filterParamExprMap.Put(lastNotEqualsExprNode, paramIn); }
private static IList<FilterSpecParam>[] PlanRemainingNodesIfFeasible( FilterParamExprMap overallExpressions, FilterSpecCompilerArgs args, int filterServiceMaxFilterWidth) { IList<ExprNode> unassigned = overallExpressions.UnassignedExpressions; IList<ExprOrNode> orNodes = new List<ExprOrNode>(unassigned.Count); foreach (ExprNode node in unassigned) { if (node is ExprOrNode) { orNodes.Add((ExprOrNode) node); } } var expressionsWithoutOr = new FilterParamExprMap(); expressionsWithoutOr.Add(overallExpressions); // first dimension: or-node index // second dimension: or child node index var orNodesMaps = new FilterParamExprMap[orNodes.Count][]; int countOr = 0; int sizeFactorized = 1; var sizePerOr = new int[orNodes.Count]; foreach (ExprOrNode orNode in orNodes) { expressionsWithoutOr.RemoveNode(orNode); orNodesMaps[countOr] = new FilterParamExprMap[orNode.ChildNodes.Length]; int len = orNode.ChildNodes.Length; for (int i = 0; i < len; i++) { var map = new FilterParamExprMap(); orNodesMaps[countOr][i] = map; IList<ExprNode> nodes = Collections.SingletonList(orNode.ChildNodes[i]); DecomposePopulateConsolidate(map, nodes, args); } sizePerOr[countOr] = len; sizeFactorized = sizeFactorized*len; countOr++; } // we become too large if (sizeFactorized > filterServiceMaxFilterWidth) { return null; } // combine var result = new IList<FilterSpecParam>[sizeFactorized]; IEnumerable<object[]> permutations = CombinationEnumeration.FromZeroBasedRanges(sizePerOr); int count = 0; foreach (var permutation in permutations) { result[count] = ComputePermutation(expressionsWithoutOr, permutation, orNodesMaps, args); count++; } return result; }
public void Add(FilterParamExprMap other) { _exprNodes.PutAll(other._exprNodes); _specParams.PutAll(other._specParams); }