Status Operators::IndexSelect(const string& result, // Name of the output relation const int projCnt, // Number of attributes in the projection const AttrDesc projNames[], // Projection list (as AttrDesc) const AttrDesc* attrDesc, // Attribute in the selection predicate const Operator op, // Predicate operator const void* attrValue, // Pointer to the literal value in the predicate const int reclen) // Length of a tuple in the output relation { cout << "Algorithm: Index Select" << endl; /* Your solution goes here */ Status Stat; HeapFile heapfile = HeapFile(result, Stat); if(Stat != OK) { cerr << "Open heap file fail" << endl; return Stat; } string relation = projNames[0].relName; int unique = 0; RID rid; Record record; Record tuple; //Open index file Index indScan(relation, attrDesc->attrOffset, attrDesc->attrLen, (Datatype)attrDesc->attrType, unique, Stat); if(Stat != OK){ return Stat; } //Heapscan object to access the getRandomRecord() function HeapFileScan heapScan=HeapFileScan(relation,attrDesc->attrOffset, attrDesc->attrLen,(Datatype)(attrDesc->attrType),(char *)attrValue,op,Stat); if(Stat != OK){ return Stat; } //Start Index Scan Stat = indScan.startScan(attrValue); while(indScan.scanNext(rid)==OK){ heapScan.getRandomRecord(rid,record); tuple.length = reclen; tuple.data = malloc(reclen); int offset = 0; //Project record for(int i=0; i<projCnt; ++i){ memcpy((char*)tuple.data + offset, (char*)record.data + projNames[i].attrOffset, projNames[i].attrLen); offset += projNames[i].attrLen; } Stat = heapfile.insertRecord(tuple, rid); free(tuple.data); if(Stat != OK){ return Stat; } } indScan.endScan(); heapScan.endScan(); return OK; }
//------------------------------------------------------------- // createFiles //------------------------------------------------------------- void createFiles() { struct _rec rec; memcpy(rec.filler," ",4); for (int i=0; i< NUMFILES; i++) { Status s; RID rid; HeapFile* f = new HeapFile(files[i],s); if (s != OK) cout<<"this is ridiculous !"<<endl; for (int j=0; j<dsize[i]; j++) { rec.key = data[i][j]; s = f->insertRecord((char*)&rec,sizeof(rec),rid); if (s != OK) cout<<"this is ridiculous !"<<endl; } delete f; } }
Status Updates::Insert(const string& relation, // Name of the relation const int attrCnt, // Number of attributes specified in INSERT statement const attrInfo attrList[]) // Value of attributes specified in INSERT statement { /* Your solution goes here */ Record record; int TempattrCnt; AttrDesc *attrd; bool insert = true; Status Stat; Stat = attrCat->getRelInfo(relation, TempattrCnt, attrd); if(Stat != OK){ return Stat; } if(TempattrCnt == attrCnt){ //Get length of record and allocate memory for it record.length = attrd[TempattrCnt-1].attrOffset+attrd[TempattrCnt-1].attrLen-attrd[0].attrOffset; record.data = malloc(record.length); //Reorder AttrList attrInfo Tempattrl[TempattrCnt]; for(int i=0; i<TempattrCnt; ++i){ for(int j=0; j<TempattrCnt; ++j){ if(strcmp(attrd[i].attrName, attrList[j].attrName)==0){ Tempattrl[i] = attrList[j]; } } } //Package data into record for(int i =0; i<TempattrCnt;i++){ int len = strlen((char*)Tempattrl[i].attrValue); if((Datatype)Tempattrl[i].attrType==2 && len>attrd[i].attrLen){ insert = false; }else{ memcpy((char*)record.data+attrd[i].attrOffset, Tempattrl[i].attrValue, attrd[i].attrLen); } } //Insert Data Entry into Heapfile Status openHeapStat, insertHeapStat, openIndexStat, insertIndexStat; RID recordId; int unique = 0; Datatype type; //Utilities U;//for insert test HeapFile tempHeap = HeapFile(relation, openHeapStat); if(openHeapStat == OK && insert){ //insert record into heapfile and release memory insertHeapStat = tempHeap.insertRecord(record, recordId); //U.Print(relation);//for insert test free(record.data); if(insertHeapStat == OK){ for (int i=0; i< TempattrCnt; ++i){ if(attrd[i].indexed==1){ type = (Datatype)attrd[i].attrType; Index index = Index(relation, attrd[i].attrOffset, attrd[i].attrLen,type, unique, openIndexStat); if (openIndexStat == OK){ insertIndexStat = index.insertEntry(Tempattrl[i].attrValue,recordId); }else{ delete []attrd; return openIndexStat; } } } }else{ delete []attrd; return insertHeapStat; } }else{ free(record.data); if(!insert){ delete []attrd; return ATTRTOOLONG; }else{ delete []attrd; return openHeapStat; } } }else{ delete []attrd; return ATTRTYPEMISMATCH; } delete []attrd; return OK; }
Status Operators::SMJ(const string& result, // Output relation name const int projCnt, // Number of attributes in the projection const AttrDesc attrDescArray[], // Projection list (as AttrDesc) const AttrDesc& attrDesc1, // The left attribute in the join predicate const Operator op, // Predicate operator const AttrDesc& attrDesc2, // The left attribute in the join predicate const int reclen) // The length of a tuple in the result relation { cout << "Algorithm: SM Join" << endl; Status getRes = OK; HeapFile res = HeapFile(result, getRes); if(getRes != OK){ return getRes; } //sort the left relation //calculate the number of unpinned pages to use int k = .8 * (bufMgr->numUnpinnedPages()); //get the description of the relation & add up the size of all the attributes AttrDesc *relationStats; int numAttr, recSize = 0; attrCat->getRelInfo(attrDesc1.relName, numAttr, relationStats); for(int i = 0; i < numAttr; i++){ recSize += relationStats[i].attrLen; } //calculation the number of tuples (aka max items) with k pages available int numTuples = k * PAGESIZE / recSize; SortedFile left = SortedFile(attrDesc1.relName, attrDesc1.attrOffset, attrDesc1.attrLen, (Datatype)attrDesc1.attrType, numTuples, getRes); if (getRes != OK){ return getRes; } //now do same calculation to sort the right relation k = .8 * (bufMgr->numUnpinnedPages()); recSize = 0; attrCat->getRelInfo(attrDesc2.relName, numAttr, relationStats); for(int i = 0; i < numAttr; i++){ recSize += relationStats[i].attrLen; } numTuples = k * PAGESIZE / recSize; SortedFile right = SortedFile(attrDesc2.relName, attrDesc2.attrOffset, attrDesc2.attrLen, (Datatype)attrDesc2.attrType, numTuples, getRes); if (getRes != OK){ return getRes; } Record leftRec, rightRec, newRec; newRec.data = malloc(reclen); newRec.length = 0; RID leftRid, rightRid, newRecRID; Status leftIsGood = left.next(leftRec); if(leftIsGood != OK){ free(newRec.data); return leftIsGood; } Status rightIsGood = right.next(rightRec); if(rightIsGood != OK){ free(newRec.data); return rightIsGood; } while(rightIsGood == OK && leftIsGood == OK){ //compare the records int compare = matchRec(leftRec, rightRec, attrDesc1, attrDesc2); if(compare == 0){ while(compare == 0 && leftIsGood == OK){ right.setMark(); while(compare == 0 and rightIsGood == OK){ //project the joined tuple newRec.length = 0; for (int i = 0; i < projCnt; i++){ if (strcmp(attrDescArray[i].relName, attrDesc1.relName) == 0){ memcpy((char*)newRec.data + newRec.length, (char*)leftRec.data+attrDescArray[i].attrOffset, attrDescArray[i].attrLen); } else { memcpy((char*)newRec.data + newRec.length, (char*)rightRec.data+attrDescArray[i].attrOffset, attrDescArray[i].attrLen); } newRec.length += attrDescArray[i].attrLen; } //insert projected record into result res.insertRecord(newRec, newRecRID); //get next record and compare if next() works rightIsGood = right.next(rightRec); if(rightIsGood == OK){ compare = matchRec(leftRec, rightRec, attrDesc1, attrDesc2); } } right.gotoMark(); rightIsGood = right.next(rightRec); leftIsGood = left.next(leftRec); if(leftIsGood == OK && rightIsGood == OK){ compare = matchRec(leftRec, rightRec, attrDesc1, attrDesc2); } } } else if (compare < 0){ //scan the next on the left leftIsGood = left.next(leftRec); } else { rightIsGood = right.next(rightRec); } } free(newRec.data); return OK; }
Status Operators::INL(const string& result, // Name of the output relation const int projCnt, // Number of attributes in the projection const AttrDesc attrDescArray[], // The projection list (as AttrDesc) const AttrDesc& attrDesc1, // The left attribute in the join predicate const Operator op, // Predicate operator const AttrDesc& attrDesc2, // The right attribute in the join predicate (INDEXED) const int reclen) // Length of a tuple in the output relation { cout << "Algorithm: Indexed NL Join" << endl; AttrDesc* r; int num; Status status = attrCat->getRelInfo(result, num, r); if(status != OK) return status; // Load heap 1 HeapFileScan heap1 = HeapFileScan(attrDesc1.relName, status); if (status != OK) return status; // Load heap 2 HeapFileScan heap2 = HeapFileScan(attrDesc2.relName, status); if (status != OK) return status; // Open output heap HeapFile heapOut = HeapFile(result, status); if (status != OK) return status; // Get size of output record int size = 0; for (int x = 0; x < projCnt; x++) { size += attrDescArray[x].attrLen; } // Create/find the index (checked to ensure indexed before entering this fn) Index index = Index(attrDesc2.relName, attrDesc2.attrOffset, attrDesc2.attrLen, (Datatype)attrDesc2.attrType, 1, status); if (status != OK) return status; //Start Join RID rid, rid1, rid2; Record record1, record2; while(heap1.scanNext(rid1, record1) == OK) { char* data1 = (char *) record1.data; // Update Heapfile Scan for Next Loop heap2 = HeapFileScan(attrDesc2.relName, status); if(status != OK) return status; // Restart the Index Scan for Next Loop status = index.startScan((char *) record1.data + attrDesc1.attrOffset); if(status != OK) return status; while(index.scanNext(rid2) == OK) { status = heap2.getRandomRecord(rid2, record2); if(status != OK) return status; char* data2 = (char *) record2.data; // Compare the values stored in both records int valueDif = matchRec(record1, record2, attrDesc1, attrDesc2); if(!valueDif) { // Add to output heap Record record; record.data = malloc(size); record.length = size; //Need to check through attrDescArray to find outside heap attrDescs for(int i = 0; i < projCnt; i++) { AttrDesc tempAttr = attrDescArray[i]; //Insert from attrDesc1 if( !strcmp(attrDesc1.relName, tempAttr.relName)) { memcpy(((char*) record.data) + r[i].attrOffset, data1 + tempAttr.attrOffset, tempAttr.attrLen); } else { memcpy(((char*) record.data) + r[i].attrOffset, data2 + tempAttr.attrOffset, tempAttr.attrLen); } } // Now insert the record into the output status = heapOut.insertRecord(record, rid); if(status != OK) return status; } } // End the scan and restart it again next iteration status = index.endScan(); if(status != OK) return status; } status = heap1.endScan(); if(status != OK) return status; return OK; }