const Status Index::scanNext(RID& outRid) { int& offset = curOffset; Bucket* buc = curBuc; const void* value = curValue; while (offset < buc->slotCnt) { if (matchRec(buc, value, offset) == OK) break; offset++; } if (offset == buc->slotCnt) return NOMORERECS; else { outRid = *(RID *)&(buc->data[offset*recSize + headerPage->length]); offset++; return OK; } }
const Status Index::deleteEntry(const void* value, const RID & rid) { Status status; int index; Bucket* bucket; status = hashIndex(value, index); // read in the bucket that might have the entry in it int pageNo = headerPage->dir[index]; status = bufMgr->readPage(file, pageNo, (Page*&)bucket); if (status != OK) return status; // scan the bucket for the entry. Delete it if found for(int i = 0; i < bucket->slotCnt; i++) { status = matchRec(bucket, value, i); if (status == OK) { if (!memcmp(&rid, &(bucket->data[i*recSize + headerPage->length]), sizeof(RID))) { // the entry is found. Decrease the entry counts in the bucket // and copy the last entry in the bucket to the slot occupied // by the deleted entry (bucket->slotCnt)--; memcpy(&(bucket->data[i*recSize]), &(bucket->data[recSize*(bucket->slotCnt)]),recSize); status = bufMgr->unPinPage(file, pageNo, true); return status; } } } status = bufMgr->unPinPage(file, pageNo, false); if (status != OK) return status; return RECNOTFOUND; }
const Status HeapFileScan::scanNext(RID& outRid) { Status status = OK; RID nextRid; RID tmpRid; int nextPageNo; Record rec; if (curPageNo < 0) return FILEEOF; // already at EOF! // special case of the first record of the first page of the file if (curPage == NULL) { // need to get the first page of the file curPageNo = headerPage->firstPage; if (curPageNo == -1) return FILEEOF; // file is empty // read the first page of the file status = bufMgr->readPage(filePtr, curPageNo, curPage); curDirtyFlag = false; curRec = NULLRID; if (status != OK) return status; else { // get the first record off the page status = curPage->firstRecord(tmpRid); curRec = tmpRid; if (status == NORECORDS) { status = bufMgr->unPinPage(filePtr, curPageNo,curDirtyFlag); if (status != OK) return status; curPageNo = -1; // in case called again curPage = NULL; // for endScan() return FILEEOF; // first page had no records } // get pointer to record status = curPage->getRecord(tmpRid, rec); if (status != OK) return status; // see if record matches predicate if (matchRec(rec) == true) { outRid = tmpRid; return OK; } } } // Default case. already have a page pinned in the buffer pool. // First see if it has any more records on it. If so, return // next one. Otherwise, get the next page of the file for(;;) { // Loop, looking for a record that satisfied the predicate. // First try and get the next record off the current page status = curPage->nextRecord(curRec, nextRid); if (status == OK) curRec = nextRid; else while ((status == ENDOFPAGE) || (status == NORECORDS)) { // get the page number of the next page in the file status = curPage->getNextPage(nextPageNo); if (nextPageNo == -1) return FILEEOF; // end of file // unpin the current page status = bufMgr->unPinPage(filePtr,curPageNo, curDirtyFlag); curPage = NULL; curPageNo = -1; if (status != OK) return status; // get prepared to read the next page curPageNo = nextPageNo; curDirtyFlag = false; // read the next page of the file status = bufMgr->readPage(filePtr,curPageNo,curPage); if (status != OK) return status; // get the first record off the page status = curPage->firstRecord(curRec); } // curRec points at a valid record // see if the record satisfies the scan's predicate // get a pointer to the record status = curPage->getRecord(curRec, rec); if (status != OK) return status; // see if record matches predicate if (matchRec(rec) == true) { // return rid of the record outRid = curRec; 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; }
const Status HeapFileScan::scanNext(RID& outRid) { Status status = OK; RID nextRid; RID tmpRid; int nextPageNo; Record rec; bool matched = false; // Do-While loop unil a record is matched bool validRecord = false; // Only check matches if a record is valid // If the current page is -1, return EOF if (curPageNo == -1) return FILEEOF; // get the very first page, looking at the constructor, it looks like // curPage is always set, so it will never be NULL unless there was // an error before the scan or endScan was called before scanNext if (curPage == NULL){ // Get the first page and check if it's already the EOF curPageNo = headerPage->firstPage; if (curPageNo == -1) return FILEEOF; // It's not EOF so read it in and also store its next page var if ((status = bufMgr->readPage(filePtr, curPageNo, curPage)) != OK) return status; if ((status = curPage->getNextPage(nextPageNo)) != OK) return status; // Get the first record. If this returns NORECORDS, unpin the page // and return EOF because if the first page has no records, it is // the EOF if ((status = curPage->firstRecord(curRec)) != OK) { if ((status = bufMgr->unPinPage(filePtr, curPageNo, false)) != OK) return status; curPageNo = -1; return FILEEOF; } // Get the pointer to the record and check if it's a match, then // continue as we would for any other record if ((status = curPage->getRecord(curRec, rec)) != OK) return status; if (matchRec(rec) == true){ outRid = curRec; return OK; } } do{ validRecord = false; // Attempt to get the next record. If it fails, must look towards // next page if ((status = curPage->nextRecord(curRec, nextRid)) != OK) { // Get the next page if ((status = curPage->getNextPage(nextPageNo)) != OK) return status; // Check to see if the next page exists if (nextPageNo != -1) { // Page does exist, so we unpin the current one and read in the next if ((status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag)) != OK)return status; if ((status = bufMgr->readPage(filePtr, nextPageNo, curPage)) != OK) return status; curPageNo = nextPageNo; // Get the first record on the new page. If no error is returned, this // is a valid record and we can check it for a match if ((status = curPage->firstRecord(curRec)) == OK) validRecord = true; } // The page doesn't exist, so we return FILEEOF else { return FILEEOF; } } // Getting the nextRecord didn't have an error, so we set curRec since this // is a valid record else { curRec = nextRid; validRecord = true; } // If a record is valid, we can get the pointer to the actual record and // check for a match. If the record isn't valid, it loops around and tries // to find a valid record or runs into an EOF if (validRecord == true){ if ((status = curPage->getRecord(curRec, rec)) != OK) return status; matched = matchRec(rec); if (matched == true) { outRid = curRec; } } } while (!matched); 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; // Relation names string relation1 = attrDesc1.relName; string relation2 = attrDesc2.relName; // Determine num-bytes of individual record for each input relation // Relation 1 int attrCnt1, attrCnt2, recLen1, recLen2; AttrDesc* attrs1, * attrs2, * end; Status status = attrCat->getRelInfo(relation1, attrCnt1, attrs1); if (status != OK) { return status; } recLen1 = 0; end = attrs1 + attrCnt1; while (attrs1 != end) { recLen1 += attrs1->attrLen; ++attrs1; } // Relation 2 status = attrCat->getRelInfo(relation2, attrCnt2, attrs2); if (status != OK) { return status; } recLen2 = 0; end = attrs2 + attrCnt2; while (attrs2 != end) { recLen2 += attrs2->attrLen; ++attrs2; } // Calculate max num tuples for each input relation int mnr1 = 0.8 * bufMgr->numUnpinnedPages() * PAGESIZE / recLen1; int mnr2 = 0.8 * bufMgr->numUnpinnedPages() * PAGESIZE / recLen2; // Initialize sorted files // Relation 1 SortedFile sf1( relation1, attrDesc1.attrOffset, attrDesc1.attrLen, (Datatype)attrDesc1.attrType, mnr1, status ); if (status != OK) { return status; } // Relation 2 SortedFile sf2( relation2, attrDesc2.attrOffset, attrDesc2.attrLen, (Datatype)attrDesc2.attrType, mnr2, status ); if (status != OK) { return status; } // Initialize heap file for output relation HeapFile outputHf(result, status); if (status != OK) { return status; } Record rec1, rec2; //Initialize rec2 status = sf2.next(rec2); if(status == FILEEOF) { return OK; } else if (status != OK) { return status; } while (1) { status = sf1.next(rec1); if (status == FILEEOF) { break; } else if (status != OK) { return status; } bool fileEnd = false; //Step through file 1 while rec2's attribute is greater than rec1's while (matchRec(rec1, rec2, attrDesc1, attrDesc2) < 0) { status = sf1.next(rec1); if(status == FILEEOF) { fileEnd = true; break; } else if (status != OK) { return status; } } if(fileEnd) { break; } //Step through file 2 while rec1's attribute is greater than rec2's while (matchRec(rec1, rec2, attrDesc1, attrDesc2) > 0) { status = sf2.next(rec2); if(status == FILEEOF) { fileEnd = true; break; } else if (status != OK) { return status; } } if(fileEnd) { break; } //Confirm that a match has been found. If not, restart the search process. if(matchRec(rec1, rec2, attrDesc1, attrDesc2) != 0) { continue; } //Found a join match, since neither attribute value is greater than the other sf2.setMark(); while (matchRec(rec1, rec2, attrDesc1, attrDesc2) == 0) { // Join records // Build join-record data with projected attributes char* joinRecData = new char[reclen]; for (int adIdx = 0; adIdx < projCnt; ++adIdx) { // Determine from which to copy Record* inputRecord = strcmp(attrDescArray[adIdx].relName, attrDesc1.relName) ? &rec2 : &rec1; // Copy data from input record to join record memcpy( joinRecData, (char*)inputRecord->data + attrDescArray[adIdx].attrOffset, attrDescArray[adIdx].attrLen ); // Advance join record pointer joinRecData += attrDescArray[adIdx].attrLen; } // Insert join record into result heap file joinRecData -= reclen; Record joinRec = {joinRecData, reclen}; RID outputRid; status = outputHf.insertRecord(joinRec, outputRid); if (status != OK) { return status; } //step through file 2 as long as a match exists status = sf2.next(rec2); if(status == FILEEOF) { break; } else if (status != OK) { return status; } } //Go back to the start of the matching record interval in file 2, //to check for possible duplicate values in file 1. sf2.gotoMark(); status = sf2.next(rec2); if(status == FILEEOF) { break; } else if (status != OK) { return status; } } 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; /* Your solution goes here */ Status status; RID rid_old1; Record rec_old1; int maxitem1; status = get_maxItems(string(attrDesc1.relName), maxitem1); if (status != OK) return status; SortedFile table1 (attrDesc1.relName, attrDesc1.attrOffset, attrDesc1.attrLen, (Datatype)attrDesc1.attrType, maxitem1, status); if (status != OK) return status; RID rid_old2; Record rec_old2; int maxitem2; status = get_maxItems(string(attrDesc2.relName), maxitem2); if (status != OK) return status; SortedFile table2 (attrDesc2.relName, attrDesc2.attrOffset, attrDesc2.attrLen, (Datatype)attrDesc2.attrType, maxitem2, status); if (status != OK) return status; HeapFile new_hf(result, status); if (status != OK) return status; RID rid_new; Record rec_new; bool matched = false; bool end_loop = false; Record prev_rec1; int diff; status = table1.next(rec_old1); if (status == FILEEOF) return OK; else if (status != OK) return status; status = table2.next(rec_old2); if (status == FILEEOF) return OK; else if (status != OK) return status; //initial new_rec rec_new.length = reclen; rec_new.data = operator new (reclen); while (!end_loop){ matched = false; diff = matchRec(rec_old1, rec_old2, attrDesc1, attrDesc2); if (diff < 0){ //next tuple in rel1 memcpy (&prev_rec1, &rec_old1, sizeof(Record)); //copy the previous rec in rel1 status = table1.next(rec_old1); if (status == FILEEOF){ end_loop = true; } else if (status != OK){ operator delete (rec_new.data); return status; } if (matchRec(prev_rec1, rec_old1, attrDesc1, attrDesc1)==0){ //is equal table2.gotoMark(); table2.next(rec_old2); } } else if (diff > 0){ //next tuple in rel2 status = table2.next(rec_old2); if (status == FILEEOF){ end_loop = true; } else if (status != OK){ operator delete (rec_new.data); return status; } } while ((diff == 0)&&(!end_loop)){ //match if (!matched){ table2.setMark(); matched = true; } //insert new tuple int offset = 0; for (int i=0; i<projCnt; i++){ if (!strcmp(attrDescArray[i].relName, attrDesc1.relName)){ //in rel1 memcpy(rec_new.data+offset, rec_old1.data+attrDescArray[i].attrOffset, attrDescArray[i].attrLen); offset += attrDescArray[i].attrLen; } else { memcpy(rec_new.data+offset, rec_old2.data+attrDescArray[i].attrOffset, attrDescArray[i].attrLen); offset += attrDescArray[i].attrLen; } } status = new_hf.insertRecord(rec_new, rid_new); if (status != OK) { operator delete (rec_new.data); return status; } //get next tuple status = table2.next(rec_old2); if (status == FILEEOF){ //if end of inner loop memcpy (&prev_rec1, &rec_old1, sizeof(Record)); //copy the previous rec in rel1 status = table1.next(rec_old1); if (status == FILEEOF){ end_loop = true; } else if (status != OK){ operator delete (rec_new.data); return status; } if (matchRec(prev_rec1, rec_old1, attrDesc1, attrDesc1)==0){ //is equal table2.gotoMark(); table2.next(rec_old2); } else { end_loop = true; } } else if (status != OK){ operator delete (rec_new.data); return status; } diff = matchRec(rec_old1, rec_old2, attrDesc1, attrDesc2); } } operator delete (rec_new.data); return OK; }
/* Scans through the heap file one page at a time. * params: RID& outRid * actually the return value. The next rid in the scan that satisfies the san predicate. * returns: uses outRid param as return * */ const Status HeapFileScan::scanNext(RID& outRid) { Status status = OK; Status tmpStatus = OK; RID nextRid; RID tmpRid; int nextPageNo; Record rec; bool first = false; // Track whethere this is the first time scanning the page or part of the sequence if (curRec.pageNo == -1) { // First scan, do some set up first = true; nextPageNo = headerPage->firstPage; } else { // Scan in progress tmpRid = curRec; nextPageNo = tmpRid.pageNo; } status = OK; while (status == OK) { // Check if curPage has link to next page. while (nextPageNo > 0) { if (nextPageNo != curPageNo) { // Next page isn't the one currently pinned. // Unpin and read in new page. status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag); status = bufMgr->readPage(filePtr, nextPageNo, curPage); // Update private members appropriately for new page. curPageNo = nextPageNo; curDirtyFlag = false; } // Set things up for first run through. if (first) { // Avoid breaking the while loop for this..need to not just quit. if ((tmpStatus = curPage->firstRecord(tmpRid)) != OK) { // Empty page, nothing to do here. status = curPage->getNextPage(nextPageNo); continue; // Go to next loop. } status = curPage->getRecord(tmpRid, rec); // Finally found the match! if (matchRec(rec)) { // Store the rid in curRec and return curRec curRec = tmpRid; outRid = curRec; return OK; } } // Again. avoid breaking while loop here with tmpStatus. // Get the next record on the page, avoiding invalid slots and checking to see if we are at the end of the page while ((tmpStatus = curPage->nextRecord(tmpRid, nextRid)) != ENDOFPAGE && tmpStatus != INVALIDSLOTNO) { tmpRid = nextRid; status = curPage->getRecord(tmpRid, rec); // Finally found the match! if (matchRec(rec)) { // Store the rid in curRec and return curRec curRec = tmpRid; outRid = curRec; return OK; } } status = curPage->getNextPage(nextPageNo); first = true; } outRid = NULLRID; status = FILEEOF; } return status; }
// implementation of sort merge join goes here const Status QU_SM_Join(const string & result, const int projCnt, const attrInfo projNames[], const attrInfo *attr1, const Operator op, const attrInfo *attr2) { Status status; if (attr1->attrType != attr2->attrType || attr1->attrLen != attr2->attrLen) { return ATTRTYPEMISMATCH; } // go through the projection list and look up each in the // attr cat to get an AttrDesc structure (for offset, length, etc) AttrDesc attrDescArray[projCnt]; for (int i = 0; i < projCnt; i++) { Status status = attrCat->getInfo(projNames[i].relName, projNames[i].attrName, attrDescArray[i]); if (status != OK) { return status; } } // get AttrDesc structure for the first join attribute AttrDesc attrDesc1; status = attrCat->getInfo(attr1->relName, attr1->attrName, attrDesc1); if (status != OK) { return status; } // get AttrDesc structure for the first join attribute AttrDesc attrDesc2; status = attrCat->getInfo(attr2->relName, attr2->attrName, attrDesc2); if (status != OK) { return status; } // get output record length from attrdesc structures int reclen = 0; for (int i = 0; i < projCnt; i++) { reclen += attrDescArray[i].attrLen; } // open sorted scans on both input files SortedFile sorted1(attrDesc1.relName, attrDesc1.attrOffset, attrDesc1.attrLen, (Datatype) attrDesc1.attrType, 1000, status); if (status != OK) { return status; } SortedFile sorted2(attrDesc2.relName, attrDesc2.attrOffset, attrDesc2.attrLen, (Datatype) attrDesc2.attrType, 1000, status); if (status != OK) { return status; } sorted2.setMark(); // prepare output buffer char outputData[reclen]; Record outputRec; outputRec.data = (void *) outputData; outputRec.length = reclen; // open output relation file InsertFileScan resultRel(result, status); if (status != OK) { return status; } // scan the outer file bool firstTime = true; bool endOfInner = false; Record outerRec; while (sorted1.next(outerRec) == OK) { if (!firstTime) { // go back sorted2.gotoMark(); endOfInner = false; } else firstTime = false; // go forward until we get a match Record innerRec; bool done = false; while (!done) { if (OK != sorted2.next(innerRec)) { endOfInner = true; break; } if (matchRec(outerRec, innerRec, attrDesc1, attrDesc2) <= 0) done = true; } sorted2.setMark(); while (! endOfInner && matchRec(outerRec, innerRec, attrDesc1, attrDesc2) == 0) { // we have a match, copy data into the output record int outputOffset = 0; for (int i = 0; i < projCnt; i++) { // copy the data out of the proper input file (inner vs. outer) if (0 == strcmp(attrDescArray[i].relName, attrDesc1.relName)) { memcpy(outputData + outputOffset, (char *)outerRec.data + attrDescArray[i].attrOffset, attrDescArray[i].attrLen); } else // get data from the inner record { memcpy(outputData + outputOffset, (char *)innerRec.data + attrDescArray[i].attrOffset, attrDescArray[i].attrLen); } outputOffset += attrDescArray[i].attrLen; } // end copy attrs // add the new record to the output relation RID outRID; status = resultRel.insertRecord(outputRec, outRID); ASSERT(status == OK); // scan to the next entry in the inner sorted file if (OK != sorted2.next(innerRec)) endOfInner = true; } // end scan inner } // end scan outer return OK; }
const Status HeapFileScan::scanNext(RID& outRid) { Status status = OK; RID nextRid; RID tmpRid; int nextPageNo; Record rec; tmpRid = curRec; while(status == OK) { status = curPage->nextRecord(tmpRid, nextRid); while(status != OK) { status = curPage->getNextPage(nextPageNo); if(status != OK) return status; if(nextPageNo == -1) return FILEEOF; status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag); if(status != OK) return status; curPageNo = nextPageNo; status = bufMgr->readPage(filePtr, curPageNo, curPage); if(status != OK) return status; curDirtyFlag = false; status = curPage->firstRecord(nextRid); } status = curPage->getRecord(nextRid, rec); if(status != OK) return status; if(matchRec(rec)) { curRec = nextRid; outRid = nextRid; return OK; } tmpRid = nextRid; } return FILEEOF; /* //Unpins Current Page status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag); if(status != OK) return status; curDirtyFlag = false; //Read in first page nextPageNo = headerPage->firstPage; for(int i = 0; i < headerPage->pageCnt; i++) { status = bufMgr->readPage(filePtr, nextPageNo, curPage); if(status != OK) return status; //Get first record of first page status = curPage->firstRecord(nextRid); if(status != OK) return status; while(status == OK) { status = curPage->getRecord(nextRid, rec); if(status != OK) return status; if(matchRec(rec)) { curRec = nextRid; outRid = nextRid; return OK; } tmpRid = nextRid; status = curPage->nextRecord(tmpRid, nextRid); } status = bufMgr->unPinPage(filePtr, curPageNo, curDirtyFlag); if(status != OK) return status; status = curPage->getNextPage(nextPageNo); if(status != OK) return status; } return FILEEOF; */ }
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; }