//In-Order public override IEnumerator <PageIndexNodeBase <T> > GetEnumerator() { var stack = new Stack <PageIndexNodeBase <T> >(); //set current to root PageIndexNodeBase <T> current = this; while (stack.Count > 0 || current != null) { if (current != null) { stack.Push(current); //try to go Left if (current.Type == MetaIndexType.Items) { current = null; } else { current = ((PageIndexNode <T>)current).Left; } } else { current = stack.Pop(); //return yield return(current); //try to go Right if (current.Type == MetaIndexType.Items) { current = null; } else { current = ((PageIndexNode <T>)current).Right; } } var node = stack.Pop(); } }
public DbIndexTree(DbColumn index) { if ((Index = index) == null) { throw new ArgumentException($"Column indexer cannot be null or error"); } //load structure try { var pathTree = io.Path.Combine(Index.Table.Database.BinaryPath, $"{Index.Indexer}"); reader = new io.BinaryReader(io.File.OpenRead(pathTree)); var headerBuffer = new byte[PageIndexTreeHeader.Size]; // var read = reader.Read(headerBuffer, 0, headerBuffer.Length); Header = PageIndexTreeHeader.FromArray(headerBuffer); IsUnique = (Header.Flags & Consts.IndexHeaderIsUnique) != 0; IsKey = (Header.Flags & Consts.IndexHeaderIsKey) != 0; IsLeaf = (Header.Flags & Consts.IndexHeaderIsLeaf) != 0; byte keyTypeValue = (byte)Header.Flags; KeyType = (DbColumnType)keyTypeValue; //amount of tree node pages Index.NodePages = 0; if (!IsLeaf) { Root = ReadTreePageStructure(0); } } catch { throw new ArgumentException($"Error processing column indexer {Index.Table.Name}.{Index.Name}"); } }
/// <summary> /// Finds a key in the key tree of nodes /// </summary> /// <param name="key">key</param> /// <returns></returns> internal PageIndexNodeBase <T> FindKey(T key) { PageIndexNodeBase <T> root = Root; while (root != null) { switch (root.Type) { case MetaIndexType.Items: //if not inside items page, then not found return(root); case MetaIndexType.Node: // var nodePage = root as PageIndexNode <T>; //compare key to node:key var comp = key.CompareTo(nodePage.Key); if (comp < 0) { //go down to the left root = nodePage.Left; } else if (comp > 0) { //go down to the right root = nodePage.Right; } else { //it's the root key return(root); } break; } } return(null); }
internal IEnumerable <KeyValuePair <T, List <int> > > DumpTreeNodesInOrder(PageIndexNodeBase <T> root) { var stack = new Stack <PageIndexNodeBase <T> >(); PageIndexNode <T> nodePage = null; //set current to root PageIndexNodeBase <T> current = root; IEnumerable <KeyValuePair <T, List <int> > > EnumerateOffsets(PageIndexItems <T> page) { //find from dictionary for fast search var metaPage = Index.IndexItems <T>()[page.Offset]; if (metaPage != null) { foreach (var ofs in metaPage.Items) { yield return(ofs); } } else { yield break; } } while (stack.Count > 0 || current != null) { if (current != null) { //if it's a items page, return all it's values if (current.Type == MetaIndexType.Items) { //find items page by its offset foreach (var ofs in EnumerateOffsets(current as PageIndexItems <T>)) { yield return(ofs); } //signal end current = null; } else { //it's a node page, push current page stack.Push(current); //try to go Left current = ((PageIndexNode <T>)current).Left; } } else { current = stack.Pop(); //return current node page items --first-- if (current.Type == MetaIndexType.Items) { //find items page by its offset foreach (var ofs in EnumerateOffsets(current as PageIndexItems <T>)) { yield return(ofs); } //signal end current = null; } else { //it's a node page, return Key values, and try to go Right nodePage = current as PageIndexNode <T>; yield return(new KeyValuePair <T, List <int> >(nodePage.Key, nodePage.Values)); current = nodePage.Right; } } } }
/// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="token"></param> /// <returns></returns> internal IEnumerable <KeyValuePair <T, List <int> > > FindGreaterKey(T key, TokenType token) { PageIndexNodeBase <T> root = Root; var stack = new Stack <PageIndexNodeBase <T> >(); var preComp = -1; while (root != null) { switch (root.Type) { case MetaIndexType.Items: //push root and finish stack.Push(root); //stop here root = null; break; case MetaIndexType.Node: var nodePage = root as PageIndexNode <T>; //compare key to node:key var comp = key.CompareTo(nodePage.Key); if (comp > 0) { root = nodePage.Right; } else { //save root stack.Push(root); if (comp < 0) { //continue probe on left node root = nodePage.Left; // ((PageIndexNode<T>)prevRoot).Left; // } //if pre Cmp >= 0 && comp <= 0 STOP if (preComp >= 0 && comp <= 0) { //root = null; } } preComp = comp; break; } } while (stack.Count > 0) { root = stack.Pop(); switch (root.Type) { case MetaIndexType.Items: var itemsPage = root as PageIndexItems <T>; foreach (var ofs in Index.IndexItems <T>() .FindByOper(itemsPage.Offset, key, token)) //TokenType.Greater or TokenType.GreaterOrEqual { yield return(ofs); } break; case MetaIndexType.Node: //output root var nodePage = root as PageIndexNode <T>; //return root values yield return(new KeyValuePair <T, List <int> >(nodePage.Key, nodePage.Values)); //return all right nodes -in-order foreach (var ofs in DumpTreeNodesInOrder(nodePage.Right)) { yield return(ofs); } break; } } }
/// <summary> /// Performs Less & LessThan comparisons /// </summary> /// <param name="key"></param> /// <param name="token"></param> /// <returns></returns> internal IEnumerable <KeyValuePair <T, List <int> > > FindLessKey(T key, TokenType token) { PageIndexNodeBase <T> root = Root; while (root != null) { switch (root.Type) { case MetaIndexType.Items: var itemsPage = root as PageIndexItems <T>; foreach (var ofs in Index.IndexItems <T>() .FindByOper(itemsPage.Offset, key, token)) //TokenType.Less or TokenType.LessOrEqual { yield return(ofs); } //stop here root = null; break; case MetaIndexType.Node: var nodePage = root as PageIndexNode <T>; //compare key to node:key var comp = key.CompareTo(nodePage.Key); if (comp < 0) { //go down to the left root = nodePage.Left; } else { //key's greater or equal than node key //return all left nodes -in-order foreach (var ofs in DumpTreeNodesInOrder(nodePage.Left)) { yield return(ofs); } //if TokenType.LessOrEqual always return, otherwise only if Token.Less and comp > 0 if (token == TokenType.LessOrEqual || (token == TokenType.Less && comp > 0)) { //return root values yield return(new KeyValuePair <T, List <int> >(key, nodePage.Values)); } if (comp > 0) { //continue probing right node root = nodePage.Right; } else { //stop here root = null; } } break; } } }