//遍历初始化,判断一下查询属性类型是否有误等等 int RM_FileScan::OpenScan(RM_FileHandle& fileHandle, AttrType attrType, int attrLength, int attrOffset, int attrCol,CompOp compOp, void* value) { if (fileHandle.GetPsum() == 1) { cout << "[RM_FileScan]Empty Database" << endl; return 1; } filehandle = &fileHandle; /* if (compOp == NO) { type = 18; } else { if(attrType == NONETYPE) { type = 19; } else { int typevalue = attrType; int opvalue = compOp; type = (typevalue - 1) * 6 + opvalue; } }*/ currentRid = new RID(fileHandle.GetFileid(), 1, 0); comparevalue = value; attrlength = attrLength; attroffset = attrOffset; op = compOp; type = attrType; attrcol = attrCol; isclose = false; return 0; }
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; }
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; }
int RM_Manager::CloseFile(RM_FileHandle &fileHandle) { fileHandle.close(); return 0; }
RC SM_CreateTable(SM_Manager *self, char *relName, AttrInfo *attributes) { int recordSize = 0, attrNum = 0, ret; AttrInfo *p, *pk = NULL; if (self->dbname == NULL) { return SM_NODBSELECTED; } if (checkInViews(self, relName)) { return SM_VIEWEXIST; } for (p = attributes; p; p = p->next) { AttrInfo *p0; for (p0 = p->next; p0; p0 = p0->next) { if (!strcmp(p->name, p0->name)) return SM_DUPLICATEATTR; } } for (p = attributes; p; p = p->next) { int j = self->attrCount++; attrNum++; AttrCat actmp; AttrCatSetRelName(&actmp, relName); AttrCatSetAttrName(&actmp, p->name); actmp.offset = recordSize; actmp.attrType = p->type; actmp.attrLength = p->size; actmp.indexNo = -1; if (!checkRelAttr(self, p->foriegnKey)) { return SM_NOREL; } if (p->foriegnKey) { MAXSCP(actmp.fkrelName, p->foriegnKey->relName, MAXNAME); MAXSCP(actmp.fkattrName, p->foriegnKey->attrName, MAXNAME); char *fname = malloc(2*MAXNAME+3); strcpy(fname, "."); strcat(fname, p->foriegnKey->relName); strcat(fname, "."); strcat(fname, p->foriegnKey->attrName); RM_FileHandle fh; initRM_FileHandle(&fh); self->rmm->CreateFile(self->rmm, fname, FKINFO_RSIZE); self->rmm->OpenFile(self->rmm, fname, &fh); fkInfo fki; strcpy(fki.relName, p->foriegnKey->relName); strcpy(fki.attrName, p->foriegnKey->attrName); RID rid; fh.InsertRec(&fh, (char *)&fki, &rid); } else { strcpy(actmp.fkrelName, ""); strcpy(actmp.fkattrName, ""); } if (p->isPrimaryKey) { if (pk) { return SM_DUPRIMARYKEY; } else { pk = p; } } if (p->check) { actmp.op = p->check->op; memcpy(&actmp.rvalue, p->check->value->data, p->size); } else { actmp.op = NO_OP; } self->attrFile.InsertRec(&(self->attrFile), (char *)&actmp, &actmp.rid); self->attrFile.ForcePages(&(self->attrFile), ALL_PAGES); ATTRARRCHECK(self, j); memcpy(&(self->attrRecords[j]), &actmp, sizeof(AttrCat)); recordSize += p->size; } if ((ret = self->rmm->CreateFile(self->rmm, relName, recordSize)) != NORMAL) { return ret; } int k = self->relCount++; RelCat rctmp; RelCatSetRelName(&rctmp, relName); rctmp.tupleLength = recordSize; rctmp.attrCount = attrNum; rctmp.indexCount = 0; if (pk) { strcpy(rctmp.primaryKey, pk->name); } else { strcpy(rctmp.primaryKey, ""); } self->relFile.InsertRec(&(self->relFile), (char *)&rctmp, &rctmp.rid); self->relFile.ForcePages(&(self->relFile), ALL_PAGES); RELARRCHECK(self, k); memcpy(&(self->relRecords[k]), &rctmp, sizeof(RelCat)); return NORMAL; }
RC QL_Manager::FindRecords(const char *relName, vector<RM_Record> &records){ RC rc; RM_FileHandle *rh; IX_IndexHandle *ih; if (rc = db.FindTableHandle(relName, rh)) return rc; RM_FileScan rmscan; IX_IndexScan ixscan; vector<RM_Record> v_now; v_now.clear(); bool flagAll = true; if (rmp.nConditions) { for (int i = 0; i < rmp.nConditions; i++) if (rmp.conditions[i].bRhsIsValue) { if (strcmp(relName, rmp.conditions[i].lhsAttr.relName) != 0) continue; vector<RM_Record> v_tmp; v_tmp.clear(); char *attrName = rmp.conditions[i].lhsAttr.attrName; SM_Attribute *smAttr; if (rc = db.FindAttribute(relName, attrName, smAttr)) return rc; AttrType attrType = smAttr->attrType; int attrLength = smAttr->attrLength; int attrOffset = smAttr->attrOffset; int attrNumber = smAttr->number; CompOp op = rmp.conditions[i].op; void *data = rmp.conditions[i].rhsValue.data; if (smAttr->hasIndex && isCmpOp(op)) { if (rc = db.FindIndexHandle(relName, attrName, ih)) return rc; ixscan.OpenScan(*ih, op, data); RID rid; RM_Record rec; v_tmp.clear(); while (1) { rc = ixscan.GetNextEntry(rid); if (rc != 0 && rc != IX_EOF) return rc; if (rc == IX_EOF) break; if (rc = rh->GetRec(rid, rec)) return rc; v_tmp.push_back(rec); } ixscan.CloseScan(); } else { if (op == IS_OP || op == IS_NOT_OP) { int number = smAttr->number; int nullBitmap = rh->header.recordSize - sizeof(int); if ((rc = rmscan.OpenScan(*rh, NOTYPE, 4, nullBitmap, 0, op, &number))) return rc; } else { if (rc = rmscan.OpenScan(*rh, attrType, attrLength, attrOffset, attrNumber, op, data)) return rc; } v_tmp.clear(); RM_Record rec; while (rmscan.GetNextRec(rec) != RM_ERR_EOF) { v_tmp.push_back(rec); } if (rc = rmscan.CloseScan()) return rc; } if (rc = MergeAnd(v_now, v_tmp, flagAll)) return rc; flagAll = false; } } //cout << "before flagAll\n"; if (flagAll) { int t = 0; if (rc = rmscan.OpenScan(*rh, INT, 4, 0, 0, NO_OP, &t, NO_HINT)) return rc; //cout << "after open scan\n"; RM_Record rec; v_now.clear(); while (rmscan.GetNextRec(rec) != RM_ERR_EOF) v_now.push_back(rec); if (rc = rmscan.CloseScan()) return rc; } //cout << "after flagAll\n"; records.clear(); records.assign(v_now.begin(), v_now.end()); return 0; }
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; }
RC RM_Manager::CloseFile (RM_FileHandle &fileHandle) { return fileHandle.Close (); }
RC RM_Manager::OpenFile (const char *fileName, RM_FileHandle &fileHandle) { return fileHandle.Open (pfm, fileName); }