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;
}
Exemple #2
0
HeapFile *SortFile(HeapFile *S, int len, int offset)
{
	Status s;

	Scan *scan;
	scan = S->OpenScan(s);
	if (s != OK)
	{
		cerr << "ERROR : cannot open scan on the heapfile to sort.\n";
	}

	//
	// Scan the HeapFile S, new a B+Tree and insert the records into B+Tree.
	// 

	BTreeFile *btree;
	btree = new BTreeFile (s, "BTree", ATTR_INT, sizeof(int));

	char *recPtr = new char[len];
	int recLen = len;
	RecordID rid;
	while (scan->GetNext(rid, recPtr, recLen) == OK)
	{
		btree->Insert(recPtr + offset, rid);
	}
	delete scan;

	HeapFile *sorted;
	sorted = new HeapFile(NULL, s); // create a temp HeapFile
	if (s != OK)
	{
	    	cerr << "Cannot create new file for sortedS\n";
	}

	//
	// Now scan the B+-Tree and insert the records into a 
	// new (sorted) HeapFile.
	//

	BTreeFileScan  *btreeScan;
	btreeScan = (BTreeFileScan *)btree->OpenScan(NULL, NULL);

	int key;

	while (btreeScan->GetNext(rid, &key) == OK)
	{
	    S->GetRecord (rid, recPtr, recLen);
	    sorted->InsertRecord (recPtr, recLen, rid);
	}
	btree->DestroyFile();

	delete btree;
	delete btreeScan;
	delete [] recPtr;

	return sorted;
}
//-------------------------------------------------------------------
// Sort::MergeManyToOne
//
// Input   : numSourceFiles,	number of files needed to be merged
//			 source,			array of heap files to be merged
//			 dest,				output heap file
// Output  : None
// Return  : OK if merging succeeds, FAIL otherwise
//-------------------------------------------------------------------
Status Sort::MergeManyToOne(unsigned int numSourceFiles, HeapFile **source, HeapFile *dest) {
	// Open a scan for each source file
	Status status;
	int numOfRecords = 0, recCounter = 0;
	Scan **scanners = new Scan *[numSourceFiles];
	RecordID rid; char *recPtr = (char *)malloc(_recLength); int recLen = _recLength;
	for (int i=0; i<numSourceFiles; i++) {
		HeapFile *hf = source[i];
		Scan *scan = hf->OpenScan(status);
		if (status != OK) return ReturnFAIL("Opening scanners in MergeManyToOne failed.");
		scanners[i] = scan;
		numOfRecords += hf->GetNumOfRecords();
	}
	// Create a vector to hold (numSourceFiles) records to compare
	std::vector<std::tuple<char *, int>> values;
	char **recPtrArray = new char*[numSourceFiles];
	for (int i=0; i<numSourceFiles; i++) {
		if (scanners[i]->GetNext(rid,recPtr,recLen) != OK)
			return ReturnFAIL("Error scanning files in MergeManyToOne");
		recPtrArray[i] = (char *)malloc(recLen);
		memcpy(recPtrArray[i],recPtr,recLen);
		values.push_back(std::make_tuple(recPtrArray[i],i));
	}
	while (recCounter < numOfRecords) { // merge till all records are written out
		std::sort(values.begin(),values.end(),&CompareForMerge); // sort vector
		std::tuple<char *,int> first = values.front(); // get smallest/largest in vector
		int firstIndex = std::get<1>(first);
		dest->InsertRecord(std::get<0>(first),recLen,rid); // add it to output file
		recCounter++;
		status = scanners[firstIndex]->GetNext(rid,recPtr,recLen); // try to move pointer
		if (status == FAIL) return ReturnFAIL("Error scanning files in MergeManyToOne");
		else if (status == OK) { // if there are still records in that file
			memcpy(recPtrArray[firstIndex],recPtr,recLen);
			values.push_back(std::make_tuple(recPtrArray[firstIndex],firstIndex)); // add new record to vector
		}
		values.erase(values.begin()); // erase first
	}
	free(recPtr);
	for (int i=0;i<numSourceFiles; i++) {
		delete scanners[i];
	}
	for (int i=0;i<numSourceFiles;i++) {
		free(recPtrArray[i]);
	}
	delete scanners;
	delete recPtrArray;
	return OK;
}
Exemple #4
0
//-------------------------------------------------------------
// test
//-------------------------------------------------------------
Status test(int t)
{
	char		outfile[10];
	int		Rarray[] = { 0, 1, 0, 3, 4, 4, 4 };
	int		Sarray[] = { 1, 0, 2, 2, 2, 3, 0 };
	int 		R = Rarray[t-1];
	int 		S = Sarray[t-1];
	Status		s;

	sprintf(outfile,"test%d", t);

	// Perform sort-merge on R and S
	sortMerge	sm(files[R],NUM_COLS,attrType,attrSize,JOIN_COL,files[S],NUM_COLS,attrType,attrSize,JOIN_COL,outfile,SORTPGNUM,Ascending,s);
	if (s != OK)
	{
		cout << "Test " << t << " -- sortMerge failed" << endl;
		return s;
	}

	// Write merged results to stdout
	HeapFile*	outf = new HeapFile (outfile,s);
	if (s != OK)
	{
		cout << "Test " << t << " -- result file not created " << endl;
		return s;
	}
        Scan*	scan = outf->openScan(s);
	assert(s == OK);
	int len;
	RID	rid;
	char	rec[sizeof(struct _rec)*2];
	cout << endl;
	cout << "------------ Test " << t << " ---------------" << endl;
	for (s = scan->getNext(rid, rec, len); s == OK; s = scan->getNext(rid, rec, len)) 
	{
	  cout << (*((struct _rec*)&rec)).key << "\t" << (*((struct _rec*)&rec[8])).key << endl;
	}
	cout << "-------- Test " << t << " completed --------" << endl;
	delete scan;
	s=outf->deleteFile();
	if(s!=OK) MINIBASE_CHAIN_ERROR(JOINS,s);
	delete outf;
	return s;
}
Exemple #5
0
//-------------------------------------------------------------
// 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;
	}
}
Exemple #6
0
//--------------------------------------------------------------------
// JoinMethod::SortFile
// 
// Purpose :  Sorts a relation by an integer attribute. 
// Input   :  file - pointer to the HeapFile to be sorted.
//            len  - length of the records in the file. (assume fixed size).
//            offset - offset of the sort attribute from the beginning of the record.
// Method  :  We create a B+-Tree using that attribute as the key. Then
//            we scan the B+-Tree and insert the records into a new
//            HeapFile. he HeapFile guarantees that the order of 
//            insertion will be the same as the order of scan later.
// Return  :  The new sorted relation/HeapFile.
//-------------------------------------------------------------------- 
HeapFile* JoinMethod::SortHeapFile(HeapFile *file, int len, int offset) {

	Status s;

	Scan *scan;
	scan = file->OpenScan(s);
	if (s != OK) {
		std::cerr << "ERROR : cannot open scan on the heapfile to sort." << std::endl;
	}

	//
	// Scan the HeapFile S, create a new B+Tree and insert the records into B+Tree.
	// 

	BTreeFile *btree;
	btree = new BTreeFile (s, "BTree");

	char* recPtr = new char[len];
	int recLen = len;
	RecordID rid;

	char* recKey = new char[100];

	while (scan->GetNext(rid, recPtr, recLen) == OK)
	{
		int* valPtr = (int*)(recPtr+offset);
		int val = *valPtr;
		toString(val,recKey);
		btree->Insert(recKey, rid);
	}
	delete scan;
	delete [] recKey;
	//std::cout << "created B+ tree!" << std::endl;

	HeapFile *sorted = new HeapFile(NULL, s); // create a temp HeapFile
	if (s != OK)
	{
		std::cerr << "Cannot create new file for sortedS\n";
	}

	// Now scan the B+-Tree and insert the records into a 
	// new (sorted) HeapFile.

	BTreeFileScan* btreeScan = btree->OpenScan(NULL, NULL);

	//int key;
	char* keyPtr;
	while (btreeScan->GetNext(rid, keyPtr) == OK)
	{
		//std::cout << "scanning " << rid << " " << keyPtr << std::endl;

	    file->GetRecord (rid, recPtr, recLen);
	    sorted->InsertRecord (recPtr, recLen, rid);
	}
	btree->DestroyFile();

	delete btree;
	delete btreeScan;
	delete [] recPtr;

	return sorted;
}
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;
}
Exemple #8
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;
}
HeapFile* IndexNestedLoopJoin(JoinSpec specOfR, JoinSpec specOfS)
{
	Status status = OK;

	// Create a HeapFile for join results
	HeapFile* joinedFile = new HeapFile(NULL, status);
	if (OK != status)
	{
		cerr << "ERROR: cannot create a file for the joined relation.\n";
		return NULL;
	}

	int recLenR = specOfR.recLen;
	int recLenS = specOfS.recLen;
	int recLenJoined = recLenR + recLenS;

	char* recR = new char[recLenR];
	char* recS = new char[recLenS];
	char* recJoined = new char[recLenJoined];

	RecordID ridR, ridS, ridJoined;

	// Build the B+-tree index on the inner relation (S)
	Scan* scanS = specOfS.file->OpenScan(status);
	if (OK != status)
	{
		cerr << "ERROR: cannot open scan on the relation S heap file.\n";
		return NULL;
	}

	BTreeFile* bTree = new BTreeFile(status, "IJBT", ATTR_INT, sizeof(int));
	while (OK == scanS->GetNext(ridS, recS, recLenS))
	{
		bTree->Insert(recS + specOfS.offset, ridS);
	}
	delete scanS;

	// Iterate through the outer relation (R) and join
	Scan* scanR = specOfR.file->OpenScan(status);
	if (OK != status)
	{
		cerr << "ERROR: cannot open scan on the relation R heap file.\n";
		return NULL;
	}

	while (OK == scanR->GetNext(ridR, recR, recLenR))
	{
		int* joinArgR = (int*)&recR[specOfR.offset];

		BTreeFileScan* bTreeScan = (BTreeFileScan*)bTree->OpenSearchScan(joinArgR, joinArgR);
		int key;
		while (OK == bTreeScan->GetNext(ridS, &key))
		{
		    specOfS.file->GetRecord(ridS, recS, recLenS);

			MakeNewRecord(recJoined, recR, recS, recLenR, recLenS);
			joinedFile->InsertRecord(recJoined, recLenJoined, ridJoined);
		}
		delete bTreeScan;
	}

	// Release the allocated resources
	delete scanR;

	delete[] recR;
	delete[] recS;
	delete[] recJoined;

	delete bTree;

	return joinedFile;
}
//---------------------------------------------------------------
// TupleNestedLoop::Execute
//
// Input:   left  - The left relation to join. 
//          right - The right relation to join. 
// Output:  out   - The relation to hold the ouptut. 
// Return:  OK if join completed succesfully. FAIL otherwise. 
//          
// Purpose: Performs a nested loop join on relations left and right
//          a tuple a time. You can assume that left is the outer
//          relation and right is the inner relation. 
//---------------------------------------------------------------
Status TupleNestedLoops::Execute(JoinSpec& left, JoinSpec& right, JoinSpec& out) {
	JoinMethod::Execute(left, right, out);

	//	Create the temporary heapfile
	Status st;
	HeapFile *tmpHeap = new HeapFile(NULL, st);
	if (st != OK) {
		std::cerr << "Failed to create output heapfile." << std::endl;
		return FAIL;
	}

	//	Open scan on left relation
	Status leftStatus;
	Scan *leftScan = left.file->OpenScan(leftStatus);
	if (leftStatus != OK) {
		std::cerr << "Failed to open scan on left relation." << std::endl;
		return FAIL;
	}

	//	Loop over the left relation
	char *leftRec = new char[left.recLen];
	while (true) {
		RecordID leftRid;
		leftStatus = leftScan->GetNext(leftRid, leftRec, left.recLen);
		if (leftStatus == DONE) break;
		if (leftStatus != OK) return FAIL;

		//	The join attribute on left relation
		int *leftJoinValPtr = (int*)(leftRec + left.offset);

		//	Open scan on right relation
		Status rightStatus;
		Scan *rightScan = right.file->OpenScan(rightStatus);
		if (rightStatus != OK) {
			std::cerr << "Failed to open scan on right relation." << std::endl;
			return FAIL;
		}

		//	Loop over right relation
		char *rightRec = new char[right.recLen];
		while (true) {
			RecordID rightRid;
			rightStatus = rightScan->GetNext(rightRid, rightRec, right.recLen);
			if (rightStatus == DONE) break;
			if (rightStatus != OK) return FAIL;

			//	Compare join attribute
			int *rightJoinValPtr = (int*)(rightRec + right.offset);
			if (*leftJoinValPtr == *rightJoinValPtr) {
				//	Create the record and insert into tmpHeap...
				char *joinedRec = new char[out.recLen];
				MakeNewRecord(joinedRec, leftRec, rightRec, left, right);
				RecordID insertedRid;
				Status tmpStatus = tmpHeap->InsertRecord(joinedRec, out.recLen, insertedRid);

				if (tmpStatus != OK) {
					std::cerr << "Failed to insert tuple into output heapfile." << std::endl;
					return FAIL;
				}
				delete [] joinedRec;
			}
		}

		delete [] rightRec;
		delete rightScan;
	}

	out.file = tmpHeap;
	delete leftScan;
	delete [] leftRec;

	return OK;
}
HeapFile* BlockNestedLoopJoin(JoinSpec specOfR, JoinSpec specOfS, int B)
{
	Status status = OK;

	// Create a HeapFile for join results
	HeapFile* joinedFile = new HeapFile(NULL, status);
	if (OK != status)
	{
		cerr << "ERROR: cannot create a file for the joined relation.\n";
		return NULL;
	}

	int recLenR = specOfR.recLen;
	int recLenS = specOfS.recLen;
	int recLenJoined = recLenR + recLenS;

	char* recBlockR = new char[B]; // Allocate memory for the block
	char* recS = new char[recLenS];
	char* recJoined = new char[recLenJoined];

	RecordID ridR, ridS, ridJoined;

	Scan* scanR = specOfR.file->OpenScan(status);
	if (OK != status)
	{
		cerr << "ERROR: cannot open scan on the relation R heap file.\n";
		return NULL;
	}

	const int recordsPerBlock = B / recLenR;

	bool lastBlock = false;
	while (!lastBlock)
	{
		// Fill the block
		int i;
		for (i = 0; i < recordsPerBlock; i++)
		{
			if (OK != scanR->GetNext(ridR, recBlockR + i*recLenR, recLenR))
			{
				lastBlock = true;
				break;
			}
		}
		int lastRecordIndex = i;

		Scan* scanS = specOfS.file->OpenScan(status);
		if (OK != status)
		{
			cerr << "ERROR: cannot open scan on the relation S heap file.\n";
			return NULL;
		}

		while (OK == scanS->GetNext(ridS, recS, recLenS))
		{
			int* joinArgS = (int*)&recS[specOfS.offset];

			for (int currentRecordIndex = 0; currentRecordIndex < lastRecordIndex; currentRecordIndex++)
			{
				char* currentRecordPtr = recBlockR + (currentRecordIndex * recLenR);
				int* joinArgR = (int*)(currentRecordPtr + specOfR.offset);

				if (*joinArgR == *joinArgS)
				{
					MakeNewRecord(recJoined, currentRecordPtr, recS, recLenR, recLenS);
					joinedFile->InsertRecord(recJoined, recLenJoined, ridJoined);
				}
			}
		}

		delete scanS;
	}

	// Release the allocated resources
	delete scanR;

	delete[] recBlockR;
	delete[] recS;
	delete[] recJoined;

	return joinedFile;
}
Exemple #12
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;
}
Exemple #13
0
//---------------------------------------------------------------
// BlockNestedLoop::Execute
//
// Input:   left  - The left relation to join. 
//          right - The right relation to join. 
// Output:  out   - The relation to hold the ouptut. 
// Return:  OK if join completed succesfully. FAIL otherwise. 
//          
// Purpose: Performs a block nested loops join on the specified relations. 
// You can find a specification of this algorithm on page 455. You should 
// choose the smaller of the two relations to be the outer relation, but you 
// should make sure to concatenate the tuples in order <left, right> when 
// producing output. The block size can be specified in the constructor, 
// and is stored in the variable blockSize. 
//---------------------------------------------------------------
Status BlockNestedLoops::Execute(JoinSpec& left, JoinSpec& right, JoinSpec& out) {
	JoinMethod::Execute(left, right, out);
	
	Status s;
	HeapFile* tmpHeap = new HeapFile(NULL, s);
	if (s != OK) {
		std::cout << "Creating new Heap File Failed" << std::endl;
		return FAIL;
	}

	Scan * leftScan = left.file->OpenScan(s);
	if (s != OK) {
		std::cout << "Open scan left failed" << std::endl;
		return FAIL;
	}

	Scan * rightScan = right.file->OpenScan(s);
	if (s != OK) {
		std::cout << "Open scan left failed" << std::endl;
		return FAIL;
	}

	RecordID leftRid, rightRid, rightFirstRid, outRid;

	// array to hold the "block" in memory
	char* blockArray = new char[left.recLen * blockSize];
	int blockArraySize = 0; // size in case of half full block
	int* leftCurrRec = (int *)blockArray;
	int* leftRec = new int[left.numOfAttr];
	int* rightRec = new int[right.numOfAttr];
	int leftRecLen = left.recLen;
	int rightRecLen = right.recLen;

	char* newRec = new char[left.recLen + right.recLen];

	rightFirstRid = rightScan->currRid;

	Status st = OK;

	while (true) {
		// fill the block with as many records as possible
		if (blockArraySize < blockSize) {
			st = leftScan->GetNext(leftRid, (char *)leftRec, leftRecLen);
			if (st != DONE) {
				memcpy(blockArray + left.recLen * blockArraySize, leftRec, left.recLen);
				blockArraySize++;
				continue;
			}
		}

		// scan through the right, and scan the block in memory for joins
		while (rightScan->GetNext(rightRid, (char *)rightRec, rightRecLen) != DONE) {
			for (int j = 0; j < blockSize; j++) {
				if (j >= blockArraySize) {
					break;
				}
				leftCurrRec = (int *) (blockArray + left.recLen * j);
				if (leftCurrRec[left.joinAttr] == rightRec[right.joinAttr]) {
					MakeNewRecord(newRec, (char *)leftCurrRec, (char *)rightRec, left, right);
					tmpHeap->InsertRecord(newRec, left.recLen + right.recLen, outRid);
				}
			}
		}
		rightScan->MoveTo(rightFirstRid);
		blockArraySize = 0;

		if (st == DONE) {
			break;
		}
	}

	out.file = tmpHeap;
	//std::cout << "NUM BNL: " << tmpHeap->GetNumOfRecords() << std::endl;

	delete leftScan;
	delete rightScan;
	delete blockArray;
	delete leftRec;
	delete rightRec;
	delete newRec;

	return OK;
}
Exemple #14
0
//-------------------------------------------------------------------
// Sort::PassZero
//
// Input   : None
// Output  : Number of temp files generated after this pass
// Return  : OK if Pass 0 succeeds, FAIL otherwise
//-------------------------------------------------------------------
Status Sort::PassZero(int &numTempFiles) {
	// Get input file
	Status status;
	HeapFile inputFile(_inFile, status);
	if (status != OK) return ReturnFAIL("Opening input file in PassZero function failed.");
	int numRecords = inputFile.GetNumOfRecords(); 
	int recCounter = 0, globalRecCounter = 0;

	// Allocate memory
	int areaSize = MINIBASE_PAGESIZE * _numBufPages;
	char *area = (char *)malloc(areaSize);
	char *areaPtr = area;
	RecordID rid; char *recPtr = (char *)malloc(_recLength); int recLen = _recLength;
	int numRecForSort = std::min(areaSize/_recLength,numRecords); // number of rec in sorting area at once

	// Open Scan
	Scan *scan = inputFile.OpenScan(status); 
	if (status != OK) return ReturnFAIL("Opening scan in PassZero function failed.");
	
	// Sort
	passZeroRuns = 0;
	if (areaSize >= _recLength) { // can fit at least one record
		while (scan->GetNext(rid,recPtr,recLen) == OK) {
			recCounter++; globalRecCounter++;
			// add to memory
			if (memcpy(areaPtr,recPtr,recLen) != areaPtr) 
				return ReturnFAIL("Reading records to memory in PassZero function failed.");
			areaPtr += recLen;
			areaSize -= recLen;
			if (areaSize < _recLength || globalRecCounter == numRecords) { // can't fit another rec or all recs have been added
				// sort
				switch (_sortType) {
					case attrInteger:
						std::qsort(area,recCounter,_recLength,CompareInt); 
						break;
					case attrString:
						std::qsort(area,recCounter,_recLength,CompareString); 
					default:
						break;
				}
				// write out
				char *fileName = CreateTempFilename(_outFile,0,passZeroRuns);
				passZeroRuns++;
				HeapFile *tempFile =  new HeapFile(fileName,status); 
				if (status != OK) return ReturnFAIL("Opening temp file in PassZero function failed.");
				areaPtr = area;
				while (recCounter > 0) { // insert
					tempFile->InsertRecord(areaPtr,_recLength,rid);
					recCounter--;
					areaPtr += _recLength;
				}
				numTempFiles++;
				areaSize = MINIBASE_PAGESIZE * _numBufPages;
				areaPtr = area; // reset
				delete fileName;
				delete tempFile; 
			}
		}
	}

	free(area);
	free(recPtr);
	delete scan;
	return OK;
}