// String and Binary handling. These are represented as a long, which is an offset into a file. public long EncodeString( string s ) { if ( s == "" ) return 0; // See if it is in SysStringIndex try { var start = new StringStart( s ); foreach( IndexFileRecord ixr in SysStringIndex.From( start.Compare, false ) ) { if ( (string)(ixr.Col[0]._O) == s ) return ixr.Col[0].L; break; } } catch ( System.Exception x ) { SysStringIndex.Dump(); throw x; } // Save to file. long sid = SysString.Length; SysString.Position = sid; SysStringWriter.Write( s ); // Insert into the index IndexFileRecord r = new IndexFileRecord( 1 ); r.Col[ 0 ].L = sid + 1; r.Col[ 0 ]._O = s; SysStringIndex.Insert( ref r ); return sid + 1; // + 1 because zero indicates the encoding has not yet been done. }
int Compare(ref IndexFileRecord r) // This make not be quite optimal for Less and Greater. { int cf = 0; if (Op <= Token.LessEqual) // Op == Token.Less || Op == Token.LessEqual { switch (Type) { case DataType.Binary: cf = Util.Compare((byte[])V._O, (byte[])r.Col[0]._O); if (cf == 0) { cf = +1; // Should be -1 if Op == Less ? } break; case DataType.String: cf = string.Compare((string)V._O, (string)r.Col[0]._O); if (cf == 0) { cf = +1; // Should be -1 if Op == Less ? } break; case DataType.Bigint: cf = V.L < r.Col[0].L ? -1 : +1; // Should be <= if Op == Less ? break; default: throw new System.Exception("Type error"); } } else // ( Op == Token.Greater || Op == Token.GreaterEqual || Op == Token.Equal ) { switch (Type) { case DataType.Binary: cf = Util.Compare((byte[])V._O, (byte[])r.Col[0]._O); if (cf == 0) { cf = -1; } break; case DataType.String: cf = string.Compare((string)V._O, (string)r.Col[0]._O); if (cf == 0) { cf = -1; } break; case DataType.Bigint: cf = V.L <= r.Col[0].L ? -1 : +1; break; default: throw new System.Exception("Type error"); } } return(cf); }
public IndexFileRecord Copy() { IndexFileRecord result = new IndexFileRecord( Col.Length ); result.Child = Child; for ( int i=0; i<Col.Length; i += 1 ) result.Col[i] = Col[i]; return result; }
protected virtual void SetRecord(int x, ref IndexFileRecord r) { int off = NodeOverhead + NodeBase + x * NodeSize; for (int i = 0; i < ColStore; i += 1) { long v = r.Col[i].L; DataType t = Inf.Types[i]; if (t == DataType.String && v == 0) { r.Col[i].L = Database.EncodeString((string)r.Col[i]._O); } else if (t == DataType.Binary && v == 0) { r.Col[i].L = Database.EncodeBinary((byte[])r.Col[i]._O); } int size = DTI.Size(t); ulong p = (ulong)r.Col[i].L; if (t == DataType.Float) { p = Conv.PackFloat(p); } Set(off, p, size); off += size; } }
void Divide(IndexPage L, IndexPage R, ref IndexFileRecord div) { var r = new IndexFileRecord(); int count = Count / 2; foreach (int x in Nodes(Root)) { GetRecord(x, ref r);; if (count > 0) { L.Insert(ref r, true); } else { if (count == 0) { div = r; if (IsLeafPage()) { R.Insert(ref div, true); } } else { R.Insert(ref r, true); } } count -= 1; } }
protected int FindSplit(DCompare compare) { int x = Root; int result = 0; IndexFileRecord r = new IndexFileRecord(); while (x != 0) { GetRecord(x, ref r); int c = compare(ref r); if (c < 0) { x = GetLeft(x); } else if (c > 0) { result = x; x = GetRight(x); } else // c == 0 { result = x; break; } } return(result); }
int Compare(int x, ref IndexFileRecord r) { IndexFileRecord y = new IndexFileRecord(); GetRecord(x, ref y); return(Compare(ref r, ref y)); }
int Compare(int x, DCompare seek) { IndexFileRecord r = new IndexFileRecord(); GetRecord(x, ref r); return(seek(ref r)); }
// Higher level operations ( indexes are updated as required ). public long Insert(Value [] row, int idCol) { long id; if (idCol < 0) // Id is not in INSERT list, allocate a new id. { id = ++RowCount; } else { id = row[idCol].L; if (RowCount < id) { RowCount = id; } } Save(id, row, idCol >= 0); // Update indexes. foreach (G.KeyValuePair <long, IndexFile> p in IxDict) { IndexFile ixf = p.Value; IndexFileRecord ixr = ixf.ExtractKey(row, id); ixf.Insert(ref ixr); } return(id); }
// Methods to Insert, Remove records, enumerate Node Ids. void Insert(ref IndexFileRecord r, bool append) // Insert IndexFileRecord into the tree ( set append true if Records are pre-sorted ) { bool h; Root = Insert(Root, ref r, out h, append); Saved = false; }
void Remove(ref IndexFileRecord r) { bool h; Root = Remove(Root, ref r, out h); Saved = false; }
protected int FindSplit(ref IndexFileRecord r) // Returns node id of the greatest IndexFileRecord less than or equal to v, or zero if no such node exists. { int x = Root; int result = 0; while (x != 0) { int c = Compare(x, ref r); if (c < 0) { x = GetLeft(x); } else if (c > 0) { result = x; x = GetRight(x); } else // c == 0 { result = x; break; } } return(result); }
public IndexFileRecord ExtractKey( Value[] x, long id ) { int n = Inf.BaseIx.Length; IndexFileRecord result = new IndexFileRecord( n + 1 ); for ( int i = 0; i < n; i += 1 ) result.Col[ i ] = x[ Inf.BaseIx[ i ] ]; result.Col[ n ].L = id; return result; }
public override void LeafOp(IndexFile ixf, ref IndexFileRecord r, bool insert) { int x = FindSplit(ref r); long childId = x == 0 ? FirstPage : GetChild(x); IndexPage cp = ixf.GetPage(childId); cp.ParentId = PageId; cp.LeafOp(ixf, ref r, insert); }
public virtual G.IEnumerable <IndexFileRecord> From(IndexFile ixf, DCompare seek, bool desc) { IndexFileRecord v = new IndexFileRecord(); foreach (int x in From(seek, desc)) { GetRecord(x, ref v); yield return(v); } }
public void Delete(long id, Value[] dr) { Save(id, null, false); // Update indexes. foreach (G.KeyValuePair <long, IndexFile> p in IxDict) { IndexFile ixf = p.Value; IndexFileRecord ixd = ixf.ExtractKey(dr, id); ixf.Delete(ref ixd); } }
public virtual void LeafOp(IndexFile ixf, ref IndexFileRecord r, bool insert) { if (insert) { Insert(ixf, ref r); } else { Remove(ref r); } }
public override void Dump(IndexFile ixf) // For debugging only { System.Console.WriteLine("Dump Parent Page, PageId=" + PageId + " First Page=" + FirstPage + " Count=" + Count + " NodeSize=" + NodeSize); ixf.GetPage(FirstPage).Dump(ixf); foreach (int x in Nodes(Root)) { IndexFileRecord v = new IndexFileRecord(); System.Console.WriteLine("Parent Node=" + x); GetRecord(x, ref v); System.Console.WriteLine("Parent Key=" + v.ToString(Inf)); ixf.GetPage(GetChild(x)).Dump(ixf); } System.Console.WriteLine("End Dump Parent Page, PageId=" + PageId + " First Page=" + FirstPage + " Count=" + Count); }
public virtual void Dump(IndexFile ixf) // For debugging. { System.Console.WriteLine("Page Dump PageId=" + PageId + " NodeSize=" + NodeSize + " MaxNode=" + MaxNode + " Count=" + Count + " Root=" + Root); CheckPage(); IndexFileRecord r = new IndexFileRecord(); foreach (int x in Nodes(Root)) { GetRecord(x, ref r); System.Console.WriteLine("Record=" + r.ToString(ixf.Inf) + " Node=" + x + " Left=" + GetLeft(x) + " Right=" + GetRight(x) + " Balance=" + GetBalance(x)); } System.Console.WriteLine("End Page Dump PageId=" + PageId + " NodeSize=" + NodeSize + " MaxNode=" + MaxNode + " Count=" + Count + " Root=" + Root); }
// Record comparison - determines the order in which the Records are stored. public int Compare(ref IndexFileRecord r, ref IndexFileRecord y) { int cf = 0; for (int i = 0; i < Inf.KeyCount; i += 1) { cf = Util.Compare(r.Col[i], y.Col[i], Inf.Types[i]); if (cf != 0) { break; } } return(cf); }
int Compare(ref IndexFileRecord r) // This make not be quite optimal for Less and Greater. { int cf = Util.Compare(V, r.Col[0], Type); if (cf == 0) { if (Op <= Token.LessEqual) // Op == Token.Less || Op == Token.LessEqual { cf = +1; // Should be -1 if Op == Less ? } else // ( Op == Token.Greater || Op == Token.GreaterEqual || Op == Token.Equal ) { cf = -1; } } return(cf); }
public bool Saved = false; // Indicates whether tree has been saved to disk. void Insert(IndexFile ixf, ref IndexFileRecord r) { if (Free == 0 && NodeAlloc == MaxNode) // Page is full, have to split it. { PageParent pp; if (this == ixf.Root) { pp = new PageParent(Inf, null, Database); ixf.AllocPageId(this); pp.FirstPage = PageId; ixf.Root = pp; ixf.PageMap[0] = pp; } else { pp = (PageParent)ixf.PageMap[ParentId]; } IndexPage left = Clone(); left.PageId = PageId; left.FirstPage = FirstPage; ixf.PageMap[PageId] = left; IndexPage right = Clone(); ixf.AllocPageId(right); var div = new IndexFileRecord(); // IndexFileRecord that divides page into left/right, will be inserted into parent page. Divide(left, right, ref div); right.FirstPage = div.Child; div.Child = right.PageId; pp.Insert(ixf, ref div); // Insert into either left or right depending on comparison with sv. (Compare(ref r, ref div) < 0 ? left : right).Insert(ref r, false); // Console.WriteLine( "Insert Split, NodeAlloc=" + NodeAlloc + " MaxNode=" + MaxNode + "ixf.PageAlloc=" + ixf.PageAlloc ); // Console.WriteLine( "Split div=" + div.ToString(ixf.Inf) ); // ixf.Dump(); } else { Insert(ref r, false); } }
protected virtual void GetRecord(int x, ref IndexFileRecord r) { if (r.Col == null) { r.Col = new Value[ColStore]; } int off = NodeOverhead + NodeBase + x * NodeSize; for (int i = 0; i < ColStore; i += 1) { DataType t = Inf.Types[i]; int size = DTI.Size(t); ulong u = Get(off, size); off += size; if (t == DataType.Float) { u = Conv.UnpackFloat((uint)u); } else if (t == DataType.Int) { u = (ulong)(long)(int)(uint)u; } else if (t == DataType.Smallint) { u = (ulong)(long)(short)(ushort)u; } else if (t == DataType.Tinyint) { u = (ulong)(long)(sbyte)(byte)u; } r.Col[i].L = (long)u; if (t == DataType.String) { r.Col[i]._O = Database.DecodeString((long)u); } else if (t == DataType.Binary) { r.Col[i]._O = Database.DecodeBinary((long)u); } } }
public void Update(long id, Value[] dr, Value [] nr) { Save(id, nr, false); // Update indexes. foreach (G.KeyValuePair <long, IndexFile> p in IxDict) { IndexFile ixf = p.Value; IndexFileRecord ixd = ixf.ExtractKey(dr, id); IndexFileRecord ixn = ixf.ExtractKey(nr, id); // Check if new and old keys are the same to save work. if (ixf.Root.Compare(ref ixd, ref ixn) != 0) { ixf.Delete(ref ixd); ixf.Insert(ref ixn); } } }
protected virtual void GetRecord(int x, ref IndexFileRecord r) { if (r.Col == null) { r.Col = new Value[ColStore]; } int off = NodeOverhead + NodeBase + x * NodeSize; for (int i = 0; i < ColStore; i += 1) { DataType t = Inf.Types[i]; int size = DTI.Size(t); long v = Util.Get(Data, off, size, t); off += size; r.Col[i].L = v; if (t <= DataType.String) { r.Col[i]._O = Database.Decode(v, t); } } }
// Functions related to Indexing. public void InitIndex(long indexId) // Called during CREATE INDEX to index existing rows. { IndexFile ixf = IxDict[indexId]; var rc = new RowCursor(this); int n = ixf.Inf.BaseIx.Length; IndexFileRecord ixr = new IndexFileRecord(n + 1); for (long id = 1; id <= RowCount; id += 1) { if (rc.Get(id)) { // Create the IndexFileRecord to be inserted. for (int i = 0; i < n; i += 1) { ixr.Col[i] = rc.V[ixf.Inf.BaseIx[i]]; } ixr.Col[n].L = id; // Append the id of the row. ixf.Insert(ref ixr); } } Dirty = true; }
public long EncodeBinary( byte [] data ) { if ( data.Length == 0 ) return 0; // See if it is in SysBinaryIndex var start = new BinaryStart( data ); foreach( IndexFileRecord ixr in SysBinaryIndex.From( start.Compare, false ) ) { if ( Util.Compare( (byte[])(ixr.Col[0]._O), data ) == 0 ) return ixr.Col[0].L; break; } // Save to file. long sid = SysBinary.Length; SysBinary.Position = sid; SysBinaryWriter.WriteBytes( data ); // Insert into the index IndexFileRecord r = new IndexFileRecord( 1 ); r.Col[ 0 ].L = sid + 1; r.Col[ 0 ]._O = data; SysBinaryIndex.Insert( ref r ); return sid + 1; // + 1 because zero means the encoding has not yet been done. }
protected virtual void SetRecord(int x, ref IndexFileRecord r) { int off = NodeOverhead + NodeBase + x * NodeSize; for (int i = 0; i < ColStore; i += 1) { DataType t = Inf.Types[i]; if (t <= DataType.String && r.Col[i].L == 0) { r.Col[i].L = Database.Encode(r.Col[i]._O, t); } int size = DTI.Size(t); long p = r.Col[i].L; if (t == DataType.Float) { p = Conv.PackFloat(p); } Set(off, (ulong)p, size); off += size; } }
public int Compare(ref IndexFileRecord r) { int cf = Util.Compare(K, (byte[])r.Col[0]._O); return(cf == 0 ? -1 : cf); }
public int Compare(ref IndexFileRecord r) { int cf = string.Compare(K, (string)r.Col[0]._O); return(cf == 0 ? -1 : cf); }