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; }
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::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; }