/// <summary> /// Checks whether the tree has B-Tree properties. /// </summary> /// <typeparam name="TNode">Type of the tree nodes stored in the tree. </typeparam> /// <typeparam name="TKey">Type of the keys stored in the tree. </typeparam> /// <typeparam name="TValue">Type of the values stored in the tree. </typeparam> /// <param name="tree">A B-Tree</param> /// <param name="expectedTotalKeyCount">The expected number of keys (duplicate and distinct) in the tree. </param> /// <param name="expectedDistinctKeyCount">The expected number of distinct keys in the tree. </param> /// <param name="expectedNodeCount">The expected number of tree nodes. </param> /// <param name="HasNodeProperties">The method used for checking properties. </param> /// <returns>True if the tree has the expected properties. </returns> public static bool HasBTreeProperties <TNode, TKey, TValue>(BTreeBase <TNode, TKey, TValue> tree, int expectedTotalKeyCount, int expectedDistinctKeyCount, int expectedNodeCount, Func <TNode, bool> HasNodeProperties) where TNode : IBTreeNode <TNode, TKey, TValue>, IComparable <TNode> where TKey : IComparable <TKey> { var nodes = new List <TNode>(); DFS <TNode, TKey, TValue>(tree.Root, nodes); Assert.AreEqual(expectedNodeCount, nodes.Count); int keyCount = 0; /* Checking whether all the nodes are proper BTree nodes. */ foreach (TNode node in nodes) { Assert.IsTrue(HasNodeProperties(node)); keyCount += node.KeyCount; } /* Check that key count matches the expected key count. */ Assert.AreEqual(expectedTotalKeyCount, keyCount); /* Get the sorted key list and make sure it is sorted. */ if (tree.Root != null) { List <KeyValuePair <TKey, TValue> > sortedKeys = tree.GetSortedKeyValues(tree.Root); Assert.AreEqual(expectedDistinctKeyCount, sortedKeys.Count); for (int i = 0; i < sortedKeys.Count - 1; i++) { Assert.IsTrue(sortedKeys[i].Key.CompareTo(sortedKeys[i + 1].Key) < 0); } } return(true); }
static IEnumerable <Key> Equal <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { SessionBase session = sourceCollection.Session; CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; Expression leftSide = binExp.Left; Expression rightSide = binExp.Right; object rightValue = GetRightValue(leftSide, rightSide); if (leftSide.NodeType == ExpressionType.Parameter) { Key key = (Key)rightValue; if (key != null) { BTreeSetIterator <Key> itr = sourceCollection.Iterator(); itr.GoTo(key); while (sourceCollection.Comparer.Compare(itr.Current(), key) == 0) { yield return(itr.Next()); } } } else { if (comparer != null) { MemberExpression returnedEx = null; #if WINDOWS_PHONE || WINDOWS_UWP Key key = (Key)Activator.CreateInstance(typeof(Key)); #else Key key = (Key)FormatterServices.GetUninitializedObject(typeof(Key)); #endif if (comparer.FieldsToCompare == null) { comparer.SetupFieldsToCompare(); } DataMember dataMember = comparer.FieldsToCompare[0]; if (rightValue != null && HasIndexablePropertyOnLeft <Key>(leftSide, sourceCollection, dataMember, out returnedEx)) { MemberExpression propExp = (MemberExpression)returnedEx; MemberInfo property = propExp.Member; dataMember.SetMemberValueWithPossibleConvert(key, rightValue); BTreeSetIterator <Key> itr = sourceCollection.Iterator(); itr.GoTo(key); Key current = itr.Current(); while (current != null && comparer.CompareField(dataMember, key, current, 0) == 0) { yield return(current); current = itr.Next(); } } } } }
static bool GreaterThanOrEqualUseIndex <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { SessionBase session = sourceCollection.Session; CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; Expression leftSide = binExp.Left; Expression rightSide = binExp.Right; object rightValue = GetRightValue(leftSide, rightSide); if (leftSide.NodeType == ExpressionType.Parameter) { Key key = (Key)rightValue; if (key != null) { if (session.TraceIndexUsage) { Trace.WriteLine(DateTime.Now.ToString("HH:mm:ss:fff") + " Index used with " + sourceCollection.ToString()); } return(true); } } else { if (comparer != null) { //if we were able to create a hash from the right side (likely) MemberExpression returnedEx = null; if (comparer.FieldsToCompare == null) { comparer.SetupFieldsToCompare(); } DataMember dataMember = comparer.FieldsToCompare[0]; if (rightValue != null && HasIndexablePropertyOnLeft <Key>(leftSide, sourceCollection, dataMember, out returnedEx)) { if (session.TraceIndexUsage) { Trace.WriteLine(DateTime.Now.ToString("HH:mm:ss:fff") + " Index used with " + sourceCollection.ToString()); } return(true); } else if (leftSide.NodeType == ExpressionType.Call) { // don't know yet how to handle TODO /*MethodCallExpression expression = leftSide as MethodCallExpression; * Trace.Out.WriteLine("Method: " + expression.Method.Name); * Trace.Out.WriteLine("Args: "); * foreach (var exp in expression.Arguments) * sourceCollection where */ } } } return(false); }
static bool GreaterThanUseIndex <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { SessionBase session = sourceCollection.GetSession(); CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; Expression leftSide = binExp.Left; Expression rightSide = binExp.Right; object rightValue = GetRightValue(leftSide, rightSide); if (leftSide.NodeType == ExpressionType.Parameter) { Key key = (Key)rightValue; if (key != null) { if (session.TraceIndexUsage) { Trace.WriteLine(DateTime.Now.ToString("HH:mm:ss:fff") + " Index used with " + sourceCollection.ToString()); } return(true); } } else { if (comparer != null) { //if we were able to create a hash from the right side (likely) MemberExpression returnedEx = null; if (comparer.FieldsToCompare == null) { comparer.SetupFieldsToCompare(); } DataMember dataMember = comparer.FieldsToCompare[0]; if (rightValue != null && HasIndexablePropertyOnLeft <Key>(leftSide, sourceCollection, dataMember, out returnedEx)) { if (session.TraceIndexUsage) { Trace.WriteLine(DateTime.Now.ToString("HH:mm:ss:fff") + " Index used with " + sourceCollection.ToString()); } return(true); } } } return(false); }
private static bool HasIndexablePropertyOnLeft <Key>(Expression leftSide, BTreeBase <Key, Key> sourceCollection, DataMember dataMember, out MemberExpression theMember) #if WINDOWS_PHONE where Key : new() #endif { theMember = null; MemberExpression mex = leftSide as MemberExpression; if (leftSide.NodeType == ExpressionType.Convert) { UnaryExpression convert = leftSide as UnaryExpression; mex = convert.Operand as MemberExpression; } if (leftSide.NodeType == ExpressionType.Call) { MethodCallExpression call = leftSide as MethodCallExpression; if (call.Method.Name == "CompareString") { mex = call.Arguments[0] as MemberExpression; } } else if (mex == null) { return(false); } else { theMember = mex; if (dataMember.Field.Name == mex.Member.Name) { return(true); } FieldAccessor accessor = CustomAttributeExtensions.GetCustomAttribute <FieldAccessor>(theMember.Member, true); if (accessor != null) { return(dataMember.Field.Name == accessor.FieldName); } } return(false); }
static bool AndUseIndex <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { while (binExp.NodeType == ExpressionType.AndAlso) { BinaryExpression leftExpr = (BinaryExpression)binExp.Left; binExp = leftExpr; if (binExp.NodeType != ExpressionType.Equal && binExp.NodeType != ExpressionType.AndAlso) { return(false); } } SessionBase session = sourceCollection.Session; if (session.TraceIndexUsage) { Trace.WriteLine(DateTime.Now.ToString("HH:mm:ss:fff") + " Index used with " + sourceCollection.ToString()); } return(true); }
static IEnumerable <Key> And <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; int indexNumberOfFields = comparer.FieldsToCompare.Length; #if WINDOWS_PHONE || WINDOWS_UWP Key key = (Key)Activator.CreateInstance(typeof(Key)); #else Key key = (Key)FormatterServices.GetUninitializedObject(typeof(Key)); #endif while (binExp.NodeType == ExpressionType.AndAlso) { BinaryExpression leftExpr = (BinaryExpression)binExp.Left; BinaryExpression rightExpr = (BinaryExpression)binExp.Right; DataMember dataMember = comparer.FieldsToCompare[--indexNumberOfFields]; object rightValue = GetRightValue(rightExpr.Left, rightExpr.Right); dataMember.SetMemberValueWithPossibleConvert(key, rightValue); binExp = leftExpr; if (binExp.NodeType == ExpressionType.Equal) { dataMember = comparer.FieldsToCompare[--indexNumberOfFields]; rightValue = GetRightValue(binExp.Left, binExp.Right); dataMember.SetMemberValueWithPossibleConvert(key, rightValue); } } BTreeSetIterator <Key> itr = sourceCollection.Iterator(); itr.GoTo(key); Key current = itr.Current(); while (current != null && comparer.Compare(key, current) == 0) { yield return(current); current = itr.Next(); } }
static bool canUseIndex <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp, CompareByField <Key> comparer) #if WINDOWS_PHONE where Key : new() #endif { if (comparer.FieldsToCompare == null) { comparer.SetupFieldsToCompare(); } int indexNumberOfFields = comparer.FieldsToCompare.Length; while (binExp.NodeType == ExpressionType.AndAlso) { BinaryExpression leftExpr = (BinaryExpression)binExp.Left; BinaryExpression rightExpr = (BinaryExpression)binExp.Right; MemberExpression returnedEx = null; if (indexNumberOfFields == 0 || !HasIndexablePropertyOnLeft(rightExpr.Left, sourceCollection, comparer.FieldsToCompare[--indexNumberOfFields], out returnedEx)) { return(false); } binExp = leftExpr; } return(true); }
static public IEnumerable <Key> Where <Key>(this BTreeBase <Key, Key> sourceCollection, Expression <Func <Key, bool> > expr) #if WINDOWS_PHONE where Key : new() #endif { if (sourceCollection != null) { bool noIndex = true; SessionBase session = sourceCollection.Session; CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; BinaryExpression binExp = expr.Body as BinaryExpression; if (binExp != null && canUseIndex <Key>(sourceCollection, binExp, comparer)) { session.WaitForIndexUpdates(); switch (expr.Body.NodeType) { case ExpressionType.AndAlso: { noIndex = AndUseIndex(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in And <Key>(sourceCollection, binExp)) { yield return(x); } } else { BinaryExpression leftExpr = (BinaryExpression)binExp.Left; binExp = leftExpr; switch (binExp.NodeType) { case ExpressionType.Equal: { noIndex = EqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { IEnumerable <Key> equal = Equal <Key>(sourceCollection, binExp); IEnumerable <Key> result = equal.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } yield break; } case ExpressionType.LessThan: { noIndex = LessThanUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { IEnumerable <Key> lessThan = LessThan <Key>(sourceCollection, binExp); IEnumerable <Key> result = lessThan.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } yield break; } case ExpressionType.LessThanOrEqual: { noIndex = LessThanOrEqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { IEnumerable <Key> lessThan = LessThanOrEqual <Key>(sourceCollection, binExp); IEnumerable <Key> result = lessThan.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } yield break; } case ExpressionType.GreaterThan: { noIndex = GreaterThanUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { IEnumerable <Key> greaterThan = GreaterThan <Key>(sourceCollection, binExp); IEnumerable <Key> result = greaterThan.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } yield break; } case ExpressionType.GreaterThanOrEqual: { noIndex = GreaterThanOrEqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { IEnumerable <Key> greaterThan = GreaterThanOrEqual <Key>(sourceCollection, binExp); IEnumerable <Key> result = greaterThan.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } yield break; } } ; } } break; case ExpressionType.Equal: { noIndex = EqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in Equal <Key>(sourceCollection, binExp)) { yield return(x); } } } break; case ExpressionType.GreaterThan: { noIndex = GreaterThanUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in GreaterThan <Key>(sourceCollection, binExp)) { yield return(x); } } } break; case ExpressionType.GreaterThanOrEqual: { noIndex = GreaterThanOrEqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in GreaterThanOrEqual <Key>(sourceCollection, binExp)) { yield return(x); } } } break; case ExpressionType.LessThan: { noIndex = LessThanUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in LessThan <Key>(sourceCollection, binExp)) { yield return(x); } } } break; case ExpressionType.LessThanOrEqual: { noIndex = LessThanOrEqualUseIndex <Key>(sourceCollection, binExp) == false; if (noIndex == false) { foreach (var x in LessThanOrEqual <Key>(sourceCollection, binExp)) { yield return(x); } } } break; } } if (noIndex) //no index? just do it the normal slow way then... { IEnumerable <Key> sourceEnum; if (sourceCollection.UsesOidShort) { BTreeSetOidShort <Key> c = (BTreeSetOidShort <Key>)sourceCollection; sourceEnum = c.AsEnumerable <Key>(); } else { BTreeSet <Key> c = (BTreeSet <Key>)sourceCollection; sourceEnum = c.AsEnumerable <Key>(); } IEnumerable <Key> result = sourceEnum.Where <Key>(expr.Compile()); foreach (Key resultItem in result) { yield return(resultItem); } } } }
static IEnumerable <Key> LessThan <Key>(BTreeBase <Key, Key> sourceCollection, BinaryExpression binExp) #if WINDOWS_PHONE where Key : new() #endif { SessionBase session = sourceCollection.Session; Expression leftSide = binExp.Left; Expression rightSide = binExp.Right; object rightValue = GetRightValue(leftSide, rightSide); CompareByField <Key> comparer = sourceCollection.Comparer as CompareByField <Key>; if (leftSide.NodeType == ExpressionType.Parameter) { Key key = (Key)rightValue; if (key != null) { BTreeSetIterator <Key> itr = sourceCollection.Iterator(); if (itr.GoTo(key)) { while (itr.Previous() != null) { yield return(itr.Current()); } } } } else { if (comparer != null) { //if we were able to create a hash from the right side (likely) MemberExpression returnedEx = null; #if WINDOWS_PHONE || WINDOWS_UWP Key key = (Key)Activator.CreateInstance(typeof(Key)); #else Key key = (Key)FormatterServices.GetUninitializedObject(typeof(Key)); #endif if (comparer.FieldsToCompare == null) { comparer.SetupFieldsToCompare(); } DataMember dataMember = comparer.FieldsToCompare[0]; if (rightValue != null && HasIndexablePropertyOnLeft <Key>(leftSide, sourceCollection, dataMember, out returnedEx)) { //cast to MemberExpression - it allows us to get the property MemberExpression propExp = (MemberExpression)returnedEx; MemberInfo property = propExp.Member; foreach (DataMember member in comparer.FieldsToCompare.Skip(1)) { if (member.GetTypeCode == TypeCode.String) { member.SetMemberValue(key, ""); } } dataMember.SetMemberValueWithPossibleConvert(key, rightValue); BTreeSetIterator <Key> itr = sourceCollection.Iterator(); itr.GoTo(key); var v = itr.Current(); if (v == null) { v = itr.Previous(); } while (v != null && comparer.CompareField(dataMember, key, v, 0) == 0) { v = itr.Previous(); } while (v != null) { yield return(v); v = itr.Previous(); } } else if (leftSide.NodeType == ExpressionType.Call) { // don't know yet how to handle TODO /*MethodCallExpression expression = leftSide as MethodCallExpression; * Trace.Out.WriteLine("Method: " + expression.Method.Name); * Trace.Out.WriteLine("Args: "); * foreach (var exp in expression.Arguments) * sourceCollection where */ } } } }
static public int Count <Key>(this BTreeBase <Key, Key> sourceCollection) { return(sourceCollection.Count); }
string DisplayData(bool useServerSession) { using (SessionBase session = useServerSession ? (SessionBase) new ServerClientSession(systemDir) : (SessionBase) new SessionNoServer(systemDir)) { StringBuilder sb = new StringBuilder(); session.BeginRead(); try { BTreeBase <RDerby1, RDerby1> index = null; try { session.Index <RDerby1>(); } catch (IndexDatabaseNotSpecifiedException) { UInt32 dbId = session.DatabaseNumberOf(typeof(RDerby1)); Database db = session.OpenDatabase(dbId); index = session.Index <RDerby1>(db); } // for testing //var index = session.Index<Test1_0_0Class>("name2"); // create variable so that can examine in Locals if (index != null) // should not be null? { // get all var testEntries = from t in index select t; int count = testEntries.ToList <RDerby1>().Count; int i = 0; sb.AppendLine("Session Details:"); sb.AppendLine(index.ToStringDetails(session)); sb.AppendLine("Results:"); foreach (RDerby1 test in testEntries) { try { string values = test.Name + ", " + test.Name2 + ", " + test.Added; sb.AppendLine(string.Format("{0, -5:00000}: {1}", i++, values)); } catch (Exception ex) { return("Exception thrown in for each loop: " + ex.Message); } } } else { return("Index was null"); // why is the index null? } } catch (Exception ex) { return("Exception occured prior to loop: " + ex.Message); // examine problem using breakpoint. } finally { session.Commit(); } return(sb.ToString()); } }