static RC RollBackDeletion(SM_DbHandle &db, Event &event) { RC rc; RID newRid; printf("QL: Undoing deletion.\n"); // Insert the record. RM_FileHandle *pTableHandle; if ((rc = db.FindTableHandle(event.tableName.c_str(), pTableHandle))) return rc; if ((rc = pTableHandle->InsertRec(event.record, newRid))) return rc; // Insert indexes. vector<SM_ActiveAttr> *attrs; if ((rc = db.AllAttributes(event.tableName.c_str(), attrs))) return rc; vector<SM_ActiveAttr>::iterator pActiveAttr; for (pActiveAttr = attrs->begin(); pActiveAttr != attrs->end(); ++pActiveAttr) { if (pActiveAttr->record.hasIndex) { IX_IndexHandle *pIndex = &pActiveAttr->indexHandle; if ((rc = pIndex->InsertEntry(event.record + pActiveAttr->record.attrOffset, newRid))) return rc; } } return 0; }
int main(){ RC rc; PF_Manager pfm; IX_Manager ixm(pfm); IX_IndexHandle ixih; IX_IndexScan ixis; if(rc=ixm.CreateIndex("indextest",0,FLOAT,4)) return rc; if(rc=ixm.OpenIndex("indextest",0,ixih)) return rc; for(int i=0;i<10;i++){ Value value((float)i); if(rc=ixih.InsertEntry(value,RID(i/10,i%10))) return rc; } if ((rc = ixm.CloseIndex(ixih))) { return rc; } if ((rc=ixm.OpenIndex("indextest",0,ixih))) { return rc; } // for(int i=0;i<1;i++){ // Value value; // value.type=INT; // value.iData=i; // // if(rc=ixih.DeleteEntry(value,RID(i/10,i%10))) // return rc; // } ixis.OpenScan(ixih,GE,Value((float)5.0)); RID id; while(ixis.GetNextEntry(id)!=IX_EOF){ PageNum pageNum; SlotNum slotNum; id.GetPageNum(pageNum); id.GetSlotNum(slotNum); cout<<pageNum<<"\t"<<slotNum<<endl; } if ((rc = ixis.CloseScan())) { return rc; } if ((rc = ixm.CloseIndex(ixih))) { return rc; } return 0; }
static RC RollBackUpdate(SM_DbHandle &db, Event &event, RID &rid) { RC rc; printf("QL: Undoing update.\n"); RM_FileHandle *pTableHandle; if ((rc = db.FindTableHandle(event.tableName.c_str(), pTableHandle))) return rc; RM_Record record; if ((rc = pTableHandle->GetRec(rid, record))) return rc; char *data; if ((rc = record.GetData(data))) return rc; SM_Attribute *pAttr; if ((rc = db.FindAttribute(event.tableName.c_str(), event.attrName.c_str(), pAttr))) return rc; // If indexed, remove the old entry. IX_IndexHandle *pIndexHandle; if (pAttr->hasIndex) { if ((rc = db.FindIndexHandle(event.tableName.c_str(), event.attrName.c_str(), pIndexHandle))) return rc; if ((rc = pIndexHandle->DeleteEntry(data + pAttr->attrOffset, rid))) return rc; } // Restore the record. int recordSize = pTableHandle->header.recordSize; memcpy(data, event.record, recordSize); // Update the record. if ((rc = pTableHandle->UpdateRec(record))) return rc; // If indexed, insert the new entry. if (pAttr->hasIndex) { if ((rc = pIndexHandle->InsertEntry(data + pAttr->attrOffset, rid))) return rc; } return 0; }
void test_IX_speed() { RID rid; IX_Manager manager; manager.DestroyIndex("ixtest", 1); manager.CreateIndex("ixtest", 1, INTEGER, 8); IX_IndexHandle handle; long long a; printf("begin insert\n"); for (int i = 1280000; i >= 1; i--) { manager.OpenIndex("ixtest", 1, handle); rid.pageid = i; rid.slotid = i; a = i; if (i % 1000 == 0) printf("i = %d \n", i); handle.InsertEntry(&a, rid); // handle.ForcePages(); manager.CloseIndex(handle); } printf("insert finish\n"); printf("begin delete\n"); manager.OpenIndex("ixtest", 1, handle); for (int i = 60; i >= 56; i--) { rid.pageid = i; rid.slotid = i; a = i; printf("i = %d \n", i); handle.DeleteEntry(&a, rid); handle.ForcePages(); } for (int i = 1; i <= 30; i++) { rid.pageid = i; rid.slotid = i; a = i; printf("i = %d \n", i); handle.DeleteEntry(&a, rid); handle.ForcePages(); } rid.pageid = 33; rid.slotid = 33; a = 33; handle.DeleteEntry(&a, rid); printf("delete finish\n"); IX_IndexScan scan; a = 43; scan.OpenScan(handle, LE, &a); RID scanrid; scan.GetNextEntry(scanrid); while (scanrid.pageid > 0) { printf("rid: %d %d\n", scanrid.pageid, scanrid.slotid); scan.GetNextEntry(scanrid); } }
void Parse_Manager::MainLoop(SM_Manager *smm, RM_Manager *rmm, IX_Manager *ixm) { string instruction = string("python python/parser.py ") + filename + string("> tmp"); system(instruction.c_str()); fp = fopen("tmp.gen", "r"); ql_manager = new QL_Manager(smm, rmm, ixm); char cmd[256]; int a = 1; while(true) { a = 0; memset(cmd, 0 , 256); fscanf(fp, "%s\n", cmd); cout << "cmd: " << cmd << endl; if (strcmp(cmd, "Syntax error") == 0) cout << "Syntax error" << endl; else if(strcmp(cmd, "createdatabase") == 0) { //CREATE DATABASE orderDB; char* DBName = readName(); cout << "CREATE " << DBName<< endl; smm->CreateDb(DBName); } else if(strcmp(cmd, "dropdatabase") == 0) { //DROP DATABASE orderDB; char* DBName = readName(); cout << "DROP " << DBName<< endl; smm->DropDb(DBName); } else if(strcmp(cmd, "use") == 0) { //USE orderDB; char* DBName = readName(); cout << "USE " << DBName<< endl; smm->CloseDb(); smm->OpenDb(DBName); } else if(strcmp(cmd, "showtables") == 0) { //SHOW TABLES cout << "showTables" << endl; smm->ShowDb(); } else if(strcmp(cmd, "drop") == 0){ //DROP TABLE customer; char* relName = readName(); cout << relName<< endl; } else if(strcmp(cmd, "desc") == 0){ //DESC customer; char* relName = readName(); cout << relName<< endl; } else if(strcmp(cmd, "showtable") == 0){ //SHOW customer char* relName = readName(); cout << relName << endl; smm->ShowTable(relName); } else if(strcmp(cmd, "createtable") == 0){ //CREATE TABLE customer {} char* relName = readName(); cout << relName << endl; char* pk = readName(); cout << pk << endl; char *temp = readName(); if(strcmp(temp, "check") == 0){ char *check_attr = readName(); int ntype; fscanf(fp, "%d", &ntype); cout << check_attr << ' ' << ntype << endl; AttrType attrType; int attrLength; Value* value = new Value[ntype]; for(int i = 0; i < ntype; i++) { fscanf(fp, "%d", &value[i].type); if (value[i].type == MyINT){ readInt(value[i].data); attrType = MyINT; attrLength = 4; } else if(value[i].type == FLOAT){ readFloat(value[i].data); attrType = FLOAT; attrLength = 4; } else{ readString(value[i].data); attrType = STRING; attrLength = 1024; } cout << value[i]; } char checkname[512]; memset(checkname, 0, sizeof checkname); sprintf(checkname, "%s.check", check_attr); ixm->CreateIndex(relName, checkname, attrType, attrLength); IX_IndexHandle ixh; ixm->OpenIndex(relName, checkname, ixh); for (int i = 0; i < ntype; i++) { ixh.InsertEntry(value[i].data, RID(i, 0)); } ixm->CloseIndex(ixh); } else if(strcmp(temp, "nocheck") == 0) { cout << "nocheck" << endl; } int attrCount; AttrInfo* attributes; fscanf(fp, "%d", &attrCount); attributes = new AttrInfo[attrCount]; for (int i = 0; i < attrCount; i++){ memset(attributes[i].attrName, 0, MAXNAME+1); fscanf(fp, "%s %d %d %d", attributes[i].attrName, &attributes[i].attrType, &attributes[i].attrLength, &attributes[i].notNull); if(strcmp(attributes[i].attrName, pk) == 0) { attributes[i].primaryKey = 1; ixm->CreateIndex(relName, attributes[i].attrName, attributes[i].attrType, attributes[i].attrLength); } } AttrInfo *x = new AttrInfo[attrCount]; for (int i = 0; i < attrCount; i++) x[i] = attributes[i]; smm->CreateTable(relName, attrCount, x); delete x; } else if(strcmp(cmd, "createindex") == 0) { //CREATE INDEX customer(name); char *relName = readName(); char *attrName = readName(); cout << relName << ' ' << attrName << endl; int attrNum; DataAttrInfo* attrs; smm->GetTable(relName, attrNum, attrs); for (int i = 0; i < attrNum; i++) if (strcmp(attrs[i].attrName, attrName) == 0) { //printf("createindex attrName : %s attrLength : %d attroffset : %d\n", attrs[i].attrName, attrs[i].attrLength, attrs[i].offset); if (ixm->CreateIndex(relName, attrName, attrs[i].attrType, attrs[i].attrLength) == -1) break; IX_IndexHandle ixh; ixm->OpenIndex(relName, attrName, ixh); RM_FileHandle relfh; rmm->OpenFile(relName, relfh); RM_FileScan scan(rmm->getFileManager(), rmm->getBufPageManager()); scan.OpenScan(relfh, attrs[i].attrType, attrs[i].attrLength, 0, NO_OP, (void*)0); int cnt = 0; while (true) { RM_Record rec; if (scan.GetNextRec(rec) == -1) break; ixh.InsertEntry(rec.data + attrs[i].offset, rec.rid); //printf("%d %s %lld\n", cnt++, rec.data + attrs[i].offset, (long long)(rec.data)); } //printf("\n"); rmm->CloseFile(relfh); ixm->CloseIndex(ixh); break; } } else if(strcmp(cmd, "dropindex") == 0) { //DROP INDEX customer(name); char *relName = readName(); char *attrName = readName(); cout << relName << ' ' << attrName << endl; ixm->DestroyIndex(relName, attrName); } else if(strcmp(cmd, "insert") == 0){ char* relName = readName(); int hasAttr; fscanf(fp, "%d", &hasAttr); AttrInfo* attrs; int nattr = 0; if (hasAttr == 1) readAttr(nattr, attrs); readInsertData(relName, nattr, attrs); } else if(strcmp(cmd, "delete") == 0){ char* relName = readName(); char temp[100] = {}; fscanf(fp, "%s", temp); if(strcmp(temp, "where") == 0) { int nrid = 0; RID *rid; readWhere(relName, nrid, rid); ql_manager->Delete(relName, nrid, rid); } else if(strcmp(temp, "enddelete") == 0) { ql_manager->Delete(relName, -1, NULL); } else { cout << "Syntax Error" << endl; break; } } else if(strcmp(cmd, "update") == 0) { char* relName = readName(); RelAttr l, r; Value v; int bIsValue = 1; readRelAttr(l); int type; fscanf(fp, "%d", &type); if (type == 0){ v.type = MyINT; readInt(v.data); } else if (type == 1){ v.type = FLOAT; readFloat(v.data); } else if(type == 2){ v.type = STRING; readString(v.data); } else if(type == 3) { bIsValue = 0; readRelAttr(r); } char* ddd = (char*)v.data; char temp[100] = {}; fscanf(fp, "%s", temp); if(strcmp(temp, "where") == 0){ int nrid = 0; RID* rid; readWhere(relName, nrid, rid); ql_manager->Update(relName, l, bIsValue, r, v, nrid, rid); } else if(strcmp(temp, "endupdate") == 0){ ql_manager->Update(relName, l, bIsValue, r, v, -1, NULL); } } else if(strcmp(cmd, "select") == 0){ int nattrs = 0; fscanf(fp, "%d", &nattrs); RelAttr *attr = new RelAttr[nattrs]; for(int i = 0; i < nattrs; i++) { fscanf(fp, "%d", &attr[i].type); readRelAttr(attr[i]); //cout << attr[i].type << ' ' << (attr[i].relName == NULL) << ' ' << attr[i].attrName << endl; } int nrela = 0; fscanf(fp, "%d", &nrela); cout << nrela << endl; // cout << "get 3" << endl; //cout << nrela << endl; char **rela = new char*[nrela]; for(int i = 0; i < nrela; i++) { rela[i] = new char[MAXNAME]; memset(rela[i], 0, MAXNAME); fscanf(fp, "%s", rela[i]); //cout << rela[i] << endl; } char temp[100] = {}; fscanf(fp, "%s", temp); // cout << "get 4" << endl; if(strcmp(temp, "where") == 0) { if(nrela == 1) { int nrid = 0; RID* rid; readWhere(rela[0], nrid, rid); ql_manager->Print(nattrs, attr, rela[0], nrid, rid); } else{ int ncond = 0; Condition* cond; readWhere(ncond, cond); //RelAttr gattr; //ql_manager->Select(0,NULL,0,NULL,0,0,NULL,gattr); ql_manager->Select(nattrs, attr, nrela, rela, 0, ncond, cond, attr[0]); } } else if(strcmp(temp, "group") == 0) { RelAttr gattr; readRelAttr(gattr); ql_manager->Select(nattrs, attr, nrela, rela, 1, 0, NULL, gattr); } else if(strcmp(temp, "endselect") == 0) { ql_manager->Select(nattrs, attr, nrela, rela, 0, 0, NULL, attr[0]); } else{ cout << "Syntax Error" << endl; break; } } else { cout << "over" << endl; break; } } fclose(fp); }
void test_IX() { RID rid; IX_Manager manager; manager.DestroyIndex("ixtest", 0); manager.CreateIndex("ixtest", 0, INTEGER, 8); // IX_IndexHandle handle; manager.OpenIndex("ixtest", 0, handle); char a[480]; memset(a, 0, 10); memset(a + 10, 255, 470); printf("begin insert\n"); // for (int i = 1; i <= 4; i++) { // for (int j = 1; j <= 4; j++) { // rid.pageid = i; rid.slotid = j; // a[i] = j; // printf("%d %d\n", i, j); // handle.InsertEntry(a, rid); // handle.ForcePages(); // } // } for (int i = 55; i >= 1; i--) { rid.pageid = i; rid.slotid = i; a[0] = i; printf("i = %d \n", i); handle.InsertEntry(a, rid); handle.ForcePages(); } printf("insert finish\n"); printf("begin delete\n"); for (int i = 60; i >= 56; i--) { rid.pageid = i; rid.slotid = i; a[0] = i; printf("i = %d \n", i); handle.DeleteEntry(a, rid); handle.ForcePages(); } for (int i = 1; i <= 30; i++) { rid.pageid = i; rid.slotid = i; a[0] = i; printf("i = %d \n", i); handle.DeleteEntry(a, rid); handle.ForcePages(); } rid.pageid = 33; rid.slotid = 33; a[0] = 33; handle.DeleteEntry(a, rid); printf("delete finish\n"); IX_IndexScan scan; a[0] = 43; scan.OpenScan(handle, NE, a); RID scanrid; scan.GetNextEntry(scanrid); while (scanrid.pageid > 0) { printf("rid: %d %d\n", scanrid.pageid, scanrid.slotid); scan.GetNextEntry(scanrid); } // handle.DeleteEntry(&a, rid); printf("%d\n", INT_MAX); }
RC QL_Manager::Insert() { RC rc; const char *tableName = rmp.relName; vector<SM_ActiveAttr> *attrs; if ((rc = db.AllAttributes(tableName, attrs))) return rc; if (rmp.nValues != attrs->size()) { fprintf(stderr, "QL: Mismatch # of attributes.\n"); return QL_ERR_INVALID_COMMAND; } // Fill in the record buffer. SM_Attribute *lastAttr = &attrs->at(attrs->size()-1).record; int recordSize = lastAttr->attrOffset + lastAttr->attrLength + sizeof(int); Event event; event.record = new char[recordSize]; event.type = INSERT; event.tableName = rmp.relName; memset(event.record, 0, recordSize); RM_FileHandle *pTableHandle; if ((rc = db.FindTableHandle(rmp.relName, pTableHandle))) { delete[] event.record; return rc; } int *pNullBitmap = (int *)(event.record + lastAttr->attrOffset + lastAttr->attrLength); for (int i = 0; i < attrs->size(); i++) { SM_Attribute *attr = &attrs->at(i).record; if (attr->attrType != rmp.values[i].type && rmp.values[i].type != NOTYPE) { fprintf(stderr, "QL: Mismatch type for attribute %s\n", attr->attrName); delete[] event.record; return QL_ERR_INVALID_COMMAND; } // Check primary key uniqueness. if (attr->isPrimary && !attr->hasIndex) { RM_FileScan scan; if ((rc = scan.OpenScan(*pTableHandle, attr->attrType, attr->attrLength, attr->attrOffset, attr->number, EQ_OP, rmp.values[i].data))) return rc; RM_Record rec; if (scan.GetNextRec(rec) != RM_ERR_EOF) { fprintf(stderr, "QL: Primary key conflicts!\n"); scan.CloseScan(); return QL_PRIMARY_KEY; } if ((rc = scan.CloseScan())) return rc; } // Check foreign key existence. if (attr->isForeignKey) { RM_FileHandle *pForeign; if ((rc = db.FindTableHandle(attr->refTableName, pForeign))) return rc; SM_Attribute *foreignAttr; if ((rc = db.FindAttribute(attr->refTableName, attr->refAttrName, foreignAttr))) return rc; if (foreignAttr->attrType != attr->attrType) { fprintf(stderr, "QL: mismatch attribute type with foreign key.\n"); return rc; } RM_FileScan scan; if ((rc = scan.OpenScan(*pForeign, foreignAttr->attrType, foreignAttr->attrLength, foreignAttr->attrOffset, foreignAttr->number, EQ_OP, rmp.values[i].data))) return rc; RM_Record rec; if (scan.GetNextRec(rec) != 0) { fprintf(stderr, "QL: Foreign key does not exist!\n"); scan.CloseScan(); return QL_FOREIGN_KEY; } if ((rc = scan.CloseScan())) return rc; } if (rmp.values[i].type == NOTYPE) { if (attr->hasIndex) { fprintf(stderr, "QL: indexed attribute %s cannot be NULL\n", attr->attrName); delete[] event.record; return QL_ERR_INVALID_COMMAND; } *pNullBitmap |= 1 << i; } else if (rmp.values[i].type == INT || rmp.values[i].type == FLOAT) memcpy(event.record + attr->attrOffset, rmp.values[i].data, attr->attrLength); else strncpy(event.record + attr->attrOffset, (const char *)rmp.values[i].data, attr->attrLength); } // Insert the record into the database. RID rid; if ((rc = pTableHandle->InsertRec(event.record, rid))) { delete[] event.record; return rc; } transaction.insert(pair<RID, Event>(rid, event)); // Insert the record into indexes. for (int i = 0; i < attrs->size(); i++) { SM_Attribute *pAttr = &attrs->at(i).record; if (pAttr->hasIndex) { IX_IndexHandle *pIndexHandle = &attrs->at(i).indexHandle; //cout << "debug:\n"; if ((rc = pIndexHandle->InsertEntry(event.record + pAttr->attrOffset, rid))) return rc; } } return 0; }
RC QL_Manager::Update() { RC rc; vector<RM_Record> chosenRecords; RM_FileHandle *pTableHandle; if ((rc = db.FindTableHandle(rmp.relName, pTableHandle))) return rc; SM_Attribute *pAttr; if ((rc = db.FindAttribute(rmp.relName, rmp.updAttr.attrName, pAttr))) return rc; if (rmp.rhsValue.type != pAttr->attrType && rmp.rhsValue.type != NOTYPE) { fprintf(stderr, "QL: Update attributes with different type!\n"); return QL_ERR_INVALID_COMMAND; } if (rmp.rhsValue.type == NOTYPE && pAttr->notNull) { fprintf(stderr, "QL: Update not-null attribute with NULL!\n"); return QL_ERR_INVALID_COMMAND; } if ((rc = FindRecords(rmp.relName, chosenRecords))) return rc; vector<RM_Record>::iterator pRecord; int recordSize = pTableHandle->header.recordSize; for (pRecord = chosenRecords.begin(); pRecord != chosenRecords.end(); pRecord++) { RID rid; if ((rc = pRecord->GetRid(rid))) return rc; char *data; if ((rc = pRecord->GetData(data))) return rc; int *pNullBitmap = (int *)(data + recordSize - sizeof(int)); // Check primary key uniqueness. SM_Attribute *attr = pAttr; if (attr->isPrimary && !attr->hasIndex) { RM_FileScan scan; if ((rc = scan.OpenScan(*pTableHandle, attr->attrType, attr->attrLength, attr->attrOffset, attr->number, EQ_OP, rmp.rhsValue.data))) return rc; RM_Record rec; if (scan.GetNextRec(rec) != RM_ERR_EOF) { fprintf(stderr, "QL: Primary key conflicts!\n"); scan.CloseScan(); return QL_PRIMARY_KEY; } if ((rc = scan.CloseScan())) return rc; } // Check foreign key existence. if (attr->isForeignKey) { RM_FileHandle *pForeign; if ((rc = db.FindTableHandle(attr->refTableName, pForeign))) return rc; SM_Attribute *foreignAttr; if ((rc = db.FindAttribute(attr->refTableName, attr->refAttrName, foreignAttr))) return rc; if (foreignAttr->attrType != attr->attrType) { fprintf(stderr, "QL: mismatch attribute type with foreign key.\n"); return rc; } RM_FileScan scan; if ((rc = scan.OpenScan(*pForeign, foreignAttr->attrType, foreignAttr->attrLength, foreignAttr->attrOffset, foreignAttr->number, EQ_OP, rmp.rhsValue.data))) return rc; RM_Record rec; if (scan.GetNextRec(rec) != 0) { fprintf(stderr, "QL: Foreign key does not exist!\n"); scan.CloseScan(); return QL_FOREIGN_KEY; } if ((rc = scan.CloseScan())) return rc; } Event event; event.type = UPDATE; event.record = new char[recordSize]; event.tableName = rmp.relName; event.attrName = rmp.updAttr.attrName; memcpy(event.record, data, recordSize); // If indexed, remove the old entry. IX_IndexHandle *pIndexHandle; if (pAttr->hasIndex) { if ((rc = db.FindIndexHandle(rmp.relName, pAttr->attrName, pIndexHandle))) { delete[] event.record; return rc; } if ((rc = pIndexHandle->DeleteEntry(data + pAttr->attrOffset, rid))) { delete[] event.record; return rc; } } map<RID, Event, RID_LessThan>::iterator pPrevEvent = transaction.find(rid); if (pPrevEvent == transaction.end()) { transaction.insert(pair<RID, Event>(rid, event)); } else { delete[] event.record; } // Modify the record. if (pAttr->attrType == INT || pAttr->attrType == FLOAT) { memcpy(data + pAttr->attrOffset, rmp.rhsValue.data, pAttr->attrLength); *pNullBitmap &= ~(1 << pAttr->number); } else if (pAttr->attrType == NOTYPE) { *pNullBitmap |= 1 << pAttr->number; } else { strncpy(data + pAttr->attrOffset, (const char *)rmp.rhsValue.data, pAttr->attrLength); *pNullBitmap &= ~(1 << pAttr->number); } // Update the record. if ((rc = pTableHandle->UpdateRec(*pRecord))) { delete[] event.record; return rc; } // If indexed, insert the new entry. if (pAttr->hasIndex) { if ((rc = pIndexHandle->InsertEntry(data + pAttr->attrOffset, rid))) { delete[] event.record; return rc; } } } return 0; }
RC QL_Manager::Delete() { RC rc; vector<RM_Record> chosenRecords; vector<SM_ActiveAttr> *attrs; if ((rc = db.AllAttributes(rmp.relName, attrs))) return rc; RM_FileHandle *pTableHandle; if ((rc = db.FindTableHandle(rmp.relName, pTableHandle))) return rc; if ((rc = FindRecords(rmp.relName, chosenRecords))) return rc; vector<RM_Record>::iterator pRecord; int recordSize = pTableHandle->header.recordSize; for (pRecord = chosenRecords.begin(); pRecord != chosenRecords.end(); ++pRecord) { RID rid; if ((rc = pRecord->GetRid(rid))) return rc; char *data; if ((rc = pRecord->GetData(data))) return rc; Event event; event.type = DELETE; event.record = new char[recordSize]; event.tableName = rmp.relName; memcpy(event.record, data, recordSize); if ((rc = pTableHandle->DeleteRec(rid))) { delete[] event.record; return rc; } // Delete the record from indexes. for (int i = 0; i < attrs->size(); i++) { SM_Attribute *pAttr = &attrs->at(i).record; if (pAttr->hasIndex) { IX_IndexHandle *pIndexHandle = &attrs->at(i).indexHandle; if ((rc = pIndexHandle->DeleteEntry(event.record + pAttr->attrOffset, rid))) return rc; } } map<RID, Event, RID_LessThan>::iterator pPrevEvent = transaction.find(rid); if (pPrevEvent == transaction.end()) { transactionDeleted.push_back(event); } else { if (pPrevEvent->second.type == INSERT) { // Previously inserted. Remove it from the transaction. delete[] event.record; delete[] pPrevEvent->second.record; transaction.erase(pPrevEvent); } else if (pPrevEvent->second.type == UPDATE) { delete[] event.record; pPrevEvent->second.type == DELETE; transactionDeleted.push_back(pPrevEvent->second); transaction.erase(pPrevEvent); } } } return 0; }