//------------------------------------------------------------------- // BTreeDriver::TestAbsent // // Input : btf, The BTree to test. // key, The key to test. // ridOffset, The offset used to compute the rid. // pad, The amount of padding to use for the keys. // Output : None // Return : True if the key was not present in the tree. // Purpose : Tests whether a key is absent from the tree. //------------------------------------------------------------------- bool BTreeDriver::TestAbsent(BTreeFile *btf, int key, int ridOffset, int pad) { char skey[MAX_KEY_LENGTH]; BTreeDriver::toString(key, skey, pad); RecordID rid; rid.pageNo = key + ridOffset; rid.slotNo = key + ridOffset + 1; BTreeFileScan *scan = btf->OpenScan(skey, NULL); if (scan == NULL) { std::cerr << "Error opening scan. " << std::endl; return false; } char *curKey; RecordID curRid; bool ret = true; while (scan->GetNext(curRid, curKey) != DONE) { if (strcmp(curKey, skey) == 0 && curRid == rid) { std::cerr << "Error: Unexpected key " << skey << " present." << std::endl; ret = false; break; } else if (strcmp(curKey, skey) > 0) { break; } } delete scan; return ret; }
HeapFile *SortFile(HeapFile *S, int len, int offset) { Status s; Scan *scan; scan = S->OpenScan(s); if (s != OK) { cerr << "ERROR : cannot open scan on the heapfile to sort.\n"; } // // Scan the HeapFile S, new a B+Tree and insert the records into B+Tree. // BTreeFile *btree; btree = new BTreeFile (s, "BTree", ATTR_INT, sizeof(int)); char *recPtr = new char[len]; int recLen = len; RecordID rid; while (scan->GetNext(rid, recPtr, recLen) == OK) { btree->Insert(recPtr + offset, rid); } delete scan; HeapFile *sorted; sorted = new HeapFile(NULL, s); // create a temp HeapFile if (s != OK) { cerr << "Cannot create new file for sortedS\n"; } // // Now scan the B+-Tree and insert the records into a // new (sorted) HeapFile. // BTreeFileScan *btreeScan; btreeScan = (BTreeFileScan *)btree->OpenScan(NULL, NULL); int key; while (btreeScan->GetNext(rid, &key) == OK) { S->GetRecord (rid, recPtr, recLen); sorted->InsertRecord (recPtr, recLen, rid); } btree->DestroyFile(); delete btree; delete btreeScan; delete [] recPtr; return sorted; }
bool BTreeDriver::TestDeleteCurrent() { Status status; BTreeFile *btf; bool res; btf = new BTreeFile(status, "BTreeTest6"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 6..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; std::cout << "Inserting entries..." << std::endl; InsertRange(btf, 1, 10); char low[MAX_KEY_LENGTH]; toString(3, low); BTreeFileScan* scan = btf->OpenScan(low, NULL); std::cout << "Deleting entries..." << std::endl; RecordID rid; char* keyPtr; scan->GetNext(rid, keyPtr); // 3 scan->GetNext(rid, keyPtr); // 4 scan->DeleteCurrent(); // 5 scan->GetNext(rid, keyPtr); // 6 scan->GetNext(rid, keyPtr); // 7 scan->GetNext(rid, keyPtr); // 8 scan->DeleteCurrent(); delete scan; res = TestAbsent(btf, 4); res = TestAbsent(btf, 8); std::cout << "Inserting duplicate entry..." << std::endl; InsertKey(btf, 1, 3); toString(1, low); scan = btf->OpenScan(low, NULL); std::cout << "Deleting entry..." << std::endl; scan->GetNext(rid, keyPtr); // 1 scan->DeleteCurrent(); // 1 delete scan; res = TestAbsent(btf, 1, 1); res = TestPresent(btf, 1, 3); if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; return res; }
bool BTreeDriver::TestBufferPool() { // does some operations // at the end check if there's anything left in the buffer pool std::cout << "Starting Test 5..." << std::endl; unsigned int pinnedPages = MINIBASE_BM->GetNumOfBuffers() - MINIBASE_BM->GetNumOfUnpinnedBuffers(); std::cout << "# pinned pages: " << pinnedPages << std::endl; BTreeFile* btf; Status status; bool res = true; btf = new BTreeFile(status, "BTreeTest5"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "BTreeIndex created successfully." << std::endl; std::cout << "Performing various operations on BTreeFile." << std::endl; InsertRange(btf, 1, 1000, 1, 5, true); InsertRange(btf, 1, 1000, 2, 5, false); InsertRange(btf, 501, 1500, 3, 5, false); InsertRange(btf, 2001, 4000, 1, 5, false); char low[MAX_KEY_LENGTH]; char high[MAX_KEY_LENGTH]; BTreeFileScan *scan = btf->OpenScan(NULL, NULL); RecordID rid; char* key; int count = 0; while (scan->GetNext(rid, key) != DONE) { count++; } if (count != 5000) { std::cerr << "Number of pages inserted doesn't equal 5000. Check insert." << std::endl; res = false; } delete scan; if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; unsigned int numPinned = MINIBASE_BM->GetNumOfBuffers() - MINIBASE_BM->GetNumOfUnpinnedBuffers(); if (pinnedPages - numPinned != 0) { std::cerr << pinnedPages - numPinned << " pages still left in buffer pool after clean up." << std::endl; res = false; } return res; }
//-------------------------------------------------------------------- // JoinMethod::SortFile // // Purpose : Sorts a relation by an integer attribute. // Input : file - pointer to the HeapFile to be sorted. // len - length of the records in the file. (assume fixed size). // offset - offset of the sort attribute from the beginning of the record. // Method : We create a B+-Tree using that attribute as the key. Then // we scan the B+-Tree and insert the records into a new // HeapFile. he HeapFile guarantees that the order of // insertion will be the same as the order of scan later. // Return : The new sorted relation/HeapFile. //-------------------------------------------------------------------- HeapFile* JoinMethod::SortHeapFile(HeapFile *file, int len, int offset) { Status s; Scan *scan; scan = file->OpenScan(s); if (s != OK) { std::cerr << "ERROR : cannot open scan on the heapfile to sort." << std::endl; } // // Scan the HeapFile S, create a new B+Tree and insert the records into B+Tree. // BTreeFile *btree; btree = new BTreeFile (s, "BTree"); char* recPtr = new char[len]; int recLen = len; RecordID rid; char* recKey = new char[100]; while (scan->GetNext(rid, recPtr, recLen) == OK) { int* valPtr = (int*)(recPtr+offset); int val = *valPtr; toString(val,recKey); btree->Insert(recKey, rid); } delete scan; delete [] recKey; //std::cout << "created B+ tree!" << std::endl; HeapFile *sorted = new HeapFile(NULL, s); // create a temp HeapFile if (s != OK) { std::cerr << "Cannot create new file for sortedS\n"; } // Now scan the B+-Tree and insert the records into a // new (sorted) HeapFile. BTreeFileScan* btreeScan = btree->OpenScan(NULL, NULL); //int key; char* keyPtr; while (btreeScan->GetNext(rid, keyPtr) == OK) { //std::cout << "scanning " << rid << " " << keyPtr << std::endl; file->GetRecord (rid, recPtr, recLen); sorted->InsertRecord (recPtr, recLen, rid); } btree->DestroyFile(); delete btree; delete btreeScan; delete [] recPtr; return sorted; }
HeapFile* IndexNestedLoopJoin(JoinSpec specOfR, JoinSpec specOfS) { Status status = OK; // Create a HeapFile for join results HeapFile* joinedFile = new HeapFile(NULL, status); if (OK != status) { cerr << "ERROR: cannot create a file for the joined relation.\n"; return NULL; } int recLenR = specOfR.recLen; int recLenS = specOfS.recLen; int recLenJoined = recLenR + recLenS; char* recR = new char[recLenR]; char* recS = new char[recLenS]; char* recJoined = new char[recLenJoined]; RecordID ridR, ridS, ridJoined; // Build the B+-tree index on the inner relation (S) Scan* scanS = specOfS.file->OpenScan(status); if (OK != status) { cerr << "ERROR: cannot open scan on the relation S heap file.\n"; return NULL; } BTreeFile* bTree = new BTreeFile(status, "IJBT", ATTR_INT, sizeof(int)); while (OK == scanS->GetNext(ridS, recS, recLenS)) { bTree->Insert(recS + specOfS.offset, ridS); } delete scanS; // Iterate through the outer relation (R) and join Scan* scanR = specOfR.file->OpenScan(status); if (OK != status) { cerr << "ERROR: cannot open scan on the relation R heap file.\n"; return NULL; } while (OK == scanR->GetNext(ridR, recR, recLenR)) { int* joinArgR = (int*)&recR[specOfR.offset]; BTreeFileScan* bTreeScan = (BTreeFileScan*)bTree->OpenSearchScan(joinArgR, joinArgR); int key; while (OK == bTreeScan->GetNext(ridS, &key)) { specOfS.file->GetRecord(ridS, recS, recLenS); MakeNewRecord(recJoined, recR, recS, recLenR, recLenS); joinedFile->InsertRecord(recJoined, recLenJoined, ridJoined); } delete bTreeScan; } // Release the allocated resources delete scanR; delete[] recR; delete[] recS; delete[] recJoined; delete bTree; return joinedFile; }