int RM_FileScan::GetNextRec(RM_Record &rec, RID &rid) { RM_Record nextrec; int result = NextRec(nextrec, rid); if(result != 0) return result; Bytes get_data = new char[filehandle->GetRsize()]; memcpy(get_data,nextrec.GetRdata(),filehandle->GetRsize()); rec.SetSize(filehandle->GetRsize()); rec.SetData(get_data); return 0; }
int RM_FileHandle::UpdateRec(RID &rid, RM_Record &rec) { int index; Bytes head = (Bytes)bpm->getPage(fileid, rid.GetPageid(), index); Bits* slots = new Bits(head, pernum); if (!slots->bit_get(rid.GetSlotid())) { //cout << "[RM_FileHandle-Update]Warning: RID doesn't exist,Maybe need Insert" << endl; return 1; } int offset = PAGE_HEAD_BYTE; offset = offset + recordsize * rid.GetSlotid(); Bytes rlocation = (Bytes)head; rlocation = rlocation + offset; memcpy(rlocation, rec.GetRdata(), rec.GetSize()); slots->bit_setone(rid.GetSlotid()); bpm->markDirty(index); return 0; }
int RM_FileHandle::InsertRec(RID &rid, RM_Record &rec) { //这里的RID是插入后返回一个RID,其余成员函数都是需要一个RID int first_index; BufType first_head = bpm->getPage(fileid, 0, first_index); int empty_rid_offset = EMPTY_RID_OFFSET_BYTE; //获取下一可插入项的偏移 int next_page_offset = NEXT_EMPTY_PAGE_BYTE; //获取下一个含空项页页码的偏移 int slots_offset = SLOT_OFFSET_BYTE; //获取slot偏移位置 if (*(int*)(first_head + EMPTY_PAGE_OFFSET_4BYTE) != -1) { //存在下一个空记录 int insert_page_index; Bytes insert_page_head = (Bytes)bpm->getPage(fileid, first_head[EMPTY_PAGE_OFFSET_4BYTE], insert_page_index); bpm->markDirty(insert_page_index); //肯定要修改,所以提前标记为脏页 RID* current_empty_rid = (RID*)(insert_page_head + empty_rid_offset); //下一可插入项 int next_page = *(int*)(insert_page_head + next_page_offset); //下一个含空项页页码 Bits* slots = new Bits(insert_page_head + slots_offset, pernum); //slots int offset = PAGE_HEAD_BYTE; offset = offset + recordsize * current_empty_rid->GetSlotid(); Bytes rlocation = insert_page_head + offset; //获取相应偏移后的地址 memcpy(rlocation, rec.GetRdata(), rec.GetSize()); //插入该记录 slots->bit_setone(current_empty_rid->GetSlotid()); //slot相应位子置1 rid = *current_empty_rid; //rid返回 bool isfull = true; //标记用,true表示当前页满 for (int current_slot = current_empty_rid->GetSlotid() + 1; current_slot < pernum; current_slot++) { if (!slots->bit_get(current_slot)) { //寻找下一个current_empty_rid,当slots[i]为0时说明该位为空 isfull = false; current_empty_rid->SetSlotid(current_slot); //修改下一个空项的位置 break; } } if (isfull) { //如果页满了 first_head[EMPTY_PAGE_OFFSET_4BYTE] = next_page; //当前数据页的下一页给第一页的含空项页 bpm->markDirty(first_index); //标记脏页 current_empty_rid->SetSlotid(-1); //slotid为-1表示没有下一项 *(int*)(insert_page_head + next_page_offset) = -1; //下一个含空项页页码表示当前页为满页 } } else { //均为满页,新建一页 pagesum++; //总页数新增一页 first_head[PSIZE_OFFSET_4BYTE] = pagesum; //修改总页数 bpm->markDirty(first_index); //标记为脏页 int new_index; //新建一个页,并将slot清零 Bytes new_head = (Bytes)bpm->getPage(fileid, pagesum - 1, new_index); Bits* new_slots = new Bits(new_head + slots_offset, pernum); new_slots->all_zero(); int new_offset = PAGE_HEAD_BYTE; //slot[0]即为第一条记录,存储insert的记录 Bytes rlocation = new_head + new_offset; memcpy(rlocation, rec.GetRdata(), rec.GetSize()); new_slots->bit_setone(0); bpm->markDirty(new_index); //标记为脏页 RID new_rid; new_rid.SetFileid(-1); new_rid.SetPageid(pagesum - 1); new_rid.SetSlotid(1); *(RID*)(new_head + empty_rid_offset) = new_rid; //下一可插入项更新为第1项 rid = new_rid; rid.SetSlotid(0); first_head[EMPTY_PAGE_OFFSET_4BYTE] = pagesum - 1; //第一页的含空项页设为当下的新增页 *(int*)(new_head + next_page_offset) = -1; //由于之前都是满页,这页显然没有后继页面,设为-1 } return 0; }
void test_QM() { int attrcount = 4; AttrInfo attrlist[4]; char aname1[] = "id"; char aname2[] = "age"; char aname3[] = "gender"; char aname4[] = "nationality"; strcpy(attrlist[0].attrName, aname1); strcpy(attrlist[1].attrName, aname2); strcpy(attrlist[2].attrName, aname3); strcpy(attrlist[3].attrName, aname4); attrlist[0].attrLenth = 8; attrlist[1].attrLenth = 8; attrlist[2].attrLenth = 8; attrlist[3].attrLenth = 15; attrlist[0].attrType = INTEGER; attrlist[1].attrType = INTEGER; attrlist[2].attrType = INTEGER; attrlist[3].attrType = STRING; attrlist[0].notNull = true; attrlist[1].notNull = false; attrlist[2].notNull = true; attrlist[3].notNull = true; FileManager* fm = new FileManager(); BufPageManager* bpm = new BufPageManager(fm); RM_Manager* rmm = new RM_Manager(bpm); IX_Manager* ixm = new IX_Manager(); SM_Manager* smm = new SM_Manager(rmm, ixm, currentdb, dbIsOpen); QL_Manager* qlm = new QL_Manager(smm, ixm, rmm, currentdb, dbIsOpen); string db1 = "db1"; string db2 = "db2"; string db3 = "db3"; string table1 = "table1"; string table2 = "table2"; string table3 = "table3"; smm->createDb(db1); smm->createDb(db2); smm->useDb(db1); smm->createTable(table1, 4, attrlist, -1); smm->createTable(table2, 4, attrlist, -1); cout << endl << "test insert----------------------" << endl; int nValues = 4; Value *values = new Value[nValues]; for (long long i = 1; i < 10; ++i) { cout << "id = " << i << endl; long long id = i; long long age1 = 10 - i; long long gender1 = i + 15; char nationality1[] = "China"; values[0].type = INTEGER; values[0].data = (void *) (&id); values[1].type = INTEGER; values[1].data = (void *) (&age1); values[2].type = INTEGER; values[2].data = (void *) (&gender1); values[3].type = STRING; values[3].data = (void *) nationality1; if(qlm->Insert(table1, nValues, values) != 0){ cout << "insert table1 failed" << endl; } } int nValues2 = 4; Value *values2 = new Value[nValues2]; for (long long i = 1; i < 10; ++i) { cout << "id = " << i << endl; long long id = i+1; long long age1 = 15 - i; long long gender1 = i + 60; char nationality1[] = "China"; values2[0].type = INTEGER; values2[0].data = (void *) (&id); values2[1].type = INTEGER; values2[1].data = (void *) (&age1); values2[2].type = INTEGER; values2[2].data = (void *) (&gender1); values2[3].type = STRING; values2[3].data = (void *) nationality1; if (qlm->Insert(table2, nValues2, values2) != 0) { cout << "insert table1 failed" << endl; } } cout << endl << "test delete----------------------" << endl; WhereNode *whereExpr2 = new WhereNode; whereExpr2->type = CONDITION; Condition condition2; condition2.lhsAttr.relName = table1; condition2.lhsAttr.attrName = "id"; condition2.op = LE; condition2.bRhsIsAttr = 0; double id_delete2 = 3; condition2.rhsValue.type = FLOAT; condition2.rhsValue.data = (void *)(&id_delete2); whereExpr2->pData = (void *)(&condition2); whereExpr2->lc = NULL; whereExpr2->rc = NULL; WhereNode *whereExpr3 = new WhereNode; whereExpr3->type = CONDITION; Condition condition3; condition3.lhsAttr.relName = table1; condition3.lhsAttr.attrName = "age"; condition3.op = LE; condition3.bRhsIsAttr = 0; double id_delete3 = 3; condition3.rhsValue.type = FLOAT; condition3.rhsValue.data = (void *)(&id_delete3); whereExpr3->pData = (void *)(&condition3); whereExpr3->lc = NULL; whereExpr3->rc = NULL; WhereNode *whereExpr1 = new WhereNode; whereExpr1->type = LOGIC_OP; LogicOp logic_op = OR; whereExpr1->pData = (void *)(&logic_op); whereExpr1->lc = whereExpr2; whereExpr1->rc = whereExpr3; WhereNode *whereExpr5 = new WhereNode; whereExpr5->type = CONDITION; Condition condition5; condition5.lhsAttr.relName = table1; condition5.lhsAttr.attrName = "id"; condition5.op = EQ; condition5.bRhsIsAttr = 1; condition5.rhsAttr.relName = table2; condition5.rhsAttr.attrName = "id"; whereExpr5->pData = (void *)(&condition5); whereExpr5->lc = NULL; whereExpr5->rc = NULL; WhereNode *whereExpr4 = new WhereNode; whereExpr4->type = LOGIC_OP; LogicOp logic_op4 = AND; whereExpr4->pData = (void *) (&logic_op4); whereExpr4->lc = whereExpr1; whereExpr4->rc = whereExpr5; qlm->Delete(table1, whereExpr1); cout << endl << "test select 1 table----------------------" << endl; /*int nSelAttrs = 2; RelAttr *selAttrs = new RelAttr[nSelAttrs]; selAttrs[0].relName = table1; selAttrs[0].attrName = "id"; selAttrs[1].relName = table1; selAttrs[1].attrName = "age";*/ int nSelAttrs = -1; RelAttr *selAttrs = NULL;/**/ int nRelations = 1; string *relations = new string[nRelations]; relations[0] = table1; //qlm->Select(nSelAttrs, selAttrs, nRelations, relations, whereExpr1); //qlm->Select(nSelAttrs, selAttrs, nRelations, relations, NULL); cout << endl << "test select 2 table----------------------" << endl; int nSelAttrs2 = 3; RelAttr *selAttrs2 = new RelAttr[nSelAttrs2]; selAttrs2[0].relName = table1; selAttrs2[0].attrName = "id"; selAttrs2[1].relName = table1; selAttrs2[1].attrName = "age"; selAttrs2[2].relName = table2; selAttrs2[2].attrName = "gender"; /*int nSelAttrs2 = -1; RelAttr *selAttrs2 = NULL;*/ int nRelations2 = 2; string *relations2 = new string[nRelations2]; relations2[0] = table1; relations2[1] = table2; //qlm->Select(nSelAttrs2, selAttrs2, nRelations2, relations2, whereExpr5); //qlm->Select(nSelAttrs2, selAttrs2, nRelations2, relations2, NULL); cout << endl << "test update----------------------" << endl; ExcNode *excLc = new ExcNode; excLc->type = VALUE; Value value_lc; double upd = 40; value_lc.type = FLOAT; value_lc.data = (void *)(&upd); excLc->pData = (void *)(&value_lc); excLc->lc = excLc->rc = NULL; ExcNode * excRc = new ExcNode; excRc->type = RELATTR; RelAttr attrRc; attrRc.relName = table1; attrRc.attrName = "age"; excRc->pData = (void *)(&attrRc); excRc->lc = excRc->rc = NULL; ExcNode *excRoot = new ExcNode; excRoot->type = ARITH_OP; ArithOp op = ADD; excRoot->pData = (void *)(&op); excRoot->lc = excLc; excRoot->rc = excRc; RelAttr updAttr; updAttr.relName = table1; updAttr.attrName = "age"; //qlm->Update(table1, updAttr, excRoot, whereExpr1); //全表扫描 cout << endl << "全表扫描 table1----------------------" << endl; string new_relName = currentdb + "/" + table1; RM_FileHandle rm_handler; rmm->OpenFile(new_relName.c_str(), rm_handler); RM_FileScan rm_scan; rm_scan.OpenScan(rm_handler, NONETYPE, 0, 0, 0, NO, NULL); RM_Record record; RID rid; while(rm_scan.GetNextRec(record, rid) == 0){ char *rbytes = record.GetRdata(); cout << *(long long*)(rbytes + 8) << " " << *(long long*)(rbytes + 16) << " " << *(long long*)(rbytes + 24) << " " << rbytes + 32 << endl; delete []rbytes; } rm_scan.CloseScan(); rmm->CloseFile(rm_handler); cout << endl << "全表扫描 table2----------------------" << endl; new_relName = currentdb + "/" + table2; rmm->OpenFile(new_relName.c_str(), rm_handler); rm_scan.OpenScan(rm_handler, NONETYPE, 0, 0, 0, NO, NULL); while (rm_scan.GetNextRec(record, rid) == 0) { char *rbytes = record.GetRdata(); cout << *(long long*) (rbytes + 8) << " " << *(long long*) (rbytes + 16) << " " << *(long long*) (rbytes + 24) << " " << rbytes + 32 << endl; delete []rbytes; } rm_scan.CloseScan(); rmm->CloseFile(rm_handler); delete []values; delete fm; delete bpm; delete rmm; delete ixm; delete smm; delete qlm; }