예제 #1
0
        //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();
            }
        }
예제 #2
0
        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}");
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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;
                    }
                }
            }
        }
예제 #5
0
        /// <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;
                }
            }
        }
예제 #6
0
        /// <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;
                }
            }
        }