Example #1
0
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;
  }
}
Example #2
0
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;
}
Example #3
0
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;
		}
    }
}
Example #4
0
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;
}
Example #5
0
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;

}
Example #6
0
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;
}
Example #7
0
File: smj.cpp Project: dianazh/p14
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;
}
Example #8
0
/* 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;

}
Example #9
0
// 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;
}
Example #10
0
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;
     */
}
Example #11
0
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;
}