/// <summary> /// Creates a new index /// </summary> /// <param name="Storage"></param> /// <param name="Parent"></param> /// <param name="IndexColumns"></param> public TreeIndex(Table Storage, Table Parent, string Name, Key IndexColumns) { this._Header = new IndexHeader(Name, -1, -1, -1, 0, 0, IndexColumns); this._Storage = Storage; this._Parent = Parent; this._IndexColumns = IndexColumns; Schema s = BinaryRecordTree.NonClusteredIndexColumns(this._Parent.Columns, this._IndexColumns); //this._Tree = new Cluster(this._Storage, s, Key.Build(this._IndexColumns.Count), null, this._Header, ClusterState.Universal); this._Tree = new BinaryRecordTree(Storage, Key.Build(this._IndexColumns.Count), s, null, Header, BinaryRecordTree.TreeAffinity.Unconstrained); }
public static void Write(byte[] Buffer, int Location, IndexHeader Header) { Array.Copy(BitConverter.GetBytes(Header.Name.Length), 0, Buffer, Location + OFFSET_NAME, 4); Array.Copy(ASCIIEncoding.ASCII.GetBytes(Header.Name), 0, Buffer, Location + OFFSET_NAME + 4, Header.Name.Length); Array.Copy(BitConverter.GetBytes(Header.OriginPageID), 0, Buffer, Location + OFFSET_ORIGIN_PAGE_ID, 4); Array.Copy(BitConverter.GetBytes(Header.TerminalPageID), 0, Buffer, Location + OFFSET_TERMINAL_PAGE_ID, 4); Array.Copy(BitConverter.GetBytes(Header.RootPageID), 0, Buffer, Location + OFFSET_ROOT_PAGE_ID, 4); Array.Copy(BitConverter.GetBytes(Header.RecordCount), 0, Buffer, Location + OFFSET_RECORD_COUNT, 8); Array.Copy(BitConverter.GetBytes(Header.PageCount), 0, Buffer, Location + OFFSET_PAGE_COUNT, 4); Array.Copy(Header.IndexColumns.Bash(), 0, Buffer, Location + OFFSET_INDEX_COLUMNS, 4); }
/// <summary> /// Opens an existing index /// </summary> /// <param name="Storage"></param> /// <param name="Parent"></param> /// <param name="Header"></param> public TreeIndex(Table Storage, Table Parent, IndexHeader Header) { this._Storage = Storage; this._Parent = Parent; this._Header = Header; this._IndexColumns = Header.IndexColumns; Page root = this._Storage.GetPage(Header.RootPageID); Schema s = BinaryRecordTree.NonClusteredIndexColumns(this._Parent.Columns, Header.IndexColumns); this._Tree = new BinaryRecordTree(Storage, Key.Build(this._IndexColumns.Count), s, root, Header, BinaryRecordTree.TreeAffinity.Unconstrained); }
public static IndexHeader Read(byte[] Buffer, int Location) { IndexHeader h = new IndexHeader(); int len = BitConverter.ToInt32(Buffer, Location + OFFSET_NAME); h.Name = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_NAME + 4, len); h.OriginPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_ORIGIN_PAGE_ID); h.TerminalPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_TERMINAL_PAGE_ID); h.RootPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_ROOT_PAGE_ID); h.RecordCount = BitConverter.ToInt64(Buffer, Location + OFFSET_RECORD_COUNT); h.PageCount = BitConverter.ToInt32(Buffer, Location + OFFSET_PAGE_COUNT); h.IndexColumns = Key.Read(Buffer, Location + OFFSET_INDEX_COLUMNS); return(h); }
public RecordReaderIndexKey(IndexHeader Header, Table Storage) : this(Header, Storage, RecordReaderBase.OriginKey(Storage, Header), RecordReaderBase.TerminalKey(Storage, Header)) { }
public RecordReaderIndexKey(IndexHeader Header, Table Storage, RecordKey LKey, RecordKey RKey) : base(Storage, LKey, RKey) { this._Header = Header; }
/// <summary> /// Converts a TableHeader to a byte array /// </summary> /// <param name="Buffer"></param> /// <param name="Location"></param> /// <param name="Key"></param> public static void ToHash(byte[] Buffer, int Location, TableHeader Element) { // Check the size // if (Buffer.Length - Location < TableHeader.SIZE) { throw new Exception("Buffer is incorrect size"); } // Write the hash key // Array.Copy(BitConverter.GetBytes(HASH_KEY), 0, Buffer, Location + OFFSET_HASH_KEY, LEN_SIZE); // Write the name // Array.Copy(BitConverter.GetBytes(Element.Name.Length), 0, Buffer, Location + OFFSET_NAME_LEN, LEN_SIZE); Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Name), 0, Buffer, Location + OFFSET_NAME, Element.Name.Length); // Write the directory // Array.Copy(BitConverter.GetBytes(Element.Directory.Length), 0, Buffer, Location + OFFSET_DIR_LEN, LEN_SIZE); Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Directory), 0, Buffer, Location + OFFSET_DIR, Element.Directory.Length); // Write the extension // Array.Copy(BitConverter.GetBytes(Element.Extension.Length), 0, Buffer, Location + OFFSET_EXT_LEN, LEN_SIZE); Array.Copy(ASCIIEncoding.ASCII.GetBytes(Element.Extension), 0, Buffer, Location + OFFSET_EXT, Element.Extension.Length); // Write page count // Array.Copy(BitConverter.GetBytes(Element.PageCount), 0, Buffer, Location + OFFSET_PAGE_COUNT, LEN_SIZE); // Write record count // Array.Copy(BitConverter.GetBytes(Element.RecordCount), 0, Buffer, Location + OFFSET_RECORD_COUNT, 8); // Long integer // Write column count // Array.Copy(BitConverter.GetBytes(Element.Columns.Count), 0, Buffer, Location + OFFSET_COLUMN_COUNT, LEN_SIZE); // Write first page ID // Array.Copy(BitConverter.GetBytes(Element.OriginPageID), 0, Buffer, Location + OFFSET_FIRST_PAGE_ID, LEN_SIZE); // Write last page ID // Array.Copy(BitConverter.GetBytes(Element.TerminalPageID), 0, Buffer, Location + OFFSET_LAST_PAGE_ID, LEN_SIZE); // Write page size // Array.Copy(BitConverter.GetBytes(Element.PageSize), 0, Buffer, Location + OFFSET_PAGE_SIZE, LEN_SIZE); // Write radix page // Array.Copy(BitConverter.GetBytes(Element.RootPageID), 0, Buffer, Location + OFFSET_ROOT_PAGE_ID, LEN_SIZE); // Write key // Buffer[Location + OFFSET_SORT_KEY] = (byte)Element.ClusterKeyState; byte[] b = Element.ClusterKey.Bash(); Array.Copy(b, 0, Buffer, Location + OFFSET_SORT_KEY + 4, b.Length); // Write the index table // Array.Copy(BitConverter.GetBytes(Element.IndexHeaders.Count), 0, Buffer, Location + OFFSET_INDEX_COUNT, LEN_SIZE); for (int i = 0; i < Element.IndexHeaders.Count; i++) { int pos = Location + OFFSET_INDEX_TABLE + i * IndexHeader.SIZE_HASH; IndexHeader.Write(Buffer, pos, Element.IndexHeaders[i]); } // Write schema // for (int i = 0; i < Element.Columns.Count; i++) { Cell c = new Cell((short)(Element.Columns.ColumnSize(i) * (Element.Columns.ColumnNull(i) ? 1 : -1))); byte NameLen = (byte)Element.Columns.ColumnName(i).Length; byte Affinity = (byte)Element.Columns.ColumnAffinity(i); byte Size1 = c.B0; byte Size2 = c.B1; byte[] Name = ASCIIEncoding.ASCII.GetBytes(Element.Columns.ColumnName(i)); int ptr = Location + OFFSET_COLUMNS + i * COL_REC_LEN; Buffer[ptr + COL_NAME_LEN_PTR] = NameLen; Buffer[ptr + COL_AFFINITY] = Affinity; Buffer[ptr + COL_SIZE] = Size1; Buffer[ptr + COL_SIZE + 1] = Size2; //Buffer[ptr + COL_NULL] = Nullness; Array.Copy(Name, 0, Buffer, ptr + COL_NAME_PTR, Name.Length); } }
// Static Methods // /// <summary> /// Converts a byte array to a TableHeader /// </summary> /// <param name="Buffer"></param> /// <param name="Location"></param> /// <returns></returns> public static TableHeader FromHash(byte[] Buffer, int Location) { // Check the size // if (Buffer.Length - Location < TableHeader.SIZE) { throw new Exception("Buffer is incorrect size"); } // Check the hash key // if (BitConverter.ToInt32(Buffer, Location + OFFSET_HASH_KEY) != HASH_KEY) { throw new Exception("Invalid hash key"); } // Create // TableHeader h = new TableHeader(); int Len = 0; // Alias // Len = BitConverter.ToInt32(Buffer, Location + OFFSET_NAME_LEN); h.Name = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_NAME, Len); // Directory // Len = BitConverter.ToInt32(Buffer, Location + OFFSET_DIR_LEN); h.Directory = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_DIR, Len); // Extension // Len = BitConverter.ToInt32(Buffer, Location + OFFSET_EXT_LEN); h.Extension = ASCIIEncoding.ASCII.GetString(Buffer, Location + OFFSET_EXT, Len); // Page count // h.PageCount = BitConverter.ToInt32(Buffer, Location + OFFSET_PAGE_COUNT); // Row count // h.RecordCount = BitConverter.ToInt64(Buffer, Location + OFFSET_RECORD_COUNT); // Column Count // int ColCount = BitConverter.ToInt32(Buffer, Location + OFFSET_COLUMN_COUNT); // First Page // h.OriginPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_FIRST_PAGE_ID); // Last Page // h.TerminalPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_LAST_PAGE_ID); // Page PageSize // h.PageSize = BitConverter.ToInt32(Buffer, Location + OFFSET_PAGE_SIZE); // Radix Page // h.RootPageID = BitConverter.ToInt32(Buffer, Location + OFFSET_ROOT_PAGE_ID); // Key // h.ClusterKey = new Key(); h.ClusterKeyState = (BinaryRecordTree.TreeAffinity)Buffer[Location + OFFSET_SORT_KEY]; // gets the unique int KeyCount = BitConverter.ToInt32(Buffer, Location + OFFSET_SORT_KEY + 4); // gets the key size for (int i = 0; i < KeyCount; i++) { int loc = Location + OFFSET_SORT_KEY + 8 + 8 * i; int idx = BitConverter.ToInt32(Buffer, loc); KeyAffinity affinity = (KeyAffinity)BitConverter.ToInt32(Buffer, loc + 4); h.ClusterKey.Add(idx, affinity); } // Read the index table // int idx_cnt = BitConverter.ToInt32(Buffer, Location + OFFSET_INDEX_COUNT); for (int i = 0; i < idx_cnt; i++) { int pos = Location + OFFSET_INDEX_TABLE + i * IndexHeader.SIZE_HASH; IndexHeader idx_h = IndexHeader.Read(Buffer, pos); h.IndexHeaders.Add(idx_h); } // Load the columns // h.Columns = new Schema(); for (int i = 0; i < ColCount; i++) { int RecordOffset = Location + OFFSET_COLUMNS + i * COL_REC_LEN; int NameLen = (int)Buffer[RecordOffset]; string ColName = ASCIIEncoding.ASCII.GetString(Buffer, RecordOffset + COL_NAME_PTR, NameLen); CellAffinity ColType = (CellAffinity)Buffer[RecordOffset + COL_AFFINITY]; int ColSize = (int)(BitConverter.ToInt16(Buffer, RecordOffset + COL_SIZE)); bool ColNull = true; if (ColSize < 0) { ColSize = -ColSize; ColNull = false; } h.Columns.Add(ColName, ColType, ColSize, ColNull); } return(h); }
/// <summary> /// Opens an indexed reader /// </summary> /// <param name="Header">The index header</param> /// <param name="Storage">The table that stores the index pages</param> /// <param name="Parent">The table that stores the data pages; may be the same object as 'Storage'</param> public RecordReaderIndexData(IndexHeader Header, Table Storage, Table Parent) : this(Header, Storage, Parent, RecordReaderBase.OriginKey(Storage, Header), RecordReaderBase.TerminalKey(Storage, Header)) { }
/// <summary> /// Opens an indexed reader /// </summary> /// <param name="Header">The index header</param> /// <param name="Storage">The table that stores the index pages</param> /// <param name="Parent">The table that stores the data pages; may be the same object as 'Storage'</param> /// <param name="LKey">The lower bound key</param> /// <param name="RKey">The upper bound key</param> public RecordReaderIndexData(IndexHeader Header, Table Storage, Table Parent, RecordKey LKey, RecordKey RKey) : base(Storage, LKey, RKey) { this._Header = Header; this._Parent = Parent; }