BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/src/relcat.cpp
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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends