int SM_Manager::DropTable (const char * deleteRelName){ RM_FileScan rfs = RM_FileScan(rmm.getFileManager(), rmm.getBufPageManager()); RM_Record rec; //RM_FileHandle attrfh; //RM_FileHandle relfh; //打开rel文件,查询所有relName属性 = deleteRelName的记录,删除该记录 /* rfs.OpenScan(relfh, STRING, strlen(deleteRelName), 4, EQ_OP, (void*)deleteRelName); while (rfs.GetNextRec(rec) != -1){ relfh.DeleteRec(rec.rid); } rfs.CloseScan();*/ //打开attr文件,查询所有relName属性 = deleteRelName的记录,删除该记录 rmm.OpenFile("attrcat", attrfh); rfs.OpenScan(attrfh, STRING, strlen(deleteRelName), 16, EQ_OP, (void*)deleteRelName); while (rfs.GetNextRec(rec) != -1){ attrfh.DeleteRec(rec.rid); } rfs.CloseScan(); rmm.CloseFile(attrfh); rmm.OpenFile("tablelist", tablefh); rfs.OpenScan(tablefh, STRING, strlen(deleteRelName), 0, EQ_OP, (void*)deleteRelName); if (rfs.GetNextRec(rec) != -1){ tablefh.DeleteRec(rec.rid); } rfs.CloseScan(); rmm.CloseFile(tablefh); rmm.DestroyFile(deleteRelName); return 0; }
int SM_Manager::GetTable (const char *readRelName, int &number, DataAttrInfo* &dataInfo){ //打开attr文件,查询所有relName属性 = readRelName的记录, 将attr个数传给number, dataAttrInfo传给dataInfo,内存释放需要外面执行 //属性个数存在上限100 RM_FileScan rfs = RM_FileScan(rmm.getFileManager(), rmm.getBufPageManager()); RM_Record rec; int returnCode; // cout << "GetTable" << endl; rmm.OpenFile("attrcat", attrfh); returnCode = rfs.OpenScan(attrfh, STRING, strlen(readRelName), 16, EQ_OP, (void*)readRelName); int x = 0; dataInfo = new DataAttrInfo[100]; number = 0; // cout << "TableName : "<< readRelName << endl; while (returnCode == 1){ // cout << "ret : 1" << endl; x = rfs.GetNextRec(rec); // cout << "ret : 2" << endl; if (x == -1) break; // cout << x << endl; DataAttrInfo * mydata; rec.GetData((char*&) mydata); dataInfo[number].copy(mydata); number++; } // cout << "Table End" << endl; rfs.CloseScan(); rmm.CloseFile(attrfh); return 0; }
int SM_Manager::ShowTable (const char *readRelName){ //打开attr文件,查询所有relName属性 = readRelName的记录, 打印该记录 RM_FileScan rfs = RM_FileScan(rmm.getFileManager(), rmm.getBufPageManager()); RM_Record rec; int returnCode; // cout << "ShowTable" << endl; rmm.OpenFile("attrcat", attrfh); returnCode = rfs.OpenScan(attrfh, STRING, strlen(readRelName), 16, EQ_OP, (void*)readRelName); int x = 0; // cout << "TableName : "<< readRelName << endl; // cout << "returnCode: " << returnCode << endl; while (returnCode == 1){ // cout << "ret : 1" << endl; x = rfs.GetNextRec(rec); // cout << "ret : 2" << endl; if (x == -1) break; cout << x << endl; DataAttrInfo * mydata; rec.GetData((char*&) mydata); mydata->print(); } cout << "Table End" << endl; rfs.CloseScan(); rmm.CloseFile(attrfh); return 0; }
int SM_Manager::ShowDb() { CloseDb(); if (OpenDb(DataName) != 0) return -1; rmm.OpenFile("tablelist", tablefh); RM_FileScan rfs = RM_FileScan(rmm.getFileManager(), rmm.getBufPageManager()); RM_Record rec; rfs.OpenScan(tablefh, STRING, 0, 0, NO_OP, NULL); cout << "----- begin -----" << endl; while (rfs.GetNextRec(rec) != -1) { cout << rec.rid << " , " << rec.data << endl; } cout << "----- end -----" << endl; rmm.CloseFile(tablefh); return 0; }
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; }
static RC PrintTable(SM_DbHandle &db, const char *tableName) { RC rc; RM_FileHandle *pTable; if ((rc = db.FindTableHandle(tableName, pTable))) return rc; int recordSize = pTable->header.recordSize; vector<SM_ActiveAttr> *attributes; if ((rc = db.AllAttributes(tableName, attributes))) return rc; RM_FileScan allScan; if ((rc = allScan.OpenScan(*pTable, INT, 0, 0, 0, NO_OP, NULL))) return rc; RM_Record record; int recordCount = 0; printf("Table: %s\n", tableName); while ((rc = allScan.GetNextRec(record)) == 0) { RID rid; if ((rc = record.GetRid(rid))) return rc; PageNum pageNum; int slotNum; if ((rc = rid.GetPageNum(pageNum))) return rc; if ((rc = rid.GetSlotNum(slotNum))) return rc; char *data; if ((rc = record.GetData(data))) return rc; printf("RID: (%d,%d)\n", pageNum, slotNum); vector<SM_ActiveAttr>::iterator pAttr; int *pNullBitmap = (int *)(data + recordSize - sizeof(int)); for (pAttr = attributes->begin(); pAttr != attributes->end(); ++pAttr) { SM_Attribute *attr = &pAttr->record; if (*pNullBitmap & (1 << attr->number)) printf(" %s: Null\n", attr->attrName); else if (attr->attrType == INT) printf(" %s: %d\n", attr->attrName, *(int *)(data + attr->attrOffset)); else if (attr->attrType == FLOAT) printf(" %s: %f\n", attr->attrName, *(float *)(data + attr->attrOffset)); else if (attr->attrType == STRING) printf(" %s: %s\n", attr->attrName, data + attr->attrOffset); } printf("\n"); recordCount++; } if (rc != RM_ERR_EOF) return rc; if ((rc = allScan.CloseScan())) return rc; printf("\nTotal %d records.\n", recordCount); 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; }