12 #include "page_iterator.h" 
   13 #include "file_iterator.h" 
   14 #include "exceptions/insufficient_space_exception.h" 
   15 #include "exceptions/index_scan_completed_exception.h" 
   16 #include "exceptions/file_not_found_exception.h" 
   17 #include "exceptions/no_such_key_found_exception.h" 
   18 #include "exceptions/bad_scanrange_exception.h" 
   19 #include "exceptions/bad_opcodes_exception.h" 
   20 #include "exceptions/scan_not_initialized_exception.h" 
   21 #include "exceptions/end_of_file_exception.h" 
   23 #define checkPassFail(a, b)                                         \ 
   26     std::cout << "\nTest passed at line no:" << __LINE__ << "\n";   \ 
   29     std::cout << "\nTest FAILS at line no:" << __LINE__;            \ 
   30     std::cout << "\nExpected no of records:" << b;                  \ 
   31     std::cout << "\nActual no of records found:" << a;              \ 
   32     std::cout << std::endl;                                         \ 
   37 using namespace badgerdb;
 
   43 const std::string relationName = 
"relA";
 
   45 const int relationSize = 5000;
 
   46 std::string intIndexName, doubleIndexName, stringIndexName;
 
   59 std::string dbRecord1;
 
   67 void createRelationForward();
 
   68 void createRelationBackward();
 
   69 void createRelationRandom();
 
   81 void deleteRelation();
 
   83 int main(
int argc, 
char **argv)
 
   87     std::cout << 
"Expects one argument as a number between 1 to 3 to choose datatype of key.\n";
 
   88     std::cout << 
"For INTEGER keys run as: ./badgerdb_main 1\n";
 
   89     std::cout << 
"For DOUBLE keys run as: ./badgerdb_main 2\n";
 
   90     std::cout << 
"For STRING keys run as: ./badgerdb_main 3\n";
 
   95   sscanf(argv[1],
"%d",&testNum);
 
  125     for (
int i = 0; i < 20; ++i)
 
  130       sprintf(record1.s, 
"%05d string record", i);
 
  132       record1.d = (double)i;
 
  133       std::string new_data(reinterpret_cast<char*>(&record1), 
sizeof(record1));
 
  136       new_file.
writePage(new_page_number, new_page);
 
  143     FileScan fscan(relationName, bufMgr);
 
  150         fscan.scanNext(scanRid);
 
  152         std::string recordStr = fscan.getRecord();
 
  153         const char *record = recordStr.c_str();
 
  154         int key = *((
int *)(record + offsetof (
RECORD, i)));
 
  155         std::cout << 
"Extracted : " << key << std::endl;
 
  160       std::cout << 
"Read all records" << std::endl;
 
  180   std::cout << 
"---------------------" << std::endl;
 
  181   std::cout << 
"createRelationForward" << std::endl;
 
  182   createRelationForward();
 
  191   std::cout << 
"----------------------" << std::endl;
 
  192   std::cout << 
"createRelationBackward" << std::endl;
 
  193   createRelationBackward();
 
  202   std::cout << 
"--------------------" << std::endl;
 
  203   std::cout << 
"createRelationRandom" << std::endl;
 
  204   createRelationRandom();
 
  213 void createRelationForward()
 
  215   std::vector<RecordId> ridVec;
 
  225   file1 = 
new PageFile(relationName, 
true);
 
  228   memset(record1.s, 
' ', 
sizeof(record1.s));
 
  233   for(
int i = 0; i < relationSize; i++ )
 
  235     sprintf(record1.s, 
"%05d string record", i);
 
  237     record1.d = (double)i;
 
  238     std::string new_data(reinterpret_cast<char*>(&record1), 
sizeof(record1));
 
  249         file1->
writePage(new_page_number, new_page);
 
  255   file1->
writePage(new_page_number, new_page);
 
  262 void createRelationBackward()
 
  272   file1 = 
new PageFile(relationName, 
true);
 
  275   memset(record1.s, 
' ', 
sizeof(record1.s));
 
  280   for(
int i = relationSize - 1; i >= 0; i-- )
 
  282     sprintf(record1.s, 
"%05d string record", i);
 
  286     std::string new_data(reinterpret_cast<char*>(&record1), 
sizeof(
RECORD));
 
  297         file1->
writePage(new_page_number, new_page);
 
  303   file1->
writePage(new_page_number, new_page);
 
  310 void createRelationRandom()
 
  320   file1 = 
new PageFile(relationName, 
true);
 
  323   memset(record1.s, 
' ', 
sizeof(record1.s));
 
  329   std::vector<int> intvec(relationSize);
 
  330   for( 
int i = 0; i < relationSize; i++ )
 
  338   while( i < relationSize )
 
  340     pos = random() % (relationSize-i);
 
  342     sprintf(record1.s, 
"%05d string record", val);
 
  346     std::string new_data(reinterpret_cast<char*>(&record1), 
sizeof(
RECORD));
 
  357         file1->
writePage(new_page_number, new_page);
 
  362     int temp = intvec[relationSize-1-i];
 
  363     intvec[relationSize-1-i] = intvec[pos];
 
  368   file1->
writePage(new_page_number, new_page);
 
  388   else if(testNum == 2)
 
  399   else if(testNum == 3)
 
  418   std::cout << 
"Create a B+ Tree index on the integer field" << std::endl;
 
  419   BTreeIndex index(relationName, intIndexName, bufMgr, offsetof(
tuple,i), INTEGER);
 
  422   checkPassFail(intScan(&index,25,GT,40,LT), 14)
 
  423   checkPassFail(intScan(&index,20,GTE,35,LTE), 16)
 
  424   checkPassFail(intScan(&index,-3,GT,3,LT), 3)
 
  425   checkPassFail(intScan(&index,996,GT,1001,LT), 4)
 
  426   checkPassFail(intScan(&index,0,GT,1,LT), 0)
 
  427   checkPassFail(intScan(&index,300,GT,400,LT), 99)
 
  428   checkPassFail(intScan(&index,3000,GTE,4000,LT), 1000)
 
  436   std::cout << 
"Scan for ";
 
  437   if( lowOp == GT ) { std::cout << 
"("; } 
else { std::cout << 
"["; }
 
  438   std::cout << lowVal << 
"," << highVal;
 
  439   if( highOp == LT ) { std::cout << 
")"; } 
else { std::cout << 
"]"; }
 
  440   std::cout << std::endl;
 
  446     index->startScan(&lowVal, lowOp, &highVal, highOp);
 
  450     std::cout << 
"No Key Found satisfying the scan criteria." << std::endl;
 
  458       index->scanNext(scanRid);
 
  466         std::cout << 
" -->:" << myRec.i << 
":" << myRec.d << 
":" << myRec.s << 
":" <<std::endl;
 
  468       else if( numResults == 5 )
 
  470         std::cout << 
"..." << std::endl;
 
  481   if( numResults >= 5 )
 
  483     std::cout << 
"Number of results: " << numResults << std::endl;
 
  486   std::cout << std::endl;
 
  497   std::cout << 
"Create a B+ Tree index on the double field" << std::endl;
 
  498   BTreeIndex index(relationName, doubleIndexName, bufMgr, offsetof(
tuple,d), DOUBLE);
 
  501   checkPassFail(doubleScan(&index,25,GT,40,LT), 14)
 
  502   checkPassFail(doubleScan(&index,20,GTE,35,LTE), 16)
 
  503   checkPassFail(doubleScan(&index,-3,GT,3,LT), 3)
 
  504   checkPassFail(doubleScan(&index,996,GT,1001,LT), 4)
 
  505   checkPassFail(doubleScan(&index,0,GT,1,LT), 0)
 
  506   checkPassFail(doubleScan(&index,300,GT,400,LT), 99)
 
  507   checkPassFail(doubleScan(&index,3000,GTE,4000,LT), 1000)
 
  515   std::cout << 
"Scan for ";
 
  516   if( lowOp == GT ) { std::cout << 
"("; } 
else { std::cout << 
"["; }
 
  517   std::cout << lowVal << 
"," << highVal;
 
  518   if( highOp == LT ) { std::cout << 
")"; } 
else { std::cout << 
"]"; }
 
  519   std::cout << std::endl;
 
  525     index->startScan(&lowVal, lowOp, &highVal, highOp);
 
  529     std::cout << 
"No Key Found satisfying the scan criteria." << std::endl;
 
  537       index->scanNext(scanRid);
 
  545         std::cout << 
" -->:" << myRec.i << 
":" << myRec.d << 
":" << myRec.s << 
":" <<std::endl;
 
  547       else if( numResults == 5 )
 
  549         std::cout << 
"..." << std::endl;
 
  560   if( numResults >= 5 )
 
  562     std::cout << 
"Number of results: " << numResults << std::endl;
 
  565   std::cout << std::endl;
 
  576   std::cout << 
"Create a B+ Tree index on the string field" << std::endl;
 
  577   BTreeIndex index(relationName, stringIndexName, bufMgr, offsetof(
tuple,s), STRING);
 
  580   checkPassFail(stringScan(&index,25,GT,40,LT), 14)
 
  581   checkPassFail(stringScan(&index,20,GTE,35,LTE), 16)
 
  582   checkPassFail(stringScan(&index,-3,GT,3,LT), 3)
 
  583   checkPassFail(stringScan(&index,996,GT,1001,LT), 4)
 
  584   checkPassFail(stringScan(&index,0,GT,1,LT), 0)
 
  585   checkPassFail(stringScan(&index,300,GT,400,LT), 99)
 
  586   checkPassFail(stringScan(&index,3000,GTE,4000,LT), 1000)
 
  594   std::cout << 
"Scan for ";
 
  595   if( lowOp == GT ) { std::cout << 
"("; } 
else { std::cout << 
"["; }
 
  596   std::cout << lowVal << 
"," << highVal;
 
  597   if( highOp == LT ) { std::cout << 
")"; } 
else { std::cout << 
"]"; }
 
  598   std::cout << std::endl;
 
  601   sprintf(lowValStr,
"%05d string record",lowVal);
 
  602   char highValStr[100];
 
  603   sprintf(highValStr,
"%05d string record",highVal);
 
  609     index->startScan(lowValStr, lowOp, highValStr, highOp);
 
  613     std::cout << 
"No Key Found satisfying the scan criteria." << std::endl;
 
  621       index->scanNext(scanRid);
 
  629         std::cout << 
" -->:" << myRec.i << 
":" << myRec.d << 
":" << myRec.s << 
":" <<std::endl;
 
  631       else if( numResults == 5 )
 
  633         std::cout << 
"..." << std::endl;
 
  644   if( numResults >= 5 )
 
  646     std::cout << 
"Number of results: " << numResults << std::endl;
 
  649   std::cout << std::endl;
 
  660   std::cout << 
"Error handling tests" << std::endl;
 
  661   std::cout << 
"--------------------" << std::endl;
 
  672   file1 = 
new PageFile(relationName, 
true);
 
  675   memset(record1.s, 
' ', 
sizeof(record1.s));
 
  680   for(
int i = 0; i <10; i++ ) 
 
  682     sprintf(record1.s, 
"%05d string record", i);
 
  684     record1.d = (double)i;
 
  685     std::string new_data(reinterpret_cast<char*>(&record1), 
sizeof(record1));
 
  696         file1->
writePage(new_page_number, new_page);
 
  702   file1->
writePage(new_page_number, new_page);
 
  704   BTreeIndex index(relationName, intIndexName, bufMgr, offsetof(
tuple,i), INTEGER);
 
  710   std::cout << 
"Call endScan before startScan" << std::endl;
 
  714     std::cout << 
"ScanNotInitialized Test 1 Failed." << std::endl;
 
  718     std::cout << 
"ScanNotInitialized Test 1 Passed." << std::endl;
 
  721   std::cout << 
"Call scanNext before startScan" << std::endl;
 
  726     std::cout << 
"ScanNotInitialized Test 2 Failed." << std::endl;
 
  730     std::cout << 
"ScanNotInitialized Test 2 Passed." << std::endl;
 
  733   std::cout << 
"Scan with bad lowOp" << std::endl;
 
  736     index.startScan(&int2, LTE, &int5, LTE);
 
  737     std::cout << 
"BadOpcodesException Test 1 Failed." << std::endl;
 
  741     std::cout << 
"BadOpcodesException Test 1 Passed." << std::endl;
 
  744   std::cout << 
"Scan with bad highOp" << std::endl;
 
  747     index.startScan(&int2, GTE, &int5, GTE);
 
  748     std::cout << 
"BadOpcodesException Test 2 Failed." << std::endl;
 
  752     std::cout << 
"BadOpcodesException Test 2 Passed." << std::endl;
 
  756   std::cout << 
"Scan with bad range" << std::endl;
 
  759     index.startScan(&int5, GTE, &int2, LTE);
 
  760     std::cout << 
"BadScanrangeException Test 1 Failed." << std::endl;
 
  764     std::cout << 
"BadScanrangeException Test 1 Passed." << std::endl;
 
  770 void deleteRelation()
 
An exception that is thrown when some unexpected error occurs in the hash table. 
An exception that is thrown when some unexpected error occurs in the hash table. 
The central class which manages the buffer pool including frame allocation and deallocation to pages ...
void readPage(File *file, const PageId PageNo, Page *&page)
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
const int INTARRAYNONLEAFSIZE
Number of key slots in B+Tree non-leaf for INTEGER key. 
const int DOUBLEARRAYLEAFSIZE
Number of key slots in B+Tree leaf for DOUBLE key. 
std::string getRecord(const RecordId &record_id) const 
const int DOUBLEARRAYNONLEAFSIZE
Number of key slots in B+Tree leaf for DOUBLE key. 
const int INTARRAYLEAFSIZE
Number of key slots in B+Tree leaf for INTEGER key. 
Operator
Scan operations enumeration. Passed to BTreeIndex::startScan() method. 
void unPinPage(File *file, const PageId PageNo, const bool dirty)
std::uint32_t PageId
Identifier for a page in a file. 
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
Class which represents a fixed-size database page containing records. 
void writePage(const PageId page_number, const Page &new_page)
void flushFile(const File *file)
BTreeIndex class. It implements a B+ Tree index on a single attribute of a relation. This index supports only one scan at a time. 
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
static void remove(const std::string &filename)
const int STRINGARRAYLEAFSIZE
Number of key slots in B+Tree leaf for STRING key. 
static PageFile create(const std::string &filename)
Identifier for a record in a page. 
Page allocatePage(PageId &new_page_number)
This class is used to sequentially scan records in a relation. 
An exception that is thrown when a record is attempted to be inserted into a page that doesn't have s...
An exception that is thrown when some unexpected error occurs in the hash table. 
const int STRINGARRAYNONLEAFSIZE
Number of key slots in B+Tree leaf for STRING key. 
RecordId insertRecord(const std::string &record_data)