/* 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); }
//Εκτελει υπο-εντολη του 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; }