/// <summary> /// Returns two pins (smaller and greater)... both will be null if there is no intersecting range between the expressions. /// Unhandled cases: /// IN, NotIn, NotEquals, NotLike, NotBetween. /// </summary> private static void ReduceRecuringRanges(ref ProxyAndPredicate singleAttributeSet) { var repeatedAttributes = PredicateHelper.GetRepeatedAttributes(singleAttributeSet.TreePredicates); foreach (var attribute in repeatedAttributes) { var repeatedExpressions = new List <ComparisonPredicate>(); foreach (var value in singleAttributeSet.TreePredicates) { var expression = (ComparisonPredicate)value; if (attribute.ToString().Equals(expression.AttributeNames[0]) && ReducableExpression(expression)) { repeatedExpressions.Add(expression); } } if (repeatedExpressions.Count > 0) { //Ranges could be between, <, >, =, Not equals to Null... //Constants could be: Null, Bool, Number, String, DateTime, -not Array, -not JSONObject. Tuple <IJsonValue, IJsonValue> tuple = GetJSONValueRange(repeatedExpressions); if (tuple != null) { if (!(tuple.Item1 is NullValue) && !(tuple.Item2 is ObjectJsonValue)) { singleAttributeSet.TreePredicates.Add( new ComparisonPredicate(attribute, Condition.Between, PredicateHelper.GetConstant(tuple.Item1), PredicateHelper.GetConstant(tuple.Item2))); } else if (tuple.Item2 is ObjectJsonValue) { //Greater than/greater and equals to. singleAttributeSet.TreePredicates.Add( new ComparisonPredicate(attribute, Condition.GreaterThan, PredicateHelper.GetConstant(tuple.Item1))); } else { //Lesser than/lesser than and equals to. singleAttributeSet.TreePredicates.Add( new ComparisonPredicate(attribute, Condition.LesserThan, PredicateHelper.GetConstant(tuple.Item1))); } } else { singleAttributeSet.AddChildPredicate(new ProxyPredicate(new EmptyPredicate(), null)); } foreach (var expression in repeatedExpressions) { singleAttributeSet.TreePredicates.Remove(expression); } } } }
/// <summary> /// Assigns a proxy predicate to a single-attributed expressions. /// </summary> private static void AssignSingleAttributesPredicate(ProxyAndPredicate proxyAnd, ICollection <IIndex> indexes, IQueryStore queryStore) { OrderedList <string, ComparisonPredicate> attribExprList = new OrderedList <string, ComparisonPredicate>(); foreach (var value in proxyAnd.TreePredicates) { var expression = (ComparisonPredicate)value; if (expression.IsBinaryExpression) { continue; } attribExprList.Add(expression.AttributeNames[0], expression); } if (attribExprList.Count > 0) { foreach (var attribute in attribExprList.Keys) { IIndex lowestIndex = null; foreach (var index in indexes) { if (attribute.Equals(index.Attributes.Name)) { if (lowestIndex == null) { lowestIndex = index; } else if (lowestIndex.ValueCount > index.ValueCount) { lowestIndex = index; } } } if (lowestIndex != null) { foreach (var expression in attribExprList[attribute]) { proxyAnd.AddChildPredicate( new ProxyPredicate(expression.AssignIndexPredicate(lowestIndex, queryStore), expression)); proxyAnd.TreePredicates.Remove(expression); } } } //For every unassigned expression... if (proxyAnd.TreePredicates.Count > 0) { ITreePredicate assingedExpression; if (proxyAnd.TreePredicates.Count.Equals(1)) { assingedExpression = proxyAnd.TreePredicates[0]; } else { AndTreePredicate assingedAnd = new AndTreePredicate(); foreach (var expression in proxyAnd.TreePredicates) { assingedAnd.Add(expression); } assingedExpression = assingedAnd; } proxyAnd.AddChildPredicate(new ProxyPredicate( new StorePredicate(assingedExpression, queryStore), assingedExpression)); } } }
/// <summary> /// Tries to assign compound indexes to expressions if applicable... /// </summary> private static List <ProxyAndPredicate> AssignCompoundIndices(ProxyAndPredicate set, IEnumerable <IIndex> indexes, IQueryStore queryStore) { var attribExprList = new OrderedList <string, ComparisonPredicate>(); var proxyPredicates = new List <ProxyAndPredicate>(); //For every expression in the set ready for assignment. foreach (var expresson in set.TreePredicates) { var expression = (ComparisonPredicate)expresson; if (expression.IsBinaryExpression) { continue; } attribExprList.Add(expression.AttributeNames[0], expression); } //Each compound index will create a new state of the expression. foreach (var index in indexes) { int matchedNumber = 0; var matchedAttribs = new List <string>(); //If keys (attributes list) does not contain the first prefix of the index //Then the index is not usable. if (attribExprList.ContainsKey(index.Attributes.Name)) { matchedAttribs.Add(index.Attributes.Name); matchedNumber += attribExprList[index.Attributes.Name].Count; } //if matched attributes are < 2 no need of compound assignment. if (matchedAttribs.Count < 2) { continue; } //Assign each of them an index and get them to the predicate, and get the one with the lowest cost. ComparisonPredicate cheapestExpression = attribExprList[matchedAttribs[0]][0]; IPredicate cheapestPredicate = cheapestExpression.AssignIndexPredicate(index, queryStore); for (int i = 1; i < attribExprList[matchedAttribs[0]].Count; i++) { ComparisonPredicate tempExpression = attribExprList[matchedAttribs[0]][i]; IPredicate tempPredicate = tempExpression.AssignIndexPredicate(index, queryStore); if (tempPredicate.Statistics[Statistic.ExpectedIO] < cheapestPredicate.Statistics[Statistic.ExpectedIO]) { cheapestExpression = tempExpression; cheapestPredicate = tempPredicate; } } //For filteration and adding rest of expressions to the index. ITreePredicate assingedExpression = null; if (!matchedNumber.Equals(2)) { AndTreePredicate assingedAnd = new AndTreePredicate(); foreach (var attribute in matchedAttribs) { foreach (var expression in attribExprList[attribute]) { if (expression != cheapestExpression) { assingedAnd.Add(expression); } } } assingedExpression = assingedAnd; } else { foreach (var expression in attribExprList[matchedAttribs[1]]) { assingedExpression = expression; } } FilterPredicate filterPredicate = new FilterPredicate(assingedExpression, index); filterPredicate.AddChildPredicate(cheapestPredicate); ProxyAndPredicate proxyAnd = (ProxyAndPredicate)set.Clone(); //Removing assigned expressions. foreach (var attribute in matchedAttribs) { foreach (var expression in attribExprList[attribute]) { proxyAnd.TreePredicates.Remove(expression); } } proxyAnd.AddChildPredicate(new ProxyPredicate(filterPredicate, null)); proxyPredicates.Add(proxyAnd); } foreach (var proxyAnd in proxyPredicates) { //Recursive call for each ProxyAndPredicate. if (proxyAnd.TreePredicates.Count > 1) { var values = AssignCompoundIndices(proxyAnd, indexes, queryStore); foreach (var value in values) { proxyPredicates.Add(value); } } } return(proxyPredicates); }
public IProxyPredicate GetProxyExecutionPredicate(IIndexProvider indexManager, IQueryStore queryStore, IEnumerable <long> rowsEnumerator) { ProxyAndPredicate proxyPredicate = new ProxyAndPredicate(); proxyPredicate.AddTreePredicates(_predciates); if (!IsTerminal) { foreach (var predicate in _predciates) { proxyPredicate.AddChildPredicate( predicate.GetProxyExecutionPredicate(indexManager, queryStore, rowsEnumerator)); } return(proxyPredicate); } OrderedList <int, IIndex> indexes = indexManager.OrderedIndexList; ArrayList sets = new ArrayList(); ProxyAndPredicate singleSet = new ProxyAndPredicate(); foreach (var value in proxyPredicate.TreePredicates) { ComparisonPredicate predicate = (ComparisonPredicate)value; if (predicate.PredicateType.Equals(PredicateType.Constant)) { //When any constant expression is false in an AND Expression it will be resulting into 0 rowIds. if (!predicate.IsTrue(null)) { return(new ProxyPredicate(new EmptyPredicate(), predicate)); } } else if (predicate.PredicateType.Equals(PredicateType.SingleVariable)) { singleSet.AddTreePredicate(predicate); } else if (predicate.PredicateType.Equals(PredicateType.MultiVariable)) { sets.Add(predicate); } else if (predicate.PredicateType.Equals(PredicateType.AllVariable)) { proxyPredicate.AddChildPredicate( predicate.GetProxyExecutionPredicate(indexManager, queryStore, rowsEnumerator)); } } if (singleSet.TreePredicates.Count > 0) { sets.Add(singleSet); } foreach (var set in sets) { if (set is ITreePredicate) { proxyPredicate.AddChildPredicate( GetMultiAttributePredicate((ComparisonPredicate)set, indexes.Values, queryStore)); } else if (set is ProxyAndPredicate) { var singleAttributeSet = (ProxyAndPredicate)set; ReduceRecuringRanges(ref singleAttributeSet); List <ProxyAndPredicate> proxyAnds = AssignCompoundIndices(singleAttributeSet, indexes.Values, queryStore); if (proxyAnds.Count == 0) { proxyAnds.Add(singleAttributeSet); } foreach (var proxyAnd in proxyAnds) { if (proxyAnd.TreePredicates.Count == 0) { continue; } AssignSingleAttributesPredicate(proxyAnd, indexes.Values, queryStore); } if (proxyAnds.Count.Equals(1)) { foreach (var predicate in proxyAnds[0].Predicates) { proxyPredicate.AddChildPredicate(predicate); proxyPredicate.TreePredicates = _predciates; } } else { //Getting the ProxyANDPredicate with the lowest cost... OrderedList <double, ProxyAndPredicate> orderedPredicates = new OrderedList <double, ProxyAndPredicate>(); foreach (var proxyAnd in proxyAnds) { orderedPredicates.Add(proxyAnd.Statistics[Statistic.ExpectedIO], proxyAnd); } foreach (var predicate in orderedPredicates.FirstValues[0].Predicates) { proxyPredicate.AddChildPredicate(predicate); proxyPredicate.TreePredicates = _predciates; } proxyPredicate.TreePredicates = _predciates; } } } return(proxyPredicate); }