/* We have a const problem with the method. We call GetPage from STORM which is not const!!! */
t_rc REM_RecordFileHandle::ReadRecord(const REM_RecordID &rid, REM_RecordHandle &rh)	{
    /* Check is file is open. */
    if (!this->isOpen) {
        return REM_FHCLOSED;
    }
    t_rc rc;

    /* Get pageID and slot number to find the record. */
    int pageID, slot;

    rc = rid.GetPageID(pageID);
    if (rc != OK) {
        return rc;
    }

    rc = rid.GetSlot(slot);
    if (rc != OK) {
        return rc;
    }

    /* Get the STORM page that contains the record we need. */
    STORM_PageHandle pageHandle;

    rc = this->sfh.GetPage(pageID, pageHandle);
    if (rc != OK) {
        return rc;
    }

    /* Check if REM Record Handler has data. If it doesn't, allocate the needed space. */
    if (rh.pData == NULL) {
        rh.pData = new char[this->remFileHeader.recordSize];
    }
    else {
        delete rh.pData;
        rh.pData = new char[this->remFileHeader.recordSize];
    }

    char *pData;
    REM_PageHeader pageHeader;

    pageHandle.GetDataPtr(&pData);

    /* Check if slot number is not correct. */
    memcpy(&pageHeader, pData, REM_PAGEHEADER_SIZE);
    if (slot > pageHeader.nRecords) {
        return REM_INVALIDRID;
    }

    /* Find the record we want and copy the data to the record handler.  */
    memcpy(rh.pData, &pData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], this->remFileHeader.recordSize);

    /* Add the recordID to the record handler. */
    rh.rid = rid;

    /* Make Record Handler valid. */
    rh.isValid = true;

    return (OK);
}
t_rc REM_RecordFileHandle::UpdateRecord(const REM_RecordHandle &rh)	{
    /* Check is file is open. */
    if (!this->isOpen) {
        return REM_FHCLOSED;
    }
    t_rc rc;

    /* Exctract RID and get pageID and slot numbers. */
    REM_RecordID rid;
    int pageID, slot;

    rc = rh.GetRecordID(rid);
    if (rc != OK) {
        return rc;
    }

    rc = rid.GetPageID(pageID);
    if (rc != OK) {
        return rc;
    }
    rc = rid.GetSlot(slot);
    if (rc != OK) {
        return rc;
    }

    /* Get the record and a pointer to the data inside. */
    STORM_PageHandle pageHandle;
    char *pData;

    rc = this->sfh.GetPage(pageID, pageHandle);
    if (rc != OK) {
        return rc;
    }

    rc = pageHandle.GetDataPtr(&pData);
    if (rc != OK) {
        return rc;
    }

    /* Copy the new data. */
    memcpy(&pData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], rh.pData, this->remFileHeader.recordSize);

    /* Mark the page as dirty because we modified it */
    rc = this->sfh.MarkPageDirty(pageID);
    if (rc != OK) {
        return rc;
    }
    /* Unpin the page */
    rc = this->sfh.UnpinPage(pageID);
    if (rc != OK) {
        return rc;
    }

    return (OK);
}
t_rc REM_RecordFileHandle::ReadRecord(const REM_RecordID &rid, REM_RecordHandle &rh)	{
                                                                                        // If file is open.  
	if (!this->is_open) { return REM_FHCLOSED; }
	t_rc rc;

                                                                                        // Get pageID and slot number. 
	int page_id, slot;
	
	rc = rid.GetPageID( page_id);
	if (rc != OK) { return rc; }
	
	rc = rid.GetSlot(slot);
	if (rc != OK) { return rc; }
	
                                                                                        // We create a stromPageHandle to handle the record with specify pageID and slot number. 
	STORM_PageHandle page_handle;
	
	rc = this->sfh.GetPage( page_id, page_handle);
	if (rc != OK) { return rc; }
	
                                                                                        // If it doesn't have data allocate the needed space. 
	if (rh.pData == NULL) {
		rh.pData = (char*) malloc(this->rem_file_header.record_size);
	}
	else {
		delete rh.pData;
		rh.pData = (char*) malloc(this->rem_file_header.record_size);
	}
	
	char *pData;
	REM_PageHeader pageHeader;                                                      // We create a page header to store info about the records
	
	page_handle.GetDataPtr(&pData);
	
                                                                                        // Check slot number
	memcpy(&pageHeader, pData, REM_PAGEHEADER_SIZE);	
	if (slot > pageHeader.n_records) { return REM_INVALIDRID; }
                                                                                        //correct slot 
                                                                                        // Find the record and copy the data to the record handler.
	memcpy(rh.pData, &pData[REM_PAGEHEADER_SIZE+((slot-1)*this->rem_file_header.record_size)], this->rem_file_header.record_size);
	
                                                                                        // Add the recordID to the record handler. 
	rh.rid = rid;
	
                                                                                        // Make Record Handler valid. 
	rh.is_valid = true;
	
	return (OK);
}
t_rc REM_RecordFileHandle::ReadRecord (const REM_RecordID &rid, REM_RecordHandle &rh) const {

    //ΥΠΟΘΕΣΗ: Το rid ΠΑΝΤΑ αντιστοιχεί σε ΣΩΣΤΟ record identifier.
    int pageID;
    rid.GetPageID(pageID);
    STORM_PageHandle ph;
    t_rc rc = const_cast<REM_RecordFileHandle*>(this)->fh.GetPage(pageID,ph);
    if(rc!=OK) return rc;
    int slot;
    rid.GetSlot(slot);
    rc = rh.Initialize(ph,slot,this->headerPage.recordSize);
    if(rc!=OK) return rc;

    return OK;
}
//Insert the exact field of each record into the indexing
t_rc SSQLM_Manager::InsertIndexEntries(REM_RecordFileHandle &rfh, int attrOffset/*, INXM_IndexHandle ih*/) {
	t_rc rc;
	int numReservedPages = rfh.sfh.GetNumReservedPages();
	int numberofSlots = rfh.rfsh.nrecords;

	REM_RecordID rid;
	REM_RecordHandle rh;
	int slot = 0;
	int pageID = 2;
	char *data;

	if(numReservedPages < 2)
		return SSQLM_NOENTRYTOINDEX;

	if(numberofSlots == 0)
		return SSQLM_NOENTRYTOINDEX;

	for( ; pageID <= numReservedPages; pageID++) {
		for( ; slot <= rfh.rfsh.recordsPerPage; slot++) {
			if(slot >(rfh.rfsh.nrecords - 1))
				return OK;

			rc = rid.SetPageID(pageID);
			if(rc != OK)
				return rc;

			rc = rid.SetSlot(slot);
			if(rc != OK)
				return rc;

			rc = rfh.ReadRecord(rid, rh);
			if(rc != OK)
				return rc;

			rc = rh.GetData(data);
			if(rc != OK)
				return rc;

			/*rc = ih.InsertEntry(data[attrOffset], rid);
			if(rc != OK)
				return rc;
*/
		}
	}
}
t_rc INXM_IndexHandle::WriteData(STORM_PageHandle pageHandle, const REM_RecordID &rid, int &slot) {
	t_rc rc;
	
	INXM_Data *inxmData = new INXM_Data();
	
	rid.GetPageID(inxmData->pageID);
	rid.GetSlot(inxmData->slot);
	
	char *leafPageData;
	
	rc = pageHandle.GetDataPtr(&leafPageData);
	if (rc != OK) { return rc; }
	
	/* Read leaf header. */
	INXM_InitPageHeader pageHeader;
	
	memcpy(&pageHeader, leafPageData, INXM_INITPAGEHEADER_SIZE);
	
	/* Write data to correct place. */
	memcpy(&leafPageData[INXM_INITPAGEHEADER_SIZE+pageHeader.nItems*INXM_DATA_SIZE], inxmData, INXM_DATA_SIZE);
	
	/* Update page header. */
	slot = pageHeader.nItems;
	pageHeader.nItems++;
	
	memcpy(leafPageData, &pageHeader, INXM_INITPAGEHEADER_SIZE);
	
	int pageID;
	rc = pageHandle.GetPageID(pageID);
	if (rc != OK) { return rc; }
	
	/* Mark the page as dirty because we modified it */
	rc = this->sfh.MarkPageDirty(pageID);
	if (rc != OK) { return rc; }
	
	rc = this->sfh.FlushPage(pageID);
	if (rc != OK) { return rc; }
	
	/* Unpin the page */
	rc = this->sfh.UnpinPage (pageID);
	if (rc != OK) { return rc; }
	
	return(OK);
}
t_rc REM_RecordFileHandle::UpdateRecord(const REM_RecordHandle &rh)	{
                                                                                        //If file is open. 
	if (!this->is_open) { return REM_FHCLOSED; }
	t_rc rc;
	
                                                                                        // get pageID and slot numbers.
	REM_RecordID rid;
	int page_id, slot;
	
	rc = rh.GetRecordID(rid);
	if (rc != OK) { return rc; }
	
	rc = rid.GetPageID( page_id);
	if (rc != OK) { return rc; }
	rc = rid.GetSlot(slot);
	if (rc != OK) { return rc; }
	
                                                                                        // Get the record and a pointer to the data
	STORM_PageHandle page_handle;
	char *pData;
	
	rc = this->sfh.GetPage( page_id, page_handle);
	if (rc != OK) { return rc; }
	
	rc = page_handle.GetDataPtr(&pData);
	if (rc != OK) { return rc; }
	
                                                                                        // Copy new data. 
	memcpy(&pData[REM_PAGEHEADER_SIZE+((slot-1)*this->rem_file_header.record_size)], rh.pData, this->rem_file_header.record_size);
	
                                                                                        // Mark last page as dirty 
	rc = this->sfh.MarkPageDirty( page_id);
	if (rc != OK) { return rc; }
                                                                                        // Unpin page 
	rc = this->sfh.UnpinPage( page_id);
	if (rc != OK) { return rc; }
	
	return (OK);
}
t_rc REM_RecordFileHandle::DeleteRecord (const REM_RecordID &rid) {

    int pageID;
    rc = rid.GetPageID(pageID); //pairneis to pageID
    if(rc!=OK) return rc;
    rc = fh.GetPage(pageID, ph);//dineis to pageHandle sto sigekrimeno page
    if(rc!=OK) return rc;
    char *data;
    rc = ph.GetDataPtr(&data); //dedomena tou page
    if(rc!=OK) return rc;

    REM_RecordHandle::RecordHeader recordHeader;

    memcpy(&recordHeader, data, sizeof(REM_RecordHandle::RecordHeader)); //pairneis to recordheader kai kaneis enimeroseis
    int slot;
    rid.GetSlot(slot);
    recordHeader.bitmap.set(slot,0);
    //recordHeader.bitmap[slot] = false;
    recordHeader.reservedRecords--;
    memcpy(data,&recordHeader,sizeof(REM_RecordHandle::RecordHeader)); //eggrafw ta dedomena pisw ston disko.
    rc = fh.MarkPageDirty(pageID);
    if(rc!=OK) return rc;
    rc = fh.UnpinPage(pageID);
    if(rc!=OK) return rc;
    //update page header
    if(recordHeader.reservedRecords == headerPage.recordsPerPage-1) { //δεν είναι πλέον full η σελίδα.
        rc = updatePageHeader(pageID, false);
        if(rc!=OK) return rc;
    }
    if(recordHeader.reservedRecords == 0) { //κάνε release το page
        rc = fh.ReleasePage(pageID);
        if(rc!=OK) return rc;
    }

    return OK;
}
t_rc SSQLM_Manager::CompareAttributes(t_attrInfo comparisonAttribute, t_attrInfo convertionAttribute, t_compOp compOp, vector<char *> &pData) {
	t_rc rc;
	REM_RecordFileHandle rfhCompare;
	REM_RecordFileHandle rfhConvertion;
	REM_RecordHandle rhCompare;
	REM_RecordHandle rhConvertion;
	REM_RecordID ridCompare;
	REM_RecordID ridConvertion;
	if(comparisonAttribute.indexNo != -1) {
		/*INXM_IndexHandle indesHandle;
		INXM_IndexScan indexScan;
		

		std::stringstream ss;
		ss << comparisonAttribute.relName << "." << comparisonAttribute.indexNo;
		
		rc = inxm.OpenIndex(ss.str(), comparisonAttribute.indexNo, indexHandle);
		if(rc != OK)
			return rc;

		rc = indexScan.OpenIndexScan(indexHandle, compOp, 

*/

	}else {
		if(comparisonAttribute.relName != convertionAttribute.relName) {
			rc = rfm.OpenRecordFile(comparisonAttribute.relName, rfhCompare);
			if(rc != OK)
				return rc;
			rc = rfm.OpenRecordFile(convertionAttribute.relName, rfhConvertion);
			if(rc != OK)
				return rc;

			REM_RecordFileScan fileScan;
		
			int slotCompare = 0;
			int pageIDCompare = 2;
			int slotConvertion = 0;
			int pageIDConvertion = 2;

			for( ;pageIDCompare <= rfhCompare.sfh.GetNumReservedPages(); pageIDCompare++) {
				for( ;slotCompare <= rfhCompare.rfsh.nrecords; slotCompare++) {
					rc = ridCompare.SetPageID(pageIDCompare);
					if(rc != OK)
						return rc;
					
					rc = ridCompare.SetSlot(slotCompare);
					if(rc != OK)
						return rc;

					rc = rfhCompare.ReadRecord(ridCompare, rhCompare);
					if(rc != OK)
						return rc;

					char *dataCompare;
					rc = rhCompare.GetData(dataCompare);
					if(rc != OK)
						return rc;

					rc = fileScan.OpenRecordScan(rfhConvertion, convertionAttribute.attrType, convertionAttribute.attrLength, convertionAttribute.offset, compOp, dataCompare);
					if(rc != OK)
						return rc;

					char *dataConvertion;
					while(fileScan.GetNextRecord(rhConvertion) == OK){
						rc = rhConvertion.GetData(dataConvertion);
						if(rc != OK)
							return rc;

						pData.push_back(dataCompare);
						pData.push_back(dataConvertion);
					}
					fileScan.CloseRecordScan();
				}
			}
		}
	}
	return OK;
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid) {

    //Edit
    if(!open) return REM_HANDLE_IS_CLOSED;

    int numReservedPages=fh.GetNumReservedPages(); //πλήθος των reserved pages
    int i;
    this->pData=pData; //δεδομένα που θα βάλουμε στην εγγραφή.
    int pageID = 0; //ID της σελίδας όπου θα βάλουμε δεδομένα.
    char *pageData; //δεδομένα της σελίδας όπου θα βάλουμε την εγγραφή.
    for(i=0; i<numReservedPages; i++)
    {

        rc=	fh.GetNextPage(pageID,ph);
        if(rc!=OK) return rc;

        rc = ph.GetPageID(pageID);
        if(rc!=OK) return rc;

        if(headerPage.bitmap.test(pageID) == false) {
            //if(headerPage.bitmap[pageID] == false)
            break;
        }
        else {
            rc = fh.UnpinPage(pageID);
            if(rc!=OK) return rc;
        }
    }
    //βρήκαμε σε ποια σελίδα θα μπεί η εγγραφή.
    if(i==numReservedPages) //πρέπει να κάνουμε νέο page reserve.
    {
        if(i == 101) return REM_PAGES_ARE_FULL;
        rc = fh.ReservePage(ph);
        if(rc!=OK) return rc;
        rc = ph.GetPageID(pageID);
        if(rc!=OK) return rc;
        rc = ph.GetDataPtr(&pageData);
        if(rc!=OK) return rc;
        //κάνουμε αρχικοποίηση το record header
        rh.recordHeader.reservedRecords=0;
        for(int i=0; i<headerPage.recordsPerPage; i++)
            //rh.recordHeader.bitmap[i] = false;
            rh.recordHeader.bitmap.set(i,0);

    }
    else { //δεν κάνουμε reserve νεo page, υπάρχει ήδη, διαβάζουμε το record header.

        rc = fh.GetPage(pageID,ph);
        if(rc!=OK) return rc;
        rc = ph.GetDataPtr(&pageData);
        if(rc!=OK) return rc;
        memcpy(&rh.recordHeader, pageData, sizeof(REM_RecordHandle::RecordHeader));

    }

    //mexri tora vrikame pageID. Πάμε να βρούμε το slot όπου θα μπούν τα δεδομένα.
    int slot = -1;
    for(i=0; i<headerPage.recordsPerPage; i++) {
        //10: bitmap size
        //if(rh.recordHeader.bitmap[i] == false)
        if(rh.recordHeader.bitmap.test(i) == false)
        {
            slot = i;
            break;
        }
    }

    //βρήκαμε page και slot όπου θα βάλουμε τα δεδομένα.

    //ενημέρωση του record handle για την εγγραφή όπου θα μπούν τα δεδομένα.
    rh.Initialize(ph, slot, this->headerPage.recordSize);
    //εγγραφή των δεδομένων στο record.
    UpdateRecord(rh);
    //ενημέρωση του recordHeader
    rh.recordHeader.reservedRecords++;
    rh.recordHeader.bitmap.set(slot,1);
    //rh.recordHeader.bitmap[slot] = true;
    //εγγραφή του recordHeader στη σελίδα.
    memcpy(pageData, &rh.recordHeader,sizeof(REM_RecordHandle::RecordHeader));
    //ενημέρωση της σελίδας με τις αλλαγές.
    rc = fh.MarkPageDirty(pageID);
    if(rc!=OK) return rc;
    rc = fh.UnpinPage(pageID);
    if(rc!=OK) return rc;
    //ενημέρωση του page header εάν χρειάζεται
    if(rh.recordHeader.reservedRecords == headerPage.recordsPerPage) { //είναι full η σελίδα..
        rc = updatePageHeader(pageID, true);
        if(rc!=OK) return rc;
    }
    //ενημέρωση του record id

    rid.SetPageID(pageID);
    rid.SetSlot(slot);
    return OK;
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid)	{
                                                                                         // If file is open.  
	if (!this->is_open) { return REM_FHCLOSED; }
	t_rc rc;
	
                                                                                        // Find an empty page to write the new record. 
	STORM_PageHandle target_page;
	REM_PageHeader page_header = {0};                                               // We store 0 ,we haven't any record yet.
	char *page_data;
	
                                                                                        //If there is no free space on this page we reserve a new page. 
	if (this->rem_file_header.is_last_page_full) {
		
		rc = sfh.ReservePage(target_page);                                      // Reserve the new page.
		if (rc != OK) { return rc; }
		
                                                                                        // We mark the last page as not full. 
		this->rem_file_header.is_last_page_full = false;
		
                                                                                        // Update file header and mark it as dirty. 
		memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);

		rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
		
                                                                                         // Get a pointer to the data of the new page to write data. 	
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }
				
	}
                                                                                	// If we have free space in a page, we just get the page. 
	else {
		rc = this->sfh.GetLastPage(target_page);
		if (rc != OK) { return rc; }
		
                                                                                        // Get a pointer to the data of the the page to read the REM Page Header. 
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }
		
		memcpy(&page_header, page_data, REM_PAGEHEADER_SIZE);
                
		
	}
	
                                                                                        //We calculate the corect offset(page header size + the offset) of each record there and we place the data 

	memcpy(&page_data[REM_PAGEHEADER_SIZE+(page_header.n_records*this->rem_file_header.record_size)], pData, this->rem_file_header.record_size);
	page_header.n_records+=1;
        this->rem_file_header.n_records+=1;
        memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
        rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
                                                                                        // Increase the number of records in the page header. This number is also the slot number of the record. 
	int slot_num = page_header.n_records; 
                                                                                	// Declare page number we are currently working on. 
	int page_num;
	rc = target_page.GetPageID(page_num);
	if (rc != OK) { return rc; }
	
                                                                                        //If page is full. 
	if (page_header.n_records == this->rem_file_header.records_per_page) {
		this->rem_file_header.is_last_page_full = true;
		
                                                                                        // Update the file header and mark as dirty. 
		memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
		
		rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
		
                                                                                        // Get a pointer to the data of the new page to write the new data. 	
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }		
	}
	
                                                                                        // Write the new REM Page Header. 
	memcpy(page_data, &page_header, REM_PAGEHEADER_SIZE);
	
	
                                                                                        // Mark the page as dirty because we modified it 
	rc = this->sfh.MarkPageDirty(page_num);
	if (rc != OK) { return rc; }
	
	this->sfh.FlushPage(page_num);                                                  // We are flushing pages
	
                                                                                        // Unpin the page 
	rc = this->sfh.UnpinPage (page_num);
	if (rc != OK) { return rc; }
	
                                                                                        // Set the passed RID's page and slot number 
	rc = rid.SetPageID(page_num);
	if (rc != OK) { return rc; }
	rc = rid.SetSlot(slot_num);
	if (rc != OK) { return rc; }

		
	return (OK);
}
t_rc REM_RecordFileHandle::DeleteRecord(const REM_RecordID &rid)	{
                                                                                        // If file is open.  
	if (!this->is_open) { return REM_FHCLOSED; }
	t_rc rc;
	
                                                                                        // Read page and slot we want to delete. 
	int page_id, slot;
	
	rc = rid.GetPageID(page_id);
	if (rc != OK) { return rc; }
	
	rc = rid.GetSlot(slot);
	if (rc != OK) { return rc; }
	
                                                                                	// Get the page. 
	STORM_PageHandle wanted_page_handle;
	rc = this->sfh.GetPage(page_id, wanted_page_handle);
	if (rc != OK) { return rc; }
	
                                                                                	// Get wanted page header. 
	char *wantedData;
	REM_PageHeader wanted_page_header;
	
	rc = wanted_page_handle.GetDataPtr(&wantedData);
	if (rc != OK) { return rc; }
	
	memcpy(&wanted_page_header, wantedData, REM_PAGEHEADER_SIZE);
	if (slot > wanted_page_header.n_records) { return REM_INVALIDRID; }
	
	STORM_PageHandle last_page_handle;
	int last_page_id;
	
	rc = this->sfh.GetLastPage(last_page_handle);
	if (rc != OK) { return rc; }
	
	rc = last_page_handle.GetPageID(last_page_id);
	if (rc != OK) { return rc; }
	
                                                                                	// Determine if we need to retrieve an other page to replace the record. 
	if (last_page_id == page_id){
		
                                                                                        // Determine if our record is the last one
		if (wanted_page_header.n_records == slot) {
			
                                                                                        // Check if we need to release the page. 
			if (wanted_page_header.n_records == 1) {
				rc = this->sfh.ReleasePage(page_id);
				if (rc != OK) { return rc; }
				
                                                                                	// We change the lastPageID in REM File Header
				this->rem_file_header.is_last_page_full = true;
                                                                                	// Copy new file header /
				memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
				/* Mark REM File Header frame as dirty */
				rc = this->sfh.MarkPageDirty(this->page_num_file_header);
				if (rc != OK) { return rc; }				
			}
			else {
                                                                                        // If our record is the last one in the row but more data exist, we just decrease the number of records of the page
				wanted_page_header.n_records--;
				
                                                                                        // Copy header back to save changes
				memcpy(wantedData, &wanted_page_header, REM_PAGEHEADER_SIZE);				
			}			
		}
		else {
                                                                                        // Copy the last record of this page (last page) in the position of the record we want to delete. */
			memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->rem_file_header.record_size)], 
				   &wantedData[REM_PAGEHEADER_SIZE+((wanted_page_header.n_records-1)*this->rem_file_header.record_size)], 
				   this->rem_file_header.record_size);			
			
                                                                                        // Decrease the number of records the pages has. 
			wanted_page_header.n_records--;

                                                                                        // Copy header back to save changes
			memcpy(wantedData, &wanted_page_header, REM_PAGEHEADER_SIZE);
		}
	}
	else {
                                                                                        // Get last record from last page to replace the record. 
		char *lastData;
		
		rc = last_page_handle.GetDataPtr(&lastData);
		if (rc != OK) { return rc; }
		
                                                                                        // Get last page header. 
		REM_PageHeader lastPageHeader;
		
		memcpy(&lastPageHeader, lastData, REM_PAGEHEADER_SIZE);		
		
                                                                                        // Copy data between the two pages 
		memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->rem_file_header.record_size)], 
			   &lastData[REM_PAGEHEADER_SIZE+((lastPageHeader.n_records-1)*this->rem_file_header.record_size)], 
			   this->rem_file_header.record_size);
		
                                                                                        // If last page has no more records
		if (lastPageHeader.n_records == 1) {
                                                                                        // If we copied the last record we can  release the page
			rc = this->sfh.ReleasePage(last_page_id);
			if (rc != OK) { return rc; }
                                
                                                                                        // We change the lastPageID in REM File Header to save the changes
			this->rem_file_header.is_last_page_full = true;
                                                                                        // Copy new file header 
			memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
                                                                                        // Mark REM File Header as dirty to flush it
			rc = this->sfh.MarkPageDirty(this->page_num_file_header);
			if (rc != OK) { return rc; }
		}
		else {
                                                                                         //Decrease last page record number in its page header		
			lastPageHeader.n_records--;
			
			memcpy(lastData, &lastPageHeader, REM_PAGEHEADER_SIZE);
			
                                                                                        // Mark last page as dirty 			
			rc = sfh.MarkPageDirty(last_page_id);
			if (rc != OK) { return rc; }
			
                                                                                        // Unpin last page.
			rc = sfh.UnpinPage (last_page_id);
			if (rc != OK) { return rc; }
		}
	}

	
                                                                                        // Mark the page as dirty because we modified it 
	rc = sfh.MarkPageDirty(page_id);
	if (rc != OK) { return rc; }
                                                                                        // Unpin page 
	rc = sfh.UnpinPage (page_id);
	if (rc != OK) { return rc; }
	
	sfh.FlushPage(page_id);
	
	
	return (OK);
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid)	{
    /* Check is file is open. */
    if (!this->isOpen) {
        return REM_FHCLOSED;
    }
    t_rc rc;

    /* Find an empty page to write the new record. */
    STORM_PageHandle targetPage;
    REM_PageHeader pageHeader = {0}; // The default number of records in a page is 0.
    char *pageData;

    /*	If there is no free space (lastPageID=-1) then we reserve a new page. */
    if (this->remFileHeader.isLastPageFull) {

        rc = sfh.ReservePage(targetPage);	// Reserve the new page.
        if (rc != OK) {
            return rc;
        }

        /* We mark the last page as not full. */
        this->remFileHeader.isLastPageFull = false;

        /* We update the file header and mark as dirty. */
        memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);

        rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the new page to write the new data. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }

    }
    /* If we have free space in a page, we just get the page. */
    else {
        rc = this->sfh.GetLastPage(targetPage);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the the page to read the REM Page Header. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }

        memcpy(&pageHeader, pageData, REM_PAGEHEADER_SIZE);

    }

    /* We write the data to the proper position. The new record offset must be the page header size + the offset of each record there
     * is inside the page. We always place the new record at the end of the page.
     */
    memcpy(&pageData[REM_PAGEHEADER_SIZE+(pageHeader.nRecords*this->remFileHeader.recordSize)], pData, this->remFileHeader.recordSize);

    /* Increase the number of records in the page header. This number is also the slot number of the record. */
    int slotNum = ++pageHeader.nRecords;
    /* Declare page number, which is the pageID we are currently working on. */
    int pageNum;
    rc = targetPage.GetPageID(pageNum);
    if (rc != OK) {
        return rc;
    }

    /* Check if page is full. */
    if (pageHeader.nRecords == this->remFileHeader.recordsPerPage) {
        this->remFileHeader.isLastPageFull = true;

        /* We update the file header and mark as dirty. */
        memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);

        rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the new page to write the new data. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }
    }

    /* Write the new REM Page Header. */
    memcpy(pageData, &pageHeader, REM_PAGEHEADER_SIZE);


    /* Mark the page as dirty because we modified it */
    rc = this->sfh.MarkPageDirty(pageNum);
    if (rc != OK) {
        return rc;
    }

    this->sfh.FlushPage(pageNum);	// We should reconsider when we are flushing pages!!!

    /* Unpin the page */
    rc = this->sfh.UnpinPage (pageNum);
    if (rc != OK) {
        return rc;
    }

    /* Set the passed RID's page number and slot number */
    rc = rid.SetPageID(pageNum);
    if (rc != OK) {
        return rc;
    }
    rc = rid.SetSlot(slotNum);
    if (rc != OK) {
        return rc;
    }

    /* Successfuly inserted record */
    return (OK);
}
t_rc REM_RecordFileHandle::DeleteRecord(const REM_RecordID &rid)	{
    /* Check is file is open. */
    if (!this->isOpen) {
        return REM_FHCLOSED;
    }
    t_rc rc;

    /* Read page and slot we want to delete. */
    int pageID, slot;

    rc = rid.GetPageID(pageID);
    if (rc != OK) {
        return rc;
    }

    rc = rid.GetSlot(slot);
    if (rc != OK) {
        return rc;
    }

    /* Get wanted page. */
    STORM_PageHandle wantedPageHandle;
    rc = this->sfh.GetPage(pageID, wantedPageHandle);
    if (rc != OK) {
        return rc;
    }

    /* Get the wanted page header. */
    char *wantedData;
    REM_PageHeader wantedPageHeader;

    rc = wantedPageHandle.GetDataPtr(&wantedData);
    if (rc != OK) {
        return rc;
    }

    memcpy(&wantedPageHeader, wantedData, REM_PAGEHEADER_SIZE);
    if (slot > wantedPageHeader.nRecords) {
        return REM_INVALIDRID;
    }

    STORM_PageHandle lastPageHandle;
    int lastPageID;

    rc = this->sfh.GetLastPage(lastPageHandle);
    if (rc != OK) {
        return rc;
    }

    rc = lastPageHandle.GetPageID(lastPageID);
    if (rc != OK) {
        return rc;
    }

    /* Determine if we need to retrive an other page to replace the record. */
    if (lastPageID == pageID) {

        /* Determine if our record is the last. */
        if (wantedPageHeader.nRecords == slot) {

            /* Check if we need to release the page. */
            if (wantedPageHeader.nRecords == 1) {
                rc = this->sfh.ReleasePage(pageID);
                if (rc != OK) {
                    return rc;
                }

                /* We must change the lastPageID in REM File Header. */
                this->remFileHeader.isLastPageFull = true;
                /* Copy new file header at memory */
                memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);
                /* Mark REM File Header frame as dirty */
                rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
                if (rc != OK) {
                    return rc;
                }
            }
            else {
                /* If our record is the last one in the row but more data exist, we just decrease the number of records the page has. */
                wantedPageHeader.nRecords--;

                /* Copy header back. */
                memcpy(wantedData, &wantedPageHeader, REM_PAGEHEADER_SIZE);
            }
        }
        else {
            /* Copy the last record of this page (last page) in the position of the record we want to erase. */
            memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)],
                   &wantedData[REM_PAGEHEADER_SIZE+((wantedPageHeader.nRecords-1)*this->remFileHeader.recordSize)],
                   this->remFileHeader.recordSize);

            /* Decrease the number of records the pages has. */
            wantedPageHeader.nRecords--;

            /* Copy header back. */
            memcpy(wantedData, &wantedPageHeader, REM_PAGEHEADER_SIZE);
        }
    }
    else {
        /* Get last record from last page to replace the asked record. */
        char *lastData;

        rc = lastPageHandle.GetDataPtr(&lastData);
        if (rc != OK) {
            return rc;
        }

        /* Get last's page header. */
        REM_PageHeader lastPageHeader;

        memcpy(&lastPageHeader, lastData, REM_PAGEHEADER_SIZE);

        /* Copy the data between the two pages */
        memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)],
               &lastData[REM_PAGEHEADER_SIZE+((lastPageHeader.nRecords-1)*this->remFileHeader.recordSize)],
               this->remFileHeader.recordSize);

        /* Check if last page has no more records. */
        if (lastPageHeader.nRecords == 1) {
            /* If we copied the last record we can safely release the last page. */
            rc = this->sfh.ReleasePage(lastPageID);
            if (rc != OK) {
                return rc;
            }

            /* We must change the lastPageID in REM File Header. */
            this->remFileHeader.isLastPageFull = true;
            /* Copy new file header at memory */
            memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);
            /* Mark REM File Header frame as dirty */
            rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
            if (rc != OK) {
                return rc;
            }
        }
        else {
            /* Decrease last page record number in its page header. */
            lastPageHeader.nRecords--;

            memcpy(lastData, &lastPageHeader, REM_PAGEHEADER_SIZE);

            /* Mark last page as dirty due to last record removal. */
            rc = sfh.MarkPageDirty(lastPageID);
            if (rc != OK) {
                return rc;
            }

            /* Unpin last page. */
            rc = sfh.UnpinPage (lastPageID);
            if (rc != OK) {
                return rc;
            }
        }
    }


    /* Mark the page as dirty because we modified it */
    rc = sfh.MarkPageDirty(pageID);
    if (rc != OK) {
        return rc;
    }
    /* Unpin the page */
    rc = sfh.UnpinPage (pageID);
    if (rc != OK) {
        return rc;
    }

    sfh.FlushPage(pageID);

    /* Record successfully deleted */
    return (OK);
}
Exemple #15
0
//Εκτελει υπο-εντολη του DML που ελεγχει τις συνθηκες στο κομματι WHERE
t_rc SSQLM::executeWhere(string tableName, queue<string> comp, queue<REM_RecordID> &ridQ)
{
	//Ουρα με τα rids που ικανοποιουν τουλαχιστον μια συνθηκη
	queue<REM_RecordID> ridQcheck;
	
	t_rc rc;
	
	//Δηλωση χειριστων
	STORM_StorageManager *sm = new STORM_StorageManager();
	REM_RecordFileManager rm(sm);
	REM_RecordFileHandle rfh;
	
	//Υποδεικνυει το πληθος των τριαδων-συνθηκων που υπαρχουν
	//Μια τριαδα ειναι της μορφης attr1 comp attr2 και ολες συνδεονται με τελεστη AND
	int ANDcounter = 0;
	
	//Παρε το directory του πινακα μεσα στη βαση
	string path="data/";
	path.append(sysm->getCurdbName());
	path.append("/");
	path.append(tableName);
	//και ανοιξε fileScan για το συγκεκριμενο πινακα
	rc = rm.OpenRecordFile(path.c_str(),rfh);
	if(rc!=OK) return rc;


	//Αν δεν εχουμε καποια συνθηκη
	if(comp.empty())
	{
		REM_RecordFileScan rfs;
		REM_RecordHandle rh;

		//Ανοιξε το χειριστη του πινακα χωρις συνθηκη
		rc = rfs.OpenRecordScan(rfh,TYPE_STRING,0,0,NO_OP,NULL);
		if(rc!=OK) return rc;
		
		//Για ολα τα records που υπαρχουν στον πινακα
		while(rfs.GetNextRecord(rh)==OK)
		{
			//Παρε το επομενο recordID
			REM_RecordID rid;
			rc = rh.GetRecordID(rid);
			if(rc!=OK) return rc;
			
			//και προσθεσε το στην τελικη ουρα απευθειας
			ridQ.push(rid);
		}
		rc = rfs.CloseRecordScan();
		
	}
	else
	{
		//Μεχρι να εχουν ελεγχθει ολες οι τριαδες συνθηκης
		while(!comp.empty())
		{
			//Διαβασε την επομενη τριαδα
			string attr1, compOp, attr2;
			attr1 = comp.front();
			comp.pop();
			compOp = comp.front();
			comp.pop();
			attr2 = comp.front();
			comp.pop();
			//Μορφης attr1 compOp attr2

			//παρε τον τελεστη REM απο το compOp το οποιο ειναι μορφης τελεστη SirenBase
			t_compOp OrCompOp = getCompOp(compOp);

			struct relAttr RAttr, RAttr2;
			string* tablePoint = &tableName;

			//Αρχικοποιησε τη στηλη attr1
			rc = initializeAttr(tablePoint, 1, attr1, RAttr);
			if(rc!=OK) return rc;
			
			//Προσπαθησε να αρχικοποιησεις τη στηλη attr2
			rc = initializeAttr(tablePoint, 1, attr2, RAttr2);
			if((rc!=OK)||(RAttr2.type!=RAttr.type)) //Αν η προσπαθεια αποτυχει ή οι δυο στηλες δεν ειναι ομοιες
			{
				//το RAttr2 δεν ειναι στηλη, αρα, αναφερεται σε τιμη
				rc = whereValueCase(rfh,ridQcheck,RAttr,OrCompOp,attr2);
				if(rc!=OK) return rc;
			}
			else //αλλιως, αν η αρχικοποιηση ηταν επιτυχης
			{
				//το RAttr2 αναφερεται σε στηλη

				rc = whereAttrCase(rfh, ridQcheck, RAttr,OrCompOp,RAttr2);
				if(rc!=OK) return rc;
			}
			if(!comp.empty()) comp.pop(); //Πεταμα του "AND", αν υπαρχει
			ANDcounter++; //Ενημερωσε το μετρητη ζευγων που εχουμε
		}
		int qSize = ridQcheck.size(); //το πληθος των πολλαπλοεμφανιζομενων rids (ικανοποιουν τουλαχιστον μια συνθηκη)
		
		//Δομη για καθε rid που ικανοποιει μια τουλαχιστον συνθηκη
		//Περιλαμβανει, το rid και τον αριθμο συνθηκων που ικανοποιει
		struct RIDdata* tAND = new RIDdata[qSize];
		int m=0; //ο Μετρητης αυτου του πινακα απο structs
		
		//Για καθε rid που ικανοποιει μια τουλαχιστον συνθηκη
		for(int i=0;i<qSize;i++)
		{
			//παρε το επομενο rid
			REM_RecordID temp = ridQcheck.front();
			ridQcheck.pop();

			bool flaggy=true; //δειχνει αν το τρεχων rid (temp) εχει ξαναεμφανιστει πριν στην ουρα
			int pID, sID, pIDs, sIDs;
			
			//Παρε τις ιδιοτητες του temp
			rc = temp.GetPageID(pID);
			if(rc!=OK) return rc;
			rc = temp.GetSlot(sID);
			if(rc!=OK) return rc;

			//Για καθε rid που διαβαστηκε προηγουμενως
			for(int j=0;j<m;j++)
			{
				//παρε τις ιδιοτητες του
				rc = tAND[j].rid.GetPageID(pIDs);
				if(rc!=OK) return rc;
				rc = tAND[j].rid.GetSlot(sIDs);
				if(rc!=OK) return rc;

				//και συγκρινε τες
				if((pID-pIDs) || (sID-sIDs)) //Αν δεν ταυτιζεται με το τρεχων rid
				{
					//nothing
				}
				else //αλλιως, αν ταυτιζεται
				{
					flaggy=false; //το rid temp δεν ειναι πρωτοεμφανιζομενο
					tAND[j].times++; //αυξησε το πληθος συνθηκων που ικανοποιει
				}
			}
			if(flaggy) //αν δεν ταυτιστηκε με κανενα απο τα προηγουμενα rids
			{
				//πρωτοεμφανιζομενο rid
				//αρχικοποιησε ενα νεο tAND
				tAND[m].rid = temp;
				tAND[m].times = 1;
				m++;
			}
		}
		
		//Για καθε δομη tAND
		for(int i=0;i<m;i++)
		{
			//Αν το συγκεκριμενο tAND ικανοποιει ολες τις συνθηκες
			if(tAND[i].times==ANDcounter)
			{
				ridQ.push(tAND[i].rid); //προστεσε το rid του στην τελικη ουρα
			}
		}
	}
	rc = rm.CloseRecordFile(rfh);
	return rc;
}
t_rc SSQLM_DML_Manager::Where(const char *tName, char *conditions, vector<char *> *finalResultRecords, vector<REM_RecordID> *finalResultRIDs){
		
	char pathname[50];
	char pathname2[50];
	REM_RecordFileHandle *rfh = new REM_RecordFileHandle();
	REM_RecordFileScan *rfs = new REM_RecordFileScan();
	REM_RecordHandle rh;
	REM_RecordID rid;

	vector <char*> conditionsList;
	vector <char*> conditionsListWithoutIndex;

	int condLength = strlen(conditions);
	char *str = (char*)malloc(condLength);
	strcpy(str,conditions);

	char *pointer = str;
	int offset = 0;
	int size;
	char *type;
	char condition[50]; // one condition
	int i = 0;
	char *conditionAttribute = NULL;
	char *conditionValue = NULL;
	t_compOp comp = NO_OP;
	int index_no;
	t_rc rc;

	// Split with delimeter "AND"
	while(strstr(pointer,"AND")){					//***********************************************
													//**	Spaw thn eisodo tou where sta conditions.
		pointer = strstr(pointer,"AND");			//**	To conditionsList periexei ola ta 
		i = 0;										//**	conditions.
		while(&str[offset] != pointer){				//**
			condition[i] = str[offset];				//**
			i++;									//**
			offset++;								//**
		}											//**
		condition[i] = '\0';						//**
													//**
		conditionsList.push_back(condition);		//**
													//**
		offset+=4;									//**
		pointer+=4;									//**
	}												//**
	//add the last condition in the list			//**
	conditionsList.push_back(pointer);				//************************************************

	hash_map<int, REM_RecordID> rids;
	bool isFirstCondition = true;

	for(int iii=0; iii< (int)conditionsList.size(); iii++){		// Gia ka8e condition, 8a elegksw ean yparxei index.  
															// Gia na to kanw auto spaw to condition sta attribute, comperator kai value, kai anoigw to attrmet.
		int condLength = strlen(conditionsList[iii]);		
		char *condit;
		condit = (char *)malloc(condLength);
		strcpy(condit,conditionsList[iii]);					// keep a back up from the condition string because strtok_s destroys it.

		rc = GetConditionInfo(conditionsList[iii],conditionAttribute,comp,conditionValue);		// get the attribute, the comperator and the value of the condition
		if (rc != OK) {return rc; }	
		
		rc = FindAttributeInAttrmet(tName,conditionAttribute,offset,type,size,index_no);
		if (rc != OK) {return rc; }	

		if(index_no != -1){	//IN CASE OF INDEX									//***********************************
																				//**	ean exei index, 
			// Open index file													//**	anoigw to arxeio tou index
			INXM_IndexHandle ih;												//**	kai psaxnw mesa ta rids pou epalh8eyoun thn syn8hkh
			_snprintf_s(pathname2,sizeof(pathname),"%s/%s",dbName,tName);		//**
																				//**
			rc = im->OpenIndex(pathname2,index_no,ih);							//**
			if (rc != OK) { return rc; }										//**
																				//**
			INXM_IndexScan *is = new INXM_IndexScan();							//**
																				//**
			if(type){	// case of Integer										//**
				int cndV = atoi(conditionValue);								//**
				int *key1 = new int(cndV);										//**
				rc = is->OpenIndexScan(ih, comp, key1);							//**			
				if (rc != OK) { return rc; }									//**
			}																	//**
			else{		//case of string										//**
				rc = is->OpenIndexScan(ih, comp, conditionValue);				//**
				if (rc != OK) { return rc; }									//**	
			}																	//***********************************
			
			
			// Prepei twra na vroume thn tomh olwn twn rid pou epistrefoun oi indexers																	
			int i = 0;	
			int page;
			int slott;

			if(isFirstCondition){									//***********************************
																	//**	Edw dhmiourgeitai o hashmap gia to prwto condition.
				while( is->GetNextEntry(rid) != INXM_FSEOF ){		//**	Gia ka8e record pou epistrefei
																	//**
					rid.GetPageID(page);							//**
					rid.GetSlot(slott);								//**			
					rids[page*10000+slott] = rid;					//**	ypologizw ena monadiko kleidi					
					i++;											//**	kai pros8etw to recordid ston hash.		
				}													//**
				isFirstCondition = false;							//**	Gia thn epomenh syn8hkh, 8a vrei thn tomh tou hash me ta epomena rids.
			}														//***********************************
			else{
				hash_map<int, REM_RecordID> intersectionRIDs;

				while( is->GetNextEntry(rid) != INXM_FSEOF ){
				
					rid.GetPageID(page);
					rid.GetSlot(slott);
					if(rids.count(page*10000+slott)){				//	ean yparxei hdh ston prohgoumeno hash
						intersectionRIDs[page*10000+slott] = rid;	//	pros8ese to ston hash me thn tomh.
					}								
					i++;															
				}
				rids.swap(intersectionRIDs);						//	antallakse tous hashes wste na leitourghsei anadromika kai gia ta epomena conditions
			}

			rc = is->CloseIndexScan();
			if (rc != OK) { return rc; }
		}
		else{	// IN CASE THERE IS NO INDEX						//	Se periptwsh pou to attribute tou condition den exei index
			conditionsListWithoutIndex.push_back(condit);			//	pros8ese to sthn lista me ta conditions pou den exoun index
		}
	}

	STORM_StorageManager *stormgr3 = new STORM_StorageManager();				//	Epomeno vhma einai na paroume apo to REM ta records sta opoia
	REM_RecordFileManager *remrfm = new REM_RecordFileManager(stormgr3);		//	antistoixoun ta recordids pou mazepsame apo tous indexers.
	REM_RecordFileHandle *remrfh = new REM_RecordFileHandle();					//	Ean den mazepsame kanena rid apo indexer, tote anazhtoume sto
	REM_RecordHandle *remrh = new REM_RecordHandle();							//	table ta records pou epalh8euoun thn syn8hkh (ths opoias to
	vector <char*> recordsFromIndexes;											//	attribute den eixe index)
	vector <REM_RecordID> ridsFromIndexes;		
	hash_map <int, REM_RecordID>::iterator rids_Iter;
	char *pdata;

	_snprintf_s(pathname,sizeof(pathname),"%s/%s",dbName,tName);
	rc = remrfm->OpenRecordFile(pathname,*remrfh);
	if (rc != OK) { return rc; }

	for ( rids_Iter = rids.begin( ); rids_Iter != rids.end( ); rids_Iter++ ){	// Vres ta records sta opoia antistoixoun h tomh twn rids twn indexes.
		
		REM_RecordID recordid = rids_Iter->second;
		rc = remrfh->ReadRecord(recordid,*remrh);
		if (rc != OK) {return rc; }	

		remrh->GetData(pdata);

		int pDataLength = strlen(pdata);
		char * newInput;
		newInput = (char *)malloc(pDataLength);
		strcpy(newInput,pdata);

		ridsFromIndexes.push_back(recordid);
		recordsFromIndexes.push_back(newInput);									// Apo8hkeyse ta se mia lista.
	}

	rc = remrfm->CloseRecordFile(*remrfh);
	if (rc != OK) {return rc; }

	if(!conditionsListWithoutIndex.empty()){																//	Ean yparxoun conditions xwris indexes,
																											//	8a psaksoume to attribute tou ka8e condition sto arxeio attrmet
//																											//	wste na paroume plhrofories gia to attribute (offset,type,...)
		int offset2,size2,indexID2;																			//	me teliko stoxo na elegksoume poia apo ta records pou epestrepsan
		char *type2;																						//	oi indexers, epalh8euoun ta conditions xwris index.

		for(int i=0; i< (int) conditionsListWithoutIndex.size(); i++){										//	Gia ka8e tetoio condition loipon,

			rc = GetConditionInfo(conditionsListWithoutIndex[i],conditionAttribute,comp,conditionValue);	//	vres ta systatika tou merh (attribute, comperator, value)
			if (rc != OK) {return rc; }	

			rc = FindAttributeInAttrmet(tName,conditionAttribute,offset2,type2,size2,indexID2);				//	kai psakse mesa sto attrmet to record gia to sygkekrimeno attribute. Pare tis plhrofories gia to attribute.
			if (rc != OK) {return rc; }	

			int j = 0;
			if(!recordsFromIndexes.empty()){
				for(int j=0; j<(int)recordsFromIndexes.size(); j++){										//	Sygkrine an isxyei h syn8hkh me ola ta records pou epestrepsan oi indexes.	
					
					char *value;																			//	Ean h syn8hkh epalh8euetai, pros8ese to record sthn lista eksodou finalResultRecords.
					value = (char *)malloc(size);
					int z;
					for(z=0; z<size; z++){
						value[z] = recordsFromIndexes[j][offset+z];
					}
					value[z] = '\0';
					if(strstr(type,"TYPE_INT")){
						int val = atoi(value);
						int condValue = atoi(conditionValue);
						if(comp == EQ_OP){
							if(val == condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						else if(comp == GT_OP){
							if(val > condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						else if(comp == LT_OP){
							if(val < condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						else if(comp == NE_OP){
							if(val != condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						else if(comp == GE_OP){
							if(val >= condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						else if(comp == LE_OP){
							if(val <= condValue){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
					}
					else{ // the type is TYPE_STRING
						if(comp == EQ_OP){
							if(strstr(value,conditionValue)){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						if(comp == GT_OP || comp == GE_OP){
							if(strcmp(value,conditionValue) == 1){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
						if(comp == LT_OP || comp == LE_OP){
							if(strcmp(value,conditionValue) == -1){
								finalResultRecords->push_back(recordsFromIndexes[j]);
								finalResultRIDs->push_back(ridsFromIndexes[j]);
							}
						}
					}
					j++;
				}
			}
			else{	// PERIPTWSH POU DEN EIXAME KANENA CONDITION ME INDEX									//	Sthn periptwsh pou den exoume kamia syn8hkh me index
				REM_RecordFileScan *remrfs = new REM_RecordFileScan();										//	psaxnoume mesa ston pinaka ta records pou epalh8euoun
				REM_RecordHandle *remrh2 = new REM_RecordHandle();											//	thn syn8hkh kai ta apouhkeyoume sthn lista eksodou.
				STORM_StorageManager *stormgr4 = new STORM_StorageManager();				
				REM_RecordFileManager *remrfm2 = new REM_RecordFileManager(stormgr4);		
				REM_RecordFileHandle *remrfh2 = new REM_RecordFileHandle();					
				char *data;

				_snprintf_s(pathname,sizeof(pathname),"%s/%s",dbName,tName);
				rc = remrfm2->OpenRecordFile(pathname,*remrfh2);
				if (rc != OK) { return rc; }
				
				if(strcmp(type,"TYPE_INT") == 0){

					int atoiCondition = atoi(conditionValue);
					int *key = new int(atoiCondition);

					rc = remrfs->OpenRecordScan(*remrfh2,TYPE_INT,size,offset,comp,key);	
					if (rc != OK) {return rc; }
				}
				else{
					rc = remrfs->OpenRecordScan(*remrfh2,TYPE_STRING,size,offset,comp,conditionValue);
					if (rc != OK) {return rc; }
				}
				while( remrfs->GetNextRecord(*remrh2) != REM_FSEOF ){

					REM_RecordID recordIDFromNoIndex;
					rc = remrh2->GetRecordID(recordIDFromNoIndex);
					if (rc != OK) {return rc; }

					rc = remrh2->GetData(data);
					if (rc != OK) {return rc; }

					int dataLength = strlen(data);
					char *input;
					input = (char *)malloc(dataLength);
					strcpy(input,data);
					finalResultRecords->push_back(input);	
					finalResultRIDs->push_back(recordIDFromNoIndex);
				}

				rc = remrfs->CloseRecordScan();
				if (rc != OK) {return rc; }

				rc = remrfm2->CloseRecordFile(*remrfh2);
				if (rc != OK) {return rc; }
				
				delete remrfs;
				delete remrh2;
				delete remrfh2;
				delete remrfm2;
				delete stormgr4;
			}
		}
	}
	else{	// PERIPTWH POU EIXAME MONO CONDITIONS ME INDEXES			//	Se auth thn periptwsh apla vgazoume sthn eksodo
		for( int i=0; i<(int)recordsFromIndexes.size(); i++){			//	ta records pou epestrepsan oi indexes.
			finalResultRecords->push_back(recordsFromIndexes[i]);
			finalResultRIDs->push_back(ridsFromIndexes[i]);
		}
	}

	delete remrh;
	delete remrfh;
	delete remrfm;
	delete stormgr3;

	return OK;
}