CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/OnlineDB/EcalCondDB/src/LMFUnique.cc

Go to the documentation of this file.
00001 #include "OnlineDB/EcalCondDB/interface/LMFUnique.h"
00002 #include <iomanip>
00003 
00004 using namespace std;
00005 using namespace oracle::occi;
00006 
00007 LMFUnique::~LMFUnique() {
00008 }
00009 
00010 std::string LMFUnique::sequencePostfix(Tm t) {
00011   std::string ts = t.str();
00012   return ts.substr(2, 2);
00013 }
00014 
00015 LMFUnique& LMFUnique::setString(std::string key, std::string value) {
00016   // check if this key exists
00017   std::map<std::string, std::string>::const_iterator i = 
00018     m_stringFields.find(key);
00019   if (i != m_stringFields.end()) {
00020     // the key exist: check if it changed: reset the ID of the object
00021     if (i->second != value) {
00022       m_stringFields[key] = value;
00023       m_ID = 0;
00024     }
00025   } else {
00026     // create this key and reset the ID of the object
00027     m_stringFields[key] = value;
00028     m_ID = 0;    
00029   }
00030   return *this;
00031 }
00032 
00033 LMFUnique& LMFUnique::setInt(std::string key, int value) {
00034   // check if this key exists
00035   std::map<std::string, int>::const_iterator i = m_intFields.find(key);
00036   if (i != m_intFields.end()) {
00037     // the key exist: check if it changed: reset the ID of the object
00038     if (i->second != value) {
00039       m_intFields[key] = value;
00040       m_ID = 0;
00041     }
00042   } else {
00043     // create this key and reset the ID of the object
00044     m_intFields[key] = value;
00045     m_ID = 0;    
00046   }
00047   return *this;
00048 }
00049 
00050 void LMFUnique::attach(std::string name, LMFUnique *u) {
00051   std::map<std::string, LMFUnique *>::const_iterator i = 
00052     m_foreignKeys.find(name);
00053   if (i != m_foreignKeys.end()) {
00054     if (i->second != u) {
00055       m_foreignKeys[name] = u;
00056       m_ID = 0;
00057     }
00058   } else {
00059     m_foreignKeys[name] = u;
00060     m_ID = 0;
00061   }
00062 }
00063 
00064 boost::ptr_list<LMFUnique> LMFUnique::fetchAll() const  
00065   throw(std::runtime_error)
00066 {
00067   /*
00068     Returns a list of pointers to DB objects
00069    */
00070   boost::ptr_list<LMFUnique> l;
00071   this->checkConnection();
00072 
00073   try {
00074     Statement* stmt = m_conn->createStatement();
00075     std::string sql = fetchAllSql(stmt);
00076     if (sql != "") {
00077       if (m_debug) {
00078         cout << m_className + ": Query " + sql << endl;
00079       }
00080       ResultSet* rset = stmt->executeQuery();
00081       while (rset->next() != 0) {
00082         LMFUnique *o = createObject();
00083         if (m_debug) {
00084           o->debug();
00085         }
00086         if (o != NULL) {
00087           o->setByID(rset->getInt(1));
00088           if (m_debug) {
00089             o->dump();
00090           }
00091           try {
00092             l.push_back(o);
00093           }
00094           catch (boost::bad_pointer &e) {
00095             throw(std::runtime_error(m_className + "::fetchAll:  " + 
00096                                      e.what()));
00097           }
00098         }
00099       }
00100     }
00101     m_conn->terminateStatement(stmt);
00102   }
00103   catch (SQLException &e) {
00104     throw(std::runtime_error(m_className + "::fetchAll:  "+e.getMessage()));
00105   }
00106   if (m_debug) {
00107     cout << m_className << ": list size = " << l.size() << endl;
00108   }
00109   return l;
00110 }
00111 
00112 void LMFUnique::dump() const {
00113   dump(0);
00114 }
00115 
00116 void LMFUnique::dump(int n) const {
00117   /*
00118     This method is used to dump the content of an object 
00119     Indent data if the object is contained inside another object
00120   */
00121   std::string m_indent = "";
00122   std::string m_trail = "";
00123   m_trail.resize(70 - 31 - n * 2, '#');
00124   m_indent.resize(n*2, ' ');
00125   m_indent += "|";
00126   // start of object
00127   cout << m_indent << "#################" << setw(15) << m_className 
00128        << " " << m_trail << endl;
00129   cout << m_indent << "Address: " << this << endl;
00130   cout << m_indent << "Connection params : " << m_env << ", " << m_conn << endl;
00131   // object ID in the DB
00132   cout << m_indent << "ID" << setw(18) << ": " << m_ID;
00133   if (m_ID == 0) {
00134     cout << " *** NULL ID ***";
00135   }
00136   if (!isValid()) {
00137     cout << " INVALID ***";
00138   }
00139   cout << endl;
00140   // iterate over string fields
00141   std::map<std::string, std::string>::const_iterator is = 
00142     m_stringFields.begin();
00143   std::map<std::string, std::string>::const_iterator es = 
00144     m_stringFields.end();
00145   while (is != es) {
00146     std::string key = is->first;
00147     cout << m_indent << key << setw(20 - key.length()) << ": " << is->second
00148          << endl;
00149     is++;
00150   }
00151   // iterate over integer fields
00152   std::map<std::string, int>::const_iterator ii = m_intFields.begin();
00153   std::map<std::string, int>::const_iterator ei = m_intFields.end();
00154   while (ii != ei) {
00155     std::string key = ii->first;
00156     cout << m_indent << key << setw(20 - key.length()) << ": " << ii->second
00157          << endl;
00158     ii++;
00159   }
00160   cout << m_indent << "#################" << setw(15) << m_className 
00161        << " " << m_trail << endl;
00162   // iterate over foreign keys
00163   std::map<std::string, LMFUnique*>::const_iterator ik = m_foreignKeys.begin();
00164   std::map<std::string, LMFUnique*>::const_iterator ek = m_foreignKeys.end();
00165   m_indent.clear();
00166   m_indent.resize((n + 1) * 2, ' ');
00167   while (ik != ek) {
00168     cout << m_indent << "Foreign Key: " << ik->first << endl;
00169     ik->second->dump(n + 1);
00170     ik++;
00171   }
00172 }
00173 
00174 bool LMFUnique::exists() {
00175   fetchID();
00176   bool ret = false;
00177   if (m_ID > 0) {
00178     ret = true;
00179   }
00180   return ret;
00181 }
00182 
00183 std::string LMFUnique::fetchAllSql(Statement *stmt) const {
00184   /* this method should setup a Statement to select the unique IDs of the
00185      objects to return */
00186   return "";
00187 }
00188 
00189 LMFUnique* LMFUnique::createObject() const {
00190   /* this method should return a pointer to a newly created object */
00191   return NULL;
00192 }
00193 
00194 std::string LMFUnique::getString(std::string s) const {
00195   std::string rs = "";
00196   std::map<std::string, std::string>::const_iterator i = m_stringFields.find(s);
00197   if (i != m_stringFields.end()) {
00198     rs = i->second;
00199   }
00200   return rs;
00201 }
00202 
00203 int LMFUnique::getInt(std::string s) const {
00204   // this should be better defined
00205   int ret = 0;
00206   std::map<std::string, int>::const_iterator i = m_intFields.find(s);
00207   if (i != m_intFields.end()) {
00208     ret = i->second;
00209   }
00210   return ret;
00211 }
00212 
00213 int LMFUnique::fetchID()
00214   throw(std::runtime_error)
00215 {
00216   /*
00217     This method fetch the ID of the object from the database according
00218     to the given specifications.
00219 
00220     It is assumed that there is only one object in the database with the
00221     given specifications. In case more than one object can be retrieved
00222     this method throws an exception.
00223 
00224     Since not all the specifications can define completely the object
00225     itself, at the end, we setup the object based on its ID.
00226    */
00227   // Return tag from memory if available
00228   if (m_ID) {
00229     return m_ID;
00230   }
00231  
00232   this->checkConnection();
00233 
00234   // fetch this ID
00235   try {
00236     Statement* stmt = m_conn->createStatement();
00237     // prepare the sql query
00238     std::string sql = fetchIdSql(stmt);
00239     if (sql != "") {
00240       if (m_debug) {
00241         cout << m_className + ": Query " + sql << endl;
00242       }
00243       
00244       ResultSet* rset = stmt->executeQuery();
00245       if (rset->next() != 0) {
00246         m_ID = rset->getInt(1);
00247       } else {
00248         m_ID = 0;
00249       }
00250       if (m_debug) {
00251         cout << m_className + ": ID set to " << m_ID << endl;
00252       }
00253       int n = rset->getNumArrayRows();
00254       if (m_debug) {
00255         cout << m_className + ": Returned " << n << " rows"  << endl;
00256       }
00257       if (n > 1) {
00258         throw(std::runtime_error(m_className + "::fetchID: too many rows returned " +
00259                             "executing query " + sql));
00260         m_ID = 0;
00261       }
00262     }
00263     m_conn->terminateStatement(stmt);
00264   } catch (SQLException &e) {
00265     throw(std::runtime_error(m_className + "::fetchID:  "+e.getMessage()));
00266   }
00267   // given the ID of this object setup it completely
00268   if (m_ID > 0) {
00269     setByID(m_ID);
00270   }
00271   // if foreignKeys are there, set these objects too
00272   map<string, LMFUnique*>::iterator i = m_foreignKeys.begin();
00273   map<string, LMFUnique*>::iterator e = m_foreignKeys.end();
00274   while (i != e) {
00275     if (i->second->getID() == 0) {
00276       i->second->fetchID();
00277     }
00278     i++;
00279   }
00280   if (m_debug) {
00281     cout << m_className << ": fetchID:: returning " << m_ID << endl;
00282   }
00283   return m_ID;
00284 }
00285 
00286 void LMFUnique::setByID(int id) 
00287   throw(std::runtime_error)
00288 {
00289   /*
00290     Given the ID of an object setup it
00291    */
00292   if (m_debug) {
00293     cout << m_className << ": Setting this object as ID = " << id << endl;
00294   }
00295   this->checkConnection();
00296   try {
00297     Statement* stmt = m_conn->createStatement();
00298     std::string sql = setByIDSql(stmt, id);
00299     if (sql == "") {
00300       throw(std::runtime_error(m_className + "::setByID: [empty sql])"));
00301     }
00302     if (m_debug) {
00303       cout << m_className + ": " + sql << endl;
00304     }
00305 
00306     ResultSet* rset = stmt->executeQuery();
00307     if (rset->next() != 0) {
00308       // setup the concrete object
00309       getParameters(rset);
00310       m_ID = id;
00311       if (m_debug) {
00312         cout << m_className + ": Setting done. ID set to " << m_ID << endl;
00313       }
00314     } else {
00315       throw(std::runtime_error(m_className + "::setByID:  Given id is not in the database"));
00316     }
00317     m_conn->terminateStatement(stmt);
00318   } catch (SQLException &e) {
00319    throw(std::runtime_error(m_className + "::setByID:  "+e.getMessage()));
00320   }
00321 }
00322 
00323 int LMFUnique::writeForeignKeys() 
00324   throw(std::runtime_error)
00325 {
00326   std::map<std::string, LMFUnique*>::const_iterator i = m_foreignKeys.begin();
00327   std::map<std::string, LMFUnique*>::const_iterator e = m_foreignKeys.end();
00328   int count = 0;
00329   while (i != e) {
00330     if (i->second->getID() == 0) {
00331       i->second->writeDB();
00332       count++;
00333     }
00334     i++;
00335   }
00336   return count;
00337 }
00338 
00339 int LMFUnique::writeDB()
00340   throw(std::runtime_error)
00341 {
00342   clock_t start = 0;
00343   clock_t end = 0;
00344   if (_profiling) {
00345     start = clock();
00346   }
00347   // write the associated objects first (foreign keys must exist before use)
00348   writeForeignKeys();
00349   // see if this data is already in the DB
00350   if (!(this->fetchID())) { 
00351     // check the connectioin
00352     this->checkConnection();
00353     
00354     // write new tag to the DB
00355     std::string sql = "";
00356     try {
00357       Statement* stmt = m_conn->createStatement();
00358       
00359       sql = writeDBSql(stmt);
00360       if (sql != "") {
00361         if (m_debug) {
00362           cout << m_className + ": " + sql << endl;
00363         }
00364         stmt->executeUpdate();
00365       }
00366       m_conn->commit();
00367       m_conn->terminateStatement(stmt);
00368     } catch (SQLException &e) {
00369       debug();
00370       dump();
00371       throw(std::runtime_error(m_className + "::writeDB:  " + e.getMessage() +
00372                                " while executing query " + sql));
00373     }
00374     // now get the id
00375     if (this->fetchID() == 0) {
00376       throw(std::runtime_error(m_className + "::writeDB:  Failed to write"));
00377     }
00378   }
00379   if (_profiling) {
00380     end = clock();
00381     if (m_debug) {
00382       std::cout << m_className << ":: Spent time in writeDB:" << 
00383         ((double) (end - start)) / CLOCKS_PER_SEC << " s" << endl;
00384     }
00385   }
00386   return m_ID;
00387 }
00388