/* * This function is used to update a Record, * updating on a deleted page is not possible */ RC updateRecord (RM_TableData *rel, Record *record) { //Find the data to be updated if(record->id.page > 0 && record->id.page <= totalPages) { BM_PageHandle *page = MAKE_PAGE_HANDLE(); int pageNum, slotNum; // Setting record id and slot number pageNum = record->id.page; slotNum = record->id.slot; //Compare if the record is a deleted Record, //return update not possible for deleted records (EC 401) if(strncmp(record->data, "DELETED_RECORD", 14) == 0) return RC_RM_UPDATE_NOT_POSSIBLE_ON_DELETED_RECORD; //Take the serailized updated record data char *record_str = serializeRecord(record, rel->schema); //pin page pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, record->id.page); //set the new fields, or the entire modified page memset(page->data, '\0', strlen(page->data)); sprintf(page->data, "%s", record_str); //free the temp data free(record_str); //mark the page as dirty markDirty(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //unpin the page, after use unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //force write onto the page, as it is modified page now forcePage(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //printf("record data in update: %s\n", page->data); free(page); //free page, avoid leaks return RC_OK; } else { return RC_RM_NO_MORE_TUPLES; //return the data to be modfied not found } return RC_OK; }
void pageOperations(recordTableInfo *table, int pageNum, int slot, RM_TableData *rel, Record *record) { BM_PageHandle *pageHandle=NULL; pageHandle = getBuffPageHandle(); char *strRecord,*tempData; strRecord = serializeRecord(record, rel->schema); if(pinPage(table->bufferManager, pageHandle, pageNum)==RC_OK) strncpy(pageHandle->data + (slot * table->slotSize), strRecord, strlen(strRecord)); markDirty(table->bufferManager, pageHandle); unpinPage(table->bufferManager, pageHandle); if(forcePage(table->bufferManager, pageHandle)==RC_OK) record->id.tombS = false; table->numOfRecords = table->numOfRecords + 1; tableInfoDetailsToFileData(rel->name, tempData, table); free(pageHandle); free(strRecord); }
char * serializeTableContent(RM_TableData *rel) { int i; VarString *result; RM_ScanHandle *sc = (RM_ScanHandle *) malloc(sizeof(RM_ScanHandle)); Record *r = (Record *) malloc(sizeof(Record)); MAKE_VARSTRING(result); for (i = 0; i < rel->schema->numAttr; i++) APPEND(result, "%s%s", (i != 0) ? ", " : "", rel->schema->attrNames[i]); startScan(rel, sc, NULL); while (next(sc, r) != RC_RM_NO_MORE_TUPLES) { APPEND_STRING(result, serializeRecord(r, rel->schema)); APPEND_STRING(result, "\n"); } closeScan(sc); RETURN_STRING(result); }
void testScansTwo (void) { RM_TableData *table = (RM_TableData *) malloc(sizeof(RM_TableData)); TestRecord inserts[] = { {1, "aaaa", 3}, {2, "bbbb", 2}, {3, "cccc", 1}, {4, "dddd", 3}, {5, "eeee", 5}, {6, "ffff", 1}, {7, "gggg", 3}, {8, "hhhh", 3}, {9, "iiii", 2}, {10, "jjjj", 5}, }; bool foundScan[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; int numInserts = 10, i; Record *r; RID *rids; Schema *schema; RM_ScanHandle *sc = (RM_ScanHandle *) malloc(sizeof(RM_ScanHandle)); Expr *sel, *left, *right, *first, *se; int rc; testName = "test creating a new table and inserting tuples"; schema = testSchema(); rids = (RID *) malloc(sizeof(RID) * numInserts); TEST_CHECK(initRecordManager(NULL)); TEST_CHECK(createTable("test_table_r",schema)); TEST_CHECK(openTable(table, "test_table_r")); // insert rows into table for(i = 0; i < numInserts; i++) { r = fromTestRecord(schema, inserts[i]); TEST_CHECK(insertRecord(table,r)); rids[i] = r->id; } TEST_CHECK(closeTable(table)); TEST_CHECK(openTable(table, "test_table_r")); // Select 1 record with INT in condition a=2. MAKE_CONS(left, stringToValue("i2")); MAKE_ATTRREF(right, 0); MAKE_BINOP_EXPR(sel, left, right, OP_COMP_EQUAL); createRecord(&r, schema); TEST_CHECK(startScan(table, sc, sel)); while((rc = next(sc, r)) == RC_OK) { ASSERT_EQUALS_RECORDS(fromTestRecord(schema, inserts[1]), r, schema, "compare records"); } if (rc != RC_NO_TUPLES) TEST_CHECK(rc); TEST_CHECK(closeScan(sc)); // Select 1 record with STRING in condition b='ffff'. MAKE_CONS(left, stringToValue("sffff")); MAKE_ATTRREF(right, 1); MAKE_BINOP_EXPR(sel, left, right, OP_COMP_EQUAL); createRecord(&r, schema); TEST_CHECK(startScan(table, sc, sel)); while((rc = next(sc, r)) == RC_OK) { ASSERT_EQUALS_RECORDS(fromTestRecord(schema, inserts[5]), r, schema, "compare records"); serializeRecord(r, schema); } if (rc != RC_NO_TUPLES) TEST_CHECK(rc); TEST_CHECK(closeScan(sc)); // Select all records, with condition being false MAKE_CONS(left, stringToValue("i4")); MAKE_ATTRREF(right, 2); MAKE_BINOP_EXPR(first, right, left, OP_COMP_SMALLER); MAKE_UNOP_EXPR(se, first, OP_BOOL_NOT); TEST_CHECK(startScan(table, sc, se)); while((rc = next(sc, r)) == RC_OK) { serializeRecord(r, schema); for(i = 0; i < numInserts; i++) { if (memcmp(fromTestRecord(schema, inserts[i])->data,r->data,getRecordSize(schema)) == 0) foundScan[i] = TRUE; } } if (rc != RC_NO_TUPLES) TEST_CHECK(rc); TEST_CHECK(closeScan(sc)); ASSERT_TRUE(!foundScan[0], "not greater than four"); ASSERT_TRUE(foundScan[4], "greater than four"); ASSERT_TRUE(foundScan[9], "greater than four"); // clean up TEST_CHECK(closeTable(table)); TEST_CHECK(deleteTable("test_table_r")); TEST_CHECK(shutdownRecordManager()); freeRecord(r); free(table); free(sc); freeExpr(sel); TEST_DONE(); }
/* * This function is used to insert a new Record into the table * while inserting, the record Manager assigns a RID to the record * and update the "record" parameter too */ RC insertRecord (RM_TableData *rel, Record *record) { //Create a record variable Record *r = (Record *)malloc(sizeof(Record)); RID rid; rid.page = 1; rid.slot = 0; //Find the next place of insertion of a record while(rid.page > 0 && rid.page < totalPages) { rid.page = rid.page + 1; rid.slot = 0; /*getRecord(rel, rid, r); //obtaining the record from the table //checking for soft delete record in the table space for insertion if(strncmp(r->data, "DELETED_RECORD", 14) == 0) break;*/ } r = NULL; free(r); //free the memory of r which was just a temporary allocation //mark the page as free page ((RM_RecordMgmt *)rel->mgmtData)->freePages[0] = rid.page; //create a page handle BM_PageHandle *page = MAKE_PAGE_HANDLE(); //assign the record, its RID and slot number record->id.page = ((RM_RecordMgmt *)rel->mgmtData)->freePages[0]; record->id.slot = 0; //Serialize the Record to be inserted char * serializedRecord = serializeRecord(record, rel->schema); //Pin the record page, to mark that it is in use pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, ((RM_RecordMgmt *)rel->mgmtData)->freePages[0]); //insert the new record data, into the Table i.e. Pages of the PageFile memset(page->data, '\0', strlen(page->data)); sprintf(page->data, "%s", serializedRecord); //mark the page as Dirty Page, as now there is a new record entry on that page markDirty(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //Unpin the page as now it has been used unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //Force Page to push entire data onto the page forcePage(((RM_RecordMgmt *)rel->mgmtData)->bm, page); //printf("record data: %s\n", page->data); free(page); //free page, avoid memory leaks ((RM_RecordMgmt *)rel->mgmtData)->freePages[0] += 1; totalPages++; return RC_OK; }