// An example procedure of appending a tuple to the end of a relation // using memory block "memory_block_index" as output buffer void appendTupleToRelation(Relation* relation_ptr, MainMemory& mem, int memory_block_index, Tuple& tuple) { Block* block_ptr; if (relation_ptr->getNumOfBlocks()==0) { cout << "The relation is empty" << endl; cout << "Get the handle to the memory block " << memory_block_index << " and clear it" << endl; block_ptr=mem.getBlock(memory_block_index); block_ptr->clear(); //clear the block block_ptr->appendTuple(tuple); // append the tuple cout << "Write to the first block of the relation" << endl; relation_ptr->setBlock(relation_ptr->getNumOfBlocks(),memory_block_index); } else { cout << "Read the last block of the relation into memory block 5:" << endl; relation_ptr->getBlock(relation_ptr->getNumOfBlocks()-1,memory_block_index); cout << "LOL LOL LOL " << relation_ptr->getNumOfBlocks()-1 << " " << memory_block_index << endl; block_ptr=mem.getBlock(memory_block_index); cout << "Printing block please" << *block_ptr << endl; if (block_ptr->isFull()) { cout << "(The block is full: Clear the memory block and append the tuple)" << endl; block_ptr->clear(); //clear the block block_ptr->appendTuple(tuple); // append the tuple cout << "Write to a new block at the end of the relation" << endl; relation_ptr->setBlock(relation_ptr->getNumOfBlocks(),memory_block_index); //write back to the relatio cout << "This condition should never be true, or big problem" << endl; } else { cout << "(The block is not full: Append it directly)" << endl; block_ptr->appendTuple(tuple); // append the tuple cout << "Write to the last block of the relation" << endl; relation_ptr->setBlock(relation_ptr->getNumOfBlocks()-1,memory_block_index); //write back to the relation } } }
bool InMemorySort(int start_index, int num_blocks, vector<string> field_names) {// InMemorySort for 2-pass algorithm //count of blocks to sort in main memory vector<Tuple> mem_tuples = mem.getTuples(start_index, num_blocks); sort(mem_tuples.begin(), mem_tuples.end(), Tuple_Comparison(field_names)); for(int index=start_index; index< num_blocks; index++) { mem.getBlock(index)->clear(); // clearing the blocks } bool success = mem.setTuples(start_index, mem_tuples); if(!success) cout<<"Error in InMemorySort"<<endl; return success; }
//Main Memory Sorting //In memory sorting operation based on tuples bool MMSorting(int startMemIndex, int noOfBlocks, vector<string> fieldNames) { //total no of blocks to sort vector<Tuple> tuplesInMem = mem.getTuples(startMemIndex, noOfBlocks); sort(tuplesInMem.begin(), tuplesInMem.end(), CompareTuple(fieldNames)); //clear out any data in the given range of memory block for(int i=startMemIndex; i< noOfBlocks; i++) { mem.getBlock(i)->clear(); } bool success = mem.setTuples(startMemIndex, tuplesInMem); if(!success) cout<<"Error in MMSorting"<<endl; return success; }
int findBlockForTuple(MainMemory &mem){ Block* block_ptr = mem.getBlock(free_blocks.front()); while (block_ptr->isFull()){ if (free_blocks.empty()){ cout << "No free blocks left. Everything is terrible." << endl; return -1; } free_blocks.pop_front(); block_ptr = mem.getBlock(free_blocks.front()); } //we have a block that is not full //free(block_ptr); cout << endl << endl; cout << " BIG BIG BIG " << free_blocks.front() << endl << endl; return free_blocks.front(); }
void deleteFromTable(string tableName, string whereCondition) { if(whereCondition.empty()){ if(!schemaManager.relationExists(tableName)) { cout<<"Illegal Table Name"<<endl; return; } Relation *relation = schemaManager.getRelation(tableName); while(relation->getNumOfBlocks()) relation->deleteBlocks(relation->getNumOfBlocks()-1); } else { Relation *relation = schemaManager.getRelation(tableName); for(int i=0;i<relation->getNumOfBlocks();i++) { relation->getBlock(i,0); Block *block = mainMemory.getBlock(0); vector<Tuple> tuples = block->getTuples(); for(int j=0;j<tuples.size();j++) { if(!tuples[j].isNull() && whereConditionEvaluator(whereCondition, tuples[j])) { block->nullTuple(j); } } relation->setBlock(i,0); } } }
void insertTuple(string tableName, Tuple tuple) { Relation *relation = schemaManager.getRelation(tableName); if(relation->getNumOfBlocks()>0){ relation->getBlock(relation->getNumOfBlocks()-1,9); Block *block = mainMemory.getBlock(9); if(block->isFull()){ block->clear(); block->appendTuple(tuple); relation->setBlock(relation->getNumOfBlocks(),9); } else { block->appendTuple(tuple); relation->setBlock(relation->getNumOfBlocks()-1,9); } } else { Block *block = mainMemory.getBlock(9); block->clear(); block->setTuple(0,tuple); relation->setBlock(0,9); } }
/** * Entry point to the Karana Lightweight SQL Interpreter. */ int main (int argc, char ** argv) { //Handle command-line params for usage etc if (argc == 1) { cout << "\n Karana: Lightweight SQL interpreter: " << endl; cout << "------------------------------------------------" << endl; cout << "Usage:\n Login and then enter SQL queries from the prompt $$" << endl; cout << "End every query with a delimiter ;" << endl; cout << "Do not enter two complete queries in one line." << endl; cout << "Type 'quit' to quit the program." << endl; cout << "------------------------------------------------" << endl; } else { if (argv[1] == "--h" ) { cout << "\n Karana: Lightweight SQL interpreter: " << endl; cout << "------------------------------------------------" << endl; cout << "Usage:\n Login and then enter SQL queries from the prompt $$" << endl; cout << "End every query with a delimiter ;" << endl; cout << "Do not enter two complete queries in one line." << endl; cout << "Type 'quit' to quit the program." << endl; cout << "------------------------------------------------" << endl; } } //Instantiate all major objects cout << "The memory now contains " << mem.getMemorySize() << " blocks" << endl << endl; setDelay(10); //Perform some initial data setup. initial_setup(); // Ask for user to input a query string line = "", query = "", linepart = ""; const char* chars = "\n\t\v\f\r "; size_t delimPosition; //printlogicaltree or printphysicaltree - flags to signify that the user requested to print parse //trees for logical or physical tree int printphysicaltree = 0, printlogicaltree = 0; while (line != "quit" && line != "QUIT") { //Check if there were any unterminated queries from previous line. if (!linepart.empty() && linepart.find_first_not_of(chars) != string::npos) { cout << "Continuing from the line: " << endl << linepart << endl; line = linepart + line; linepart = ""; } line = trim(line); delimPosition = line.find_last_of(";"); if (delimPosition == string::npos) { linepart = line; } else if (delimPosition != line.size()) { query = line.substr(0,delimPosition); linepart = line.substr(delimPosition+1); } if (!query.empty()) { if (query == "printlogicaltree") { printlogicaltree = 1; } else if (query == "printphysicaltree") { printphysicaltree = 1; } else { //Loop for each query run_query(query, printlogicaltree, printphysicaltree, 0, false); } cout << endl << "------------------------------------------" << endl; } cout << endl << "$$ "; query = ""; getline(cin, line); } //Perform some final cleanup final_cleanup(); }
int main() { //=======================Initialization========================= cout << "=======================Initialization=========================" << endl; // Initialize the memory, disk and the schema manager MainMemory mem; Disk disk; cout << "The memory contains " << mem.getMemorySize() << " blocks" << endl; cout << mem << endl << endl; SchemaManager schema_manager(&mem,&disk); Schema *schema; disk.resetDiskIOs(); disk.resetDiskTimer(); // Another way to time clock_t start_time; start_time=clock(); // TODO Set up a block here?? //=========================Initialization ends ========================== string line; vector<string> strings; ifstream myfile ("TinySQL_linux.txt"); if(myfile.is_open()) { while(getline (myfile,line)) { //cout << line << '\n'; istringstream f(line); string s; while(getline(f, s, ' ')) { //cout << s << endl; strings.push_back(s); } if(strings[0].compare("CREATE") == 0) { // Creating a schema for the create statement. schema = processCreate(strings); //printSchema(*schema); // Creating the relation with the schema above using schema manager. string relation_name=strings[2]; cout << "Creating table " << relation_name << endl; Relation* relation_ptr=schema_manager.createRelation(relation_name, *schema); //printRelation(relation_ptr); } // TODO Change the command to lower-case and compare else if(strings[0].compare("INSERT") == 0) { cout << "It is an INSERT statement " << endl; processInsert(line, strings, schema_manager); } else if(strings[0].compare("SELECT") == 0) { cout << "It is a SELECT statement " << endl; processSelect(line, strings, schema_manager, &mem); } strings.clear(); } myfile.close(); } else cout << "Unable to open file"; return 0; }
string crossJoin(vector<string> attributes, string tableName1, string tableName2, string whereCondition, bool multi) { string small,big; bool proj = false; if(schemaManager.getRelation(tableName1)->getNumOfBlocks()<=schemaManager.getRelation(tableName2)->getNumOfBlocks()) { small = tableName1; big = tableName2; } else { small=tableName2; big=tableName1; } Schema schema1 = schemaManager.getSchema(small); Schema schema2 = schemaManager.getSchema(big); vector<string> fieldNames; vector<enum FIELD_TYPE> fieldTypes; if(!multi) { for(int i=0;i<schema1.getNumOfFields();i++) { fieldNames.push_back(small+"."+schema1.getFieldName(i)); fieldTypes.push_back(schema1.getFieldType(i)); } } else { for(int i=0;i<schema1.getNumOfFields();i++) { fieldNames.push_back(schema1.getFieldName(i)); fieldTypes.push_back(schema1.getFieldType(i)); } } for(int i=0;i<schema2.getNumOfFields();i++) { fieldNames.push_back(big+"."+schema2.getFieldName(i)); fieldTypes.push_back(schema2.getFieldType(i)); } Schema schema(fieldNames,fieldTypes); Relation *relation = schemaManager.createRelation(big+"_join",schema); Relation *relation1 = schemaManager.getRelation(small); Relation *relation2 = schemaManager.getRelation(big); int size1 = relation1->getNumOfBlocks(), size2 = relation2->getNumOfBlocks(); if(!((attributes.size()==1 && attributes[0]=="*") || multi)) { vector<string> fieldNames1; vector<enum FIELD_TYPE> fieldTypes1; for(int i=0;i<attributes.size();i++) { int temp = schema.getFieldOffset(attributes[i]); fieldNames1.push_back(schema.getFieldName(temp)); fieldTypes1.push_back(schema.getFieldType(attributes[i])); } Schema schema1(fieldNames1, fieldTypes1); proj = true; Relation *relationp = schemaManager.createRelation(big+"_joinp", schema1); } if(size1<=10) { relation1->getBlocks(0,0,size1); vector<Tuple> tuples = mainMemory.getTuples(0,size1); for(int x=0;x<tuples.size();x++) { for(int i=0;i<size2;i++) { relation2->getBlock(i,1); Block *block = mainMemory.getBlock(1); for(int j=0;j<block->getNumTuples();j++) { Tuple tuple2 = block->getTuple(j); join(tuples[x], tuple2, small, big, whereCondition, multi, attributes); } } } } else { for(int x=0;x<size1;x++) { relation1->getBlock(x,0); Block *block0 = mainMemory.getBlock(0); for(int y=0;y<block0->getNumTuples();y++) { Tuple tuple1 = block0->getTuple(y); for(int i=0;i<size2;i++) { relation2->getBlock(i,1); Block *block = mainMemory.getBlock(1); for(int j=0;j<block->getNumTuples();j++) { Tuple tuple2 = block->getTuple(j); join(tuple1, tuple2, small, big, whereCondition, multi, attributes); } } } } } string rt = big+"_join"; if(proj) { schemaManager.deleteRelation(rt); rt = big+"_joinp"; } return rt; }
string distinct(string tableName) { Relation *relation = schemaManager.getRelation(tableName); Schema schema = relation->getSchema(); int size = relation->getNumOfBlocks(); vector<Tuple> tuples; bool flag = true; //one-pass if(size<=10) { relation->getBlocks(0,0,size); tuples = mainMemory.getTuples(0,size); tuples = getDistinctTuples(tuples); Relation *relation1 = schemaManager.createRelation(tableName+"_distinct",schema); insertTuples(tableName+"_distinct",tuples); } //two pass else { int index = 0, loadSize=10; while(size>0) { relation->getBlocks(index,0,loadSize); for(int i=0;i<loadSize;i++) { Block *block = mainMemory.getBlock(i); for(int j=0;j<block->getNumTuples();j++) { tuples.push_back(block->getTuple(j)); } } tuples = getDistinctTuples(tuples); //partition(tuples, 0, tuples.size()-1); if(flag) { Relation *relation2= schemaManager.createRelation(tableName+"_dis", schema); flag = false; } insertTuples(tableName+"_dis", tuples); Relation *relation2 = schemaManager.getRelation(tableName+"_dis"); tuples.clear(); index = index+10; size = size-10; if(size<10) loadSize = size; } if(size<=100) { Relation *relation2 = schemaManager.createRelation(tableName+"_distinct", schema); relation = schemaManager.getRelation(tableName+"_dis"); int buckets = relation->getNumOfBlocks()/10; vector<Tuple> tuples; for(int i=0;i<10;i++) { for(int j=0;j<buckets;j++) { if(j*10+i > relation->getNumOfBlocks()) break; relation->getBlock(i+10*j,j); Block *block = mainMemory.getBlock(j); for(int k=0;k<block->getNumTuples();k++) { tuples.push_back(block->getTuple(k)); } } } tuples = getDistinctTuples(tuples); insertTuples(tableName+"_distinct", tuples); tuples.clear(); schemaManager.deleteRelation(tableName+"_dis"); } else cerr<<"Table size exceeds the limit size(mainMemory)^2"<<endl; } return tableName+"_distinct"; }
string projection(vector<string> attributes, string tableName, string whereCondition) { Relation *relation = schemaManager.getRelation(tableName); Schema tableSchema = relation->getSchema(); vector<string> fieldNames; vector<enum FIELD_TYPE> fieldTypes; vector<string>::iterator it; int flag=-1; bool print=true; for(it=attributes.begin();it!=attributes.end();it++) { for(int i=0;i<tableSchema.getNumOfFields();i++) { string temp = *it; if(tableSchema.getFieldName(i)==temp || tableName+"."+tableSchema.getFieldName(i) == temp) flag=i; } if(flag!=-1) { fieldNames.push_back(tableSchema.getFieldName(flag)); fieldTypes.push_back(tableSchema.getFieldType(flag)); flag = -1; } } if(attributes.size()==1 && attributes[0] == "*") { if(whereCondition.empty()) return tableName; fieldNames = tableSchema.getFieldNames(); fieldTypes = tableSchema.getFieldTypes(); } Schema dupSchema(fieldNames,fieldTypes); Relation *relationDup = schemaManager.createRelation(tableName.append("_dup"), dupSchema); Tuple tuple = relationDup->createTuple(); vector<Tuple>::iterator it1; Block *block = mainMemory.getBlock(9); block->clear(); int index=0; for(int i=0;i<relation->getNumOfBlocks();i++) { relation->getBlock(i,0); vector<Tuple> t = mainMemory.getBlock(0)->getTuples(); for(it1=t.begin();it1!=t.end();it1++) { if(!it1->isNull()){ for(int j=0;j<fieldNames.size();j++) { if(fieldTypes[j]==INT) tuple.setField(fieldNames[j],it1->getField(fieldNames[j]).integer); else tuple.setField(fieldNames[j],*(it1->getField(fieldNames[j]).str)); } bool ttp = whereConditionEvaluator(whereCondition, *it1); if(ttp) { if(!block->isFull()) block->appendTuple(tuple); else { relationDup->setBlock(index,9); index++; block->clear(); block->appendTuple(tuple); } } } } } if(index!=relationDup->getNumOfBlocks()-1) relationDup->setBlock(index, 9); return tableName; }