static void TestLeafTableCell() { // init record DBRecord record = GetTestBRecord(); // init key List <AtomValue> keyValues = new List <AtomValue>(); AtomValue key = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 8, StringValue = "114514" }; keyValues.Add(key); DBRecord keyRecord = new DBRecord(keyValues); // make raw bytes List <byte> rawNode = new List <byte>(); rawNode.AddRange(new byte[30]); // build cell LeafTableCell leafTableCell = new LeafTableCell(keyRecord, record); byte[] raw = leafTableCell.Pack(); rawNode.AddRange(raw); // clone LeafTableCell leafTableCellClone = new LeafTableCell(rawNode.ToArray(), 30); // assert AssertDBRecords(leafTableCell.DBRecord, leafTableCellClone.DBRecord); AssertCell(leafTableCell, leafTableCellClone); }
/// <summary> /// Insert a row/record/cell. /// </summary> /// <param name="root">the root of the B+ tree.</param> /// <param name="key">primary key in table tree and indexed column in index tree.</param> /// <param name="dBRecord">new row of values to insert.</param> /// <returns>new root node of the B+ tree</returns> public BTreeNode InsertCell(BTreeNode root, DBRecord key, DBRecord dBRecord) { // create a new tree if (root == null) { BTreeNode newRootFromNull = GetNewNode(PageTypes.LeafTablePage); LeafTableCell newCell = new LeafTableCell(key, dBRecord); newRootFromNull.InsertBTreeCell(newCell); return(newRootFromNull); } // no need to split if (root.NumCells < MaxCell) { InsertNonFull(root, key, dBRecord); return(root); } // need to split, and return with a new root BTreeNode newRoot = GetNewNode(PageTypes.InternalTablePage); root.ParentPage = (uint)newRoot.RawPage.PageNumber; SplitNode(root, newRoot, key); InsertNonFull(newRoot, key, dBRecord); return(newRoot); }
/// <summary> /// <para>Insert cell into a non-full node `node` if `node` is a leaf node.</para> /// <para>If `node` is not the leaf node, the child node of `node` might need to split before recursively performing this function to the child node.</para> /// <para>`node` should be ensured to be not full.</para> /// </summary> /// <param name="node">node being inserted</param> /// <param name="newKey">new key value</param> /// <param name="dBRecord">new row/record</param> /// <returns>new root node</returns> private BTreeNode InsertNonFull(BTreeNode node, DBRecord newKey, DBRecord dBRecord) { // the actual insertion performs in leaf node if (node.PageType == PageTypes.LeafTablePage) { BTreeCell check_repeat; (check_repeat, _, _) = node.FindBTreeCell(newKey, false); if (check_repeat != null) { throw new RepeatedKeyException($"The primary key to be inserted ({newKey.GetValues()[0]}) is repeated!"); } LeafTableCell newCell = new LeafTableCell(newKey, dBRecord); node.InsertBTreeCell(newCell); return(node); } // find the child node to try to insert BTreeNode child; BTreeCell cell; UInt16 offset; (cell, offset, _) = node.FindBTreeCell(newKey); MemoryPage nextpage; if (offset == 0) // rightest page { nextpage = _pager.ReadPage((int)node.RightPage); child = new BTreeNode(nextpage); } else { InternalTableCell internalTableCell = (InternalTableCell)cell; nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); child = new BTreeNode(nextpage); } // child needs to split if (child.NumCells >= MaxCell) { SplitNode(child, node, newKey); return(InsertNonFull(node, newKey, dBRecord)); } return(InsertNonFull(child, newKey, dBRecord)); }
// `keyName` := primary key in table tree; indexed value in index tree public List <BTreeCell> FindCells(BTreeNode root, Expression condition, string keyName, List <AttributeDeclaration> attributeDeclarations) { if (condition == null) { return(LinearSearch(root, condition, attributeDeclarations)); } else if (condition.SimpleMinterms.ContainsKey(keyName)) { List <BTreeCell> result = new List <BTreeCell>(); List <AtomValue> values = new List <AtomValue>(); BTreeNode startNode; BTreeCell cell; int startIndexOfCellInStartNode; AtomValue bound = condition.SimpleMinterms[keyName].RightOperand.ConcreteValue; values.Add(bound); DBRecord keyFind = new DBRecord(values); switch (condition.SimpleMinterms[keyName].Operator) { case Operator.NotEqual: return(LinearSearch(root, condition, attributeDeclarations)); case Operator.Equal: LeafTableCell tmpCell = (LeafTableCell)FindCell(keyFind, root); if (tmpCell == null) { break; } else if (condition.Calculate(attributeDeclarations, tmpCell.DBRecord.GetValues()).BooleanValue == true) { result.Add(tmpCell); } break; case Operator.LessThan: startNode = FindMin(root); return(FindCells(startNode, condition, attributeDeclarations, bound, false)); case Operator.LessThanOrEqualTo: startNode = FindMin(root); return(FindCells(startNode, condition, attributeDeclarations, bound, true)); case Operator.MoreThan: startNode = FindNode(keyFind, root, true); // nothing is equal or more than the value of `keyFind` in the tree if (startNode == null) { return(result); } (cell, _, startIndexOfCellInStartNode) = startNode.FindBTreeCell(keyFind); // 2 possible situations for `cell == null`: // 1: The `keyFind` is bigger than all the key in `startNode` // 2: The `keyFind` is just between the bigest one in `startNode` and the smallest one in next node if (cell == null) { if (startNode.RightPage == 0) { return(result); } else { startIndexOfCellInStartNode = 0; MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); startNode = new BTreeNode(nextpage); } } return(FindCells(startNode, startIndexOfCellInStartNode, condition, attributeDeclarations, false)); case Operator.MoreThanOrEqualTo: startNode = FindNode(keyFind, root, true); // nothing is equal or more than the value of `keyFind` in the tree if (startNode == null) { return(result); } (cell, _, startIndexOfCellInStartNode) = startNode.FindBTreeCell(keyFind); if (cell == null) { if (startNode.RightPage == 0) { return(result); } else { startIndexOfCellInStartNode = 0; MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); startNode = new BTreeNode(nextpage); } } return(FindCells(startNode, startIndexOfCellInStartNode, condition, attributeDeclarations, true)); default: throw new Exception("The Operand is not supported!"); } //This step may not need? return(result); } else { return(LinearSearch(root, condition, attributeDeclarations)); } }
static void TestBTreeInsert() { LeafTableCell result = null; // init record DBRecord record_0 = GetTestBRecord(100); DBRecord record_1 = GetTestBRecord(101); DBRecord record_2 = GetTestBRecord(102); DBRecord record_3 = GetTestBRecord(103); DBRecord record_4 = GetTestBRecord(104); DBRecord record_5 = GetTestBRecord(105); DBRecord record_6 = GetTestBRecord(106); DBRecord record_7 = GetTestBRecord(107); DBRecord keyRecord_0 = GetTestBRecord(1); DBRecord keyRecord_1 = GetTestBRecord(2); DBRecord keyRecord_2 = GetTestBRecord(3); DBRecord keyRecord_3 = GetTestBRecord(4); DBRecord keyRecord_4 = GetTestBRecord(5); DBRecord keyRecord_5 = GetTestBRecord(6); DBRecord keyRecord_6 = GetTestBRecord(7); // init key string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList); BTreeNode root = null; root = controller.InsertCell(root, keyRecord_0, record_0); result = (LeafTableCell)controller.FindCell(keyRecord_0, root); Assert.NotNull(result); Assert.Equal(1, result.Key.GetValues()[0].IntegerValue); //1 root = controller.InsertCell(root, keyRecord_1, record_1); result = (LeafTableCell)controller.FindCell(keyRecord_1, root); Assert.NotNull(result); Assert.Equal(2, result.Key.GetValues()[0].IntegerValue); //2 root = controller.InsertCell(root, keyRecord_2, record_2); result = (LeafTableCell)controller.FindCell(keyRecord_2, root); Assert.NotNull(result); Assert.Equal(3, result.Key.GetValues()[0].IntegerValue); //3 root = controller.InsertCell(root, keyRecord_3, record_3); result = (LeafTableCell)controller.FindCell(keyRecord_3, root); Assert.NotNull(result); Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); //4 root = controller.InsertCell(root, keyRecord_4, record_4); result = (LeafTableCell)controller.FindCell(keyRecord_4, root); Assert.NotNull(result); Assert.Equal(5, result.Key.GetValues()[0].IntegerValue); //5 root = controller.InsertCell(root, keyRecord_5, record_5); result = (LeafTableCell)controller.FindCell(keyRecord_5, root); Assert.NotNull(result); Assert.Equal(6, result.Key.GetValues()[0].IntegerValue); //6 root = controller.InsertCell(root, keyRecord_6, record_6); result = (LeafTableCell)controller.FindCell(keyRecord_6, root); Assert.NotNull(result); Assert.Equal(7, result.Key.GetValues()[0].IntegerValue); //Find result = (LeafTableCell)controller.FindCell(keyRecord_0, root); Assert.NotNull(result); Assert.Equal(1, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_1, root); Assert.NotNull(result); Assert.Equal(2, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_2, root); Assert.NotNull(result); Assert.Equal(3, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_3, root); Assert.NotNull(result); Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_4, root); Assert.NotNull(result); Assert.Equal(5, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_5, root); Assert.NotNull(result); Assert.Equal(6, result.Key.GetValues()[0].IntegerValue); result = (LeafTableCell)controller.FindCell(keyRecord_6, root); Assert.NotNull(result); Assert.Equal(7, result.Key.GetValues()[0].IntegerValue); pager.Close(); }
static void HardTestForBTree() { string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList, 4); BTreeNode root = null; LeafTableCell result = null; //Construct BTree for (int i = 1; i < 20; i++) { DBRecord record = GetTestBRecord(i + 100); DBRecord keyRecord = GetTestBRecord(i); root = controller.InsertCell(root, keyRecord, record); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); } // test inserting records with repeated primary keys DBRecord record_D = GetTestBRecord(103); DBRecord keyRecord_D = GetTestBRecord(3); bool isError = false; try { root = controller.InsertCell(root, keyRecord_D, record_D); } catch (RepeatedKeyException) { isError = true; } Assert.True(isError); isError = false; record_D = GetTestBRecord(105); keyRecord_D = GetTestBRecord(5); try { root = controller.InsertCell(root, keyRecord_D, record_D); } catch (RepeatedKeyException) { isError = true; } BTreeNodeHelper.VisualizeIntegerTree(pager, root); //find all for (int i = 1; i < 20; i++) { DBRecord keyRecord = GetTestBRecord(i); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); } //delete for (int i = 10; i < 20; i++) { DBRecord keyRecord = GetTestBRecord(i); root = controller.Delete(keyRecord, root); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.Null(result); for (int m = 1; m < 10; m++) { DBRecord keyRecord_check = GetTestBRecord(m); result = (LeafTableCell)controller.FindCell(keyRecord_check, root); Assert.NotNull(result); Assert.Equal(m, result.Key.GetValues()[0].IntegerValue); } } BTreeNodeHelper.VisualizeIntegerTree(pager, root); //find others for (int i = 1; i < 10; i++) { DBRecord keyRecord = GetTestBRecord(i); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); } //insert after delete for (int i = 10; i < 20; i++) { DBRecord record = GetTestBRecord(i + 100); DBRecord keyRecord = GetTestBRecord(i); root = controller.InsertCell(root, keyRecord, record); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); } //find all for (int i = 1; i < 20; i++) { DBRecord keyRecord = GetTestBRecord(i); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); } pager.Close(); }
static void TestExpressionFind() { string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList); BTreeNode root = null; List <BTreeCell> result = null; Expression expression = GetAndsExpression(); for (int i = 1; i < 30; i++) { DBRecord record = GetTestRecord_expression(i, "str", (float)3.3); DBRecord key = GetTestKey_expression(i); if (i == 17 || i == 19) { record = GetTestRecord_expression(i, "str", (float)10.5); } else if (i == 20 || i == 23) { record = GetTestRecord_expression(i, "www", (float)1.3); } root = controller.InsertCell(root, key, record); } List <AttributeDeclaration> attributeNames = new List <AttributeDeclaration>(); AttributeDeclaration attribute_1 = new AttributeDeclaration(); attribute_1.AttributeName = "a"; attribute_1.IsUnique = true; attributeNames.Add(attribute_1); AttributeDeclaration attribute_2 = new AttributeDeclaration(); attribute_2.AttributeName = "b"; attribute_2.IsUnique = false; attributeNames.Add(attribute_2); AttributeDeclaration attribute_3 = new AttributeDeclaration(); attribute_3.AttributeName = "c"; attribute_3.IsUnique = false; attributeNames.Add(attribute_3); result = controller.FindCells(root, expression, "a", attributeNames); foreach (var cell in result) { LeafTableCell leafTableCell = (LeafTableCell)cell; Console.Write(leafTableCell.DBRecord.GetValues()[0].IntegerValue); Console.Write("|"); Console.Write(leafTableCell.DBRecord.GetValues()[1].StringValue); Console.Write("|"); Console.Write(leafTableCell.DBRecord.GetValues()[2].FloatValue); Console.WriteLine(); } pager.Close(); }
static void BugTest3() { string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList); BTreeNode root = null; LeafTableCell result = null; // 1 // DBRecord record = GetTestBRecord(74396264); // DBRecord keyRecord = GetTestBRecord(74396264); DBRecord record = GetTestBRecord(1); DBRecord keyRecord = GetTestBRecord(1); root = controller.InsertCell(root, keyRecord, record); // 2 // record = GetTestBRecord(1766307441); // keyRecord = GetTestBRecord(1766307441); record = GetTestBRecord(7); keyRecord = GetTestBRecord(7); root = controller.InsertCell(root, keyRecord, record); // 3 // record = GetTestBRecord(2025306881); // keyRecord = GetTestBRecord(2025306881); record = GetTestBRecord(8); keyRecord = GetTestBRecord(8); root = controller.InsertCell(root, keyRecord, record); // 4 // record = GetTestBRecord(147488698); // keyRecord = GetTestBRecord(147488698); record = GetTestBRecord(2); keyRecord = GetTestBRecord(2); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); // 5 // record = GetTestBRecord(1109110087); // keyRecord = GetTestBRecord(1109110087); record = GetTestBRecord(4); keyRecord = GetTestBRecord(4); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); // test 5 // keyRecord = GetTestBRecord(1109110087); keyRecord = GetTestBRecord(4); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); // Assert.Equal(==, result.Key.GetValues()[0].IntegerValue 1109110087); Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); // 6 // record = GetTestBRecord(1163206015); // keyRecord = GetTestBRecord(1163206015); record = GetTestBRecord(5); keyRecord = GetTestBRecord(5); // ISSUE HERE root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); // 7 // record = GetTestBRecord(1485715653); // keyRecord = GetTestBRecord(1485715653); record = GetTestBRecord(6); keyRecord = GetTestBRecord(6); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); // 8 // record = GetTestBRecord(1087082570); // keyRecord = GetTestBRecord(1087082570); record = GetTestBRecord(3); keyRecord = GetTestBRecord(3); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); pager.Close(); }
static void Bugtest2() { string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList); BTreeNode root = null; LeafTableCell result = null; DBRecord record = GetTestBRecord(660132168); DBRecord keyRecord = GetTestBRecord(660132168); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(2007593075); keyRecord = GetTestBRecord(2007593075); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(356456016); keyRecord = GetTestBRecord(356456016); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(32731844); keyRecord = GetTestBRecord(32731844); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(159431057); keyRecord = GetTestBRecord(159431057); root = controller.InsertCell(root, keyRecord, record); keyRecord = GetTestBRecord(660132168); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(660132168, result.Key.GetValues()[0].IntegerValue); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(991596943); keyRecord = GetTestBRecord(991596943); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(794643883); keyRecord = GetTestBRecord(794643883); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(1158712065); keyRecord = GetTestBRecord(1158712065); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); pager.Close(); }
static void BugTest1() { string dbPath = "./testdbfile.minidb"; File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); BTreeController controller = new BTreeController(pager, freeList); BTreeNode root = null; LeafTableCell result = null; DBRecord record = GetTestBRecord(76767785); DBRecord keyRecord = GetTestBRecord(76767785); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(1922063022); keyRecord = GetTestBRecord(1922063022); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(514874720); keyRecord = GetTestBRecord(514874720); root = controller.InsertCell(root, keyRecord, record); record = GetTestBRecord(724803552); keyRecord = GetTestBRecord(724803552); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(1219882375); keyRecord = GetTestBRecord(1219882375); root = controller.InsertCell(root, keyRecord, record); keyRecord = GetTestBRecord(724803552); result = (LeafTableCell)controller.FindCell(keyRecord, root); Assert.NotNull(result); Assert.Equal(724803552, result.Key.GetValues()[0].IntegerValue); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(681446986); keyRecord = GetTestBRecord(681446986); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(1427789753); keyRecord = GetTestBRecord(1427789753); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); record = GetTestBRecord(1066176166); keyRecord = GetTestBRecord(1066176166); root = controller.InsertCell(root, keyRecord, record); BTreeNodeHelper.VisualizeIntegerTree(pager, root); pager.Close(); }