BadgerDB
|
00001 #include "utility.h" 00002 #include <cstring> 00003 #include "catalog.h" 00004 #include "exceptions/relation_not_found_exception.h" 00005 #include "exceptions/relation_already_exists_exception.h" 00006 #include "exceptions/duplicate_attribute_exception.h" 00007 #include "exceptions/end_of_file_exception.h" 00008 #include "exceptions/bad_param_exception.h" 00009 00010 extern badgerdb::AttrCatalog *attrCat; // Pointer to the attribute catalog object 00011 00012 namespace badgerdb { 00013 00014 // extern variables that are instantianted in the main program. 00015 00016 RelCatalog::RelCatalog(BufMgr *bufferMgr) 00017 :FileScan(RELCATNAME, bufferMgr) 00018 { 00019 } 00020 00021 void RelCatalog::getInfo(const std::string &relation, RelDesc &reldesc) 00022 { 00023 RecordId rid; 00024 00025 startScan(0, relation.size() + 1, STRING, relation, EQ); 00026 00027 try 00028 { 00029 scanNext(rid); 00030 } 00031 catch(EndOfFileException e) 00032 { 00033 throw RelationNotFoundException(); 00034 } 00035 00036 std::string recordStr = getRecord(); 00037 00038 assert(sizeof(RelDesc) == recordStr.size()); 00039 00040 memcpy(&reldesc, recordStr.c_str(), sizeof(RelDesc)); 00041 00042 endScan(); 00043 } 00044 00045 void RelCatalog::addInfo(RelDesc &reldesc) 00046 { 00047 RecordId outRid; 00048 std::string new_data(reinterpret_cast<char*>(&reldesc), sizeof(RelDesc)); 00049 insertRecord(new_data, outRid); 00050 } 00051 00052 void RelCatalog::removeInfo(const std::string & relation) 00053 { 00054 RecordId rid; 00055 00056 startScan(0, relation.size() + 1, STRING, relation, EQ); 00057 00058 try 00059 { 00060 scanNext(rid); 00061 } 00062 catch(EndOfFileException e) 00063 { 00064 throw RelationNotFoundException(); 00065 } 00066 00067 endScan(); 00068 00069 deleteRecord(rid); 00070 } 00071 00072 void RelCatalog::createRel(const std::string &relation, int attrCnt, const attrInfo attrList[]) 00073 { 00074 RelDesc rd; 00075 AttrDesc ad; 00076 00077 if(relation.size() >= sizeof(rd.relName)) 00078 throw BadParamException(); 00079 00080 // make sure the relation doesn't already exist 00081 try 00082 { 00083 getInfo(relation, rd); 00084 throw RelationAlreadyExistsException(); 00085 } 00086 catch(RelationNotFoundException &e) 00087 { 00088 } 00089 00090 //make sure there are no duplicate attribute names 00091 00092 if(attrCnt > 1) 00093 { 00094 for(int i = 1; i < attrCnt; i++) 00095 { 00096 for(int j = 0; j < i; j++) 00097 { 00098 if(strcmp(attrList[i].attrName, attrList[j].attrName) == 0) 00099 throw DuplicateAttributeException(); 00100 } 00101 } 00102 } 00103 00104 strcpy(rd.relName, relation.c_str()); 00105 rd.attrCnt = attrCnt; 00106 rd.indexCnt = 0; 00107 00108 addInfo(rd); 00109 00110 strcpy(ad.relName, relation.c_str()); 00111 int offset = 0; 00112 00113 for(int i = 0; i < attrCnt; i++) 00114 { 00115 if (strlen(attrList[i].attrName) >= sizeof(ad.attrName)) 00116 throw BadParamException(); 00117 00118 //TODO::remove the following offset computation, get it from the user 00119 strcpy(ad.attrName, attrList[i].attrName); 00120 ad.attrOffset = offset; 00121 ad.attrType = attrList[i].attrType; 00122 ad.attrLen = attrList[i].attrLen; 00123 ad.indexed = false; 00124 00125 attrCat->addInfo(ad); 00126 00127 offset += ad.attrLen; 00128 } 00129 00130 //create relation file 00131 PageFile relFile(relation, true); 00132 00133 //so that select on these relations show updated information 00134 attrCat->flushFile(); 00135 this->flushFile(); 00136 } 00137 00138 // 00139 // Destroys a relation. It performs the following steps: 00140 // 00141 // removes the catalog entry for the relation 00142 // destroys the heap file containing the tuples in the relation 00143 // 00144 // Returns: 00145 // OK on success 00146 // error code otherwise 00147 // 00148 00149 void RelCatalog::destroyRel(const std::string & relation) 00150 { 00151 if (relation.empty() || relation == RELCATNAME || relation == ATTRCATNAME) 00152 throw BadParamException(); 00153 00154 // delete attrcat entries 00155 attrCat->dropRelation(relation); 00156 00157 // delete entry from relcat 00158 removeInfo(relation); 00159 00160 File::remove(relation); 00161 00162 //so that select on these relations show updated information 00163 attrCat->flushFile(); 00164 this->flushFile(); 00165 } 00166 00167 00168 RelCatalog::~RelCatalog() 00169 { 00170 } 00171 00172 // 00173 // Retrieves and prints the catalog information for the relation. 00174 // If no relation is given (relation is NULL), then it lists all 00175 // the relations in the database, along with the width in bytes of the 00176 // relation, the number of attributes in the relation, and the number of 00177 // attributes that are indexed. If a relation is given, then it lists 00178 // all of the attributes of the relation, as well as its type, length, 00179 // and offset, whether it's indexed or not, and its index number. 00180 // 00181 // Returns: 00182 // OK on success 00183 // error code otherwise 00184 // 00185 00186 void RelCatalog::help(const std::string &relation) 00187 { 00188 if(relation.empty()) 00189 { 00190 Utilities::Print(std::string(RELCATNAME)); 00191 return; 00192 } 00193 00194 RelDesc rd; 00195 AttrDesc *attrs; 00196 int attrCnt; 00197 00198 // get relation data 00199 00200 try 00201 { 00202 getInfo(relation, rd); 00203 } 00204 catch(RelationNotFoundException &e) 00205 { 00206 return; 00207 } 00208 00209 // get attribute data 00210 00211 attrCat->getRelInfo(relation, attrCnt, attrs); 00212 00213 // print relation information 00214 00215 std::cout << "Relation name: " << rd.relName << " (" << rd.attrCnt << " attributes, " << rd.indexCnt << " indexed)" << std::endl << std::endl; 00216 00217 printf("%16.16s Off T Len I\n\n", "Attribute name"); 00218 for(int i = 0; i < attrCnt; i++) 00219 { 00220 Datatype t = (Datatype)attrs[i].attrType; 00221 printf("%16.16s %3d %c %3d %c\n", attrs[i].attrName, attrs[i].attrOffset, (t == INTEGER ? 'i' : (t == DOUBLE ? 'f' : 's')), 00222 attrs[i].attrLen, (attrs[i].indexed ? 'Y' : 'N')); 00223 } 00224 00225 delete [] attrs; 00226 } 00227 00228 // 00229 // Creates an index on attribute `attrName' of relation `relation.' This 00230 // function assumes (but does not verify) that relation is an empty relation. 00231 // It performs the following steps: 00232 // 00233 // verifies the existance of relation relname and attribute attrname 00234 // creates the appropriate index file 00235 // updates the index count in relcat 00236 // 00237 // Returns: 00238 // OK on success 00239 // error code otherwise 00240 // 00241 00242 void RelCatalog::addIndex(const std::string &relation, const std::string &attrName) 00243 { 00244 RelDesc rd; 00245 00246 // get existing relation data 00247 getInfo(relation, rd); 00248 00249 // create index file 00250 attrCat->addIndex(relation, attrName); 00251 00252 // modify indexCnt in relcat 00253 rd.indexCnt++; 00254 00255 removeInfo(relation); 00256 addInfo(rd); 00257 00258 //so that select on these relations show updated information 00259 attrCat->flushFile(); 00260 this->flushFile(); 00261 } 00262 00263 // 00264 // Drops an index. 00265 // 00266 // Returns: 00267 // OK on success 00268 // error code otherwise 00269 // 00270 00271 void RelCatalog::dropIndex(const std::string &relation, const std::string &attrName) 00272 { 00273 RelDesc rd; 00274 00275 // get existing relation data 00276 getInfo(relation, rd); 00277 00278 // destroy index file 00279 attrCat->dropIndex(relation, attrName); 00280 00281 // modify indexCnt in relcat 00282 rd.indexCnt--; 00283 00284 removeInfo(relation); 00285 addInfo(rd); 00286 00287 //so that select on these relations show updated information 00288 attrCat->flushFile(); 00289 this->flushFile(); 00290 } 00291 00292 }