Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:32:02

0001 #include "OnlineDB/EcalCondDB/interface/LMFUnique.h"
0002 #include <iomanip>
0003 
0004 using namespace std;
0005 using namespace oracle::occi;
0006 
0007 LMFUnique::~LMFUnique() {}
0008 
0009 std::string LMFUnique::sequencePostfix(const Tm& t) {
0010   std::string ts = t.str();
0011   return ts.substr(2, 2);
0012 }
0013 
0014 LMFUnique& LMFUnique::setString(std::string key, std::string value) {
0015   // check if this key exists
0016   std::map<std::string, std::string>::const_iterator i = m_stringFields.find(key);
0017   if (i != m_stringFields.end()) {
0018     // the key exist: check if it changed: reset the ID of the object
0019     if (i->second != value) {
0020       m_stringFields[key] = value;
0021       m_ID = 0;
0022     }
0023   } else {
0024     // create this key and reset the ID of the object
0025     m_stringFields[key] = value;
0026     m_ID = 0;
0027   }
0028   return *this;
0029 }
0030 
0031 LMFUnique& LMFUnique::setInt(std::string key, int value) {
0032   // check if this key exists
0033   std::map<std::string, int>::const_iterator i = m_intFields.find(key);
0034   if (i != m_intFields.end()) {
0035     // the key exist: check if it changed: reset the ID of the object
0036     if (i->second != value) {
0037       m_intFields[key] = value;
0038       m_ID = 0;
0039     }
0040   } else {
0041     // create this key and reset the ID of the object
0042     m_intFields[key] = value;
0043     m_ID = 0;
0044   }
0045   return *this;
0046 }
0047 
0048 void LMFUnique::attach(std::string name, LMFUnique* u) {
0049   std::map<std::string, LMFUnique*>::const_iterator i = m_foreignKeys.find(name);
0050   if (i != m_foreignKeys.end()) {
0051     if (i->second != u) {
0052       m_foreignKeys[name] = u;
0053       m_ID = 0;
0054     }
0055   } else {
0056     m_foreignKeys[name] = u;
0057     m_ID = 0;
0058   }
0059 }
0060 
0061 std::list<std::unique_ptr<LMFUnique>> LMFUnique::fetchAll() const noexcept(false) {
0062   /*
0063     Returns a list of pointers to DB objects
0064    */
0065   std::list<std::unique_ptr<LMFUnique>> l;
0066   this->checkConnection();
0067 
0068   try {
0069     Statement* stmt = m_conn->createStatement();
0070     std::string sql = fetchAllSql(stmt);
0071     if (!sql.empty()) {
0072       if (m_debug) {
0073         cout << m_className + ": Query " + sql << endl;
0074       }
0075       ResultSet* rset = stmt->executeQuery();
0076       while (rset->next() != 0) {
0077         LMFUnique* o = createObject();
0078         if (m_debug) {
0079           o->debug();
0080         }
0081         if (o != nullptr) {
0082           o->setByID(rset->getInt(1));
0083           if (m_debug) {
0084             o->dump();
0085           }
0086           try {
0087             l.emplace_back(o);
0088           } catch (std::exception& e) {
0089             throw(std::runtime_error(m_className + "::fetchAll:  " + e.what()));
0090           }
0091         }
0092       }
0093     }
0094     m_conn->terminateStatement(stmt);
0095   } catch (SQLException& e) {
0096     throw(std::runtime_error(m_className + "::fetchAll:  " + e.getMessage()));
0097   }
0098   if (m_debug) {
0099     cout << m_className << ": list size = " << l.size() << endl;
0100   }
0101   return l;
0102 }
0103 
0104 void LMFUnique::dump() const { dump(0); }
0105 
0106 void LMFUnique::dump(int n) const {
0107   /*
0108     This method is used to dump the content of an object 
0109     Indent data if the object is contained inside another object
0110   */
0111   std::string m_indent = "";
0112   std::string m_trail = "";
0113   m_trail.resize(70 - 31 - n * 2, '#');
0114   m_indent.resize(n * 2, ' ');
0115   m_indent += "|";
0116   // start of object
0117   cout << m_indent << "#################" << setw(15) << m_className << " " << m_trail << endl;
0118   cout << m_indent << "Address: " << this << endl;
0119   cout << m_indent << "Connection params : " << m_env << ", " << m_conn << endl;
0120   // object ID in the DB
0121   cout << m_indent << "ID" << setw(18) << ": " << m_ID;
0122   if (m_ID == 0) {
0123     cout << " *** NULL ID ***";
0124   }
0125   if (!isValid()) {
0126     cout << " INVALID ***";
0127   }
0128   cout << endl;
0129   // iterate over string fields
0130   std::map<std::string, std::string>::const_iterator is = m_stringFields.begin();
0131   std::map<std::string, std::string>::const_iterator es = m_stringFields.end();
0132   while (is != es) {
0133     std::string key = is->first;
0134     cout << m_indent << key << setw(20 - key.length()) << ": " << is->second << endl;
0135     is++;
0136   }
0137   // iterate over integer fields
0138   std::map<std::string, int>::const_iterator ii = m_intFields.begin();
0139   std::map<std::string, int>::const_iterator ei = m_intFields.end();
0140   while (ii != ei) {
0141     std::string key = ii->first;
0142     cout << m_indent << key << setw(20 - key.length()) << ": " << ii->second << endl;
0143     ii++;
0144   }
0145   cout << m_indent << "#################" << setw(15) << m_className << " " << m_trail << endl;
0146   // iterate over foreign keys
0147   std::map<std::string, LMFUnique*>::const_iterator ik = m_foreignKeys.begin();
0148   std::map<std::string, LMFUnique*>::const_iterator ek = m_foreignKeys.end();
0149   m_indent.clear();
0150   m_indent.resize((n + 1) * 2, ' ');
0151   while (ik != ek) {
0152     cout << m_indent << "Foreign Key: " << ik->first << endl;
0153     ik->second->dump(n + 1);
0154     ik++;
0155   }
0156 }
0157 
0158 bool LMFUnique::exists() {
0159   fetchID();
0160   bool ret = false;
0161   if (m_ID > 0) {
0162     ret = true;
0163   }
0164   return ret;
0165 }
0166 
0167 std::string LMFUnique::fetchAllSql(Statement* stmt) const {
0168   /* this method should setup a Statement to select the unique IDs of the
0169      objects to return */
0170   return "";
0171 }
0172 
0173 LMFUnique* LMFUnique::createObject() const {
0174   /* this method should return a pointer to a newly created object */
0175   return nullptr;
0176 }
0177 
0178 std::string LMFUnique::getString(std::string s) const {
0179   std::string rs = "";
0180   std::map<std::string, std::string>::const_iterator i = m_stringFields.find(s);
0181   if (i != m_stringFields.end()) {
0182     rs = i->second;
0183   }
0184   return rs;
0185 }
0186 
0187 int LMFUnique::getInt(std::string s) const {
0188   // this should be better defined
0189   int ret = 0;
0190   std::map<std::string, int>::const_iterator i = m_intFields.find(s);
0191   if (i != m_intFields.end()) {
0192     ret = i->second;
0193   }
0194   return ret;
0195 }
0196 
0197 int LMFUnique::fetchID() noexcept(false) {
0198   /*
0199     This method fetch the ID of the object from the database according
0200     to the given specifications.
0201 
0202     It is assumed that there is only one object in the database with the
0203     given specifications. In case more than one object can be retrieved
0204     this method throws an exception.
0205 
0206     Since not all the specifications can define completely the object
0207     itself, at the end, we setup the object based on its ID.
0208    */
0209   // Return tag from memory if available
0210   if (m_ID) {
0211     return m_ID;
0212   }
0213 
0214   this->checkConnection();
0215 
0216   // fetch this ID
0217   try {
0218     Statement* stmt = m_conn->createStatement();
0219     // prepare the sql query
0220     std::string sql = fetchIdSql(stmt);
0221     if (!sql.empty()) {
0222       if (m_debug) {
0223         cout << m_className + ": Query " + sql << endl;
0224       }
0225 
0226       ResultSet* rset = stmt->executeQuery();
0227       if (rset->next() != 0) {
0228         m_ID = rset->getInt(1);
0229       } else {
0230         m_ID = 0;
0231       }
0232       if (m_debug) {
0233         cout << m_className + ": ID set to " << m_ID << endl;
0234       }
0235       int n = rset->getNumArrayRows();
0236       if (m_debug) {
0237         cout << m_className + ": Returned " << n << " rows" << endl;
0238       }
0239       if (n > 1) {
0240         throw(std::runtime_error(m_className + "::fetchID: too many rows returned " + "executing query " + sql));
0241         m_ID = 0;
0242       }
0243     }
0244     m_conn->terminateStatement(stmt);
0245   } catch (SQLException& e) {
0246     throw(std::runtime_error(m_className + "::fetchID:  " + e.getMessage()));
0247   }
0248   // given the ID of this object setup it completely
0249   if (m_ID > 0) {
0250     setByID(m_ID);
0251   }
0252   // if foreignKeys are there, set these objects too
0253   map<string, LMFUnique*>::iterator i = m_foreignKeys.begin();
0254   map<string, LMFUnique*>::iterator e = m_foreignKeys.end();
0255   while (i != e) {
0256     if (i->second->getID() == 0) {
0257       i->second->fetchID();
0258     }
0259     i++;
0260   }
0261   if (m_debug) {
0262     cout << m_className << ": fetchID:: returning " << m_ID << endl;
0263   }
0264   return m_ID;
0265 }
0266 
0267 void LMFUnique::setByID(int id) noexcept(false) {
0268   /*
0269     Given the ID of an object setup it
0270    */
0271   if (m_debug) {
0272     cout << m_className << ": Setting this object as ID = " << id << endl;
0273   }
0274   this->checkConnection();
0275   try {
0276     Statement* stmt = m_conn->createStatement();
0277     std::string sql = setByIDSql(stmt, id);
0278     if (sql.empty()) {
0279       throw(std::runtime_error(m_className + "::setByID: [empty sql])"));
0280     }
0281     if (m_debug) {
0282       cout << m_className + ": " + sql << endl;
0283     }
0284 
0285     ResultSet* rset = stmt->executeQuery();
0286     if (rset->next() != 0) {
0287       // setup the concrete object
0288       getParameters(rset);
0289       m_ID = id;
0290       if (m_debug) {
0291         cout << m_className + ": Setting done. ID set to " << m_ID << endl;
0292       }
0293     } else {
0294       throw(std::runtime_error(m_className + "::setByID:  Given id is not in the database"));
0295     }
0296     m_conn->terminateStatement(stmt);
0297   } catch (SQLException& e) {
0298     throw(std::runtime_error(m_className + "::setByID:  " + e.getMessage()));
0299   }
0300 }
0301 
0302 int LMFUnique::writeForeignKeys() noexcept(false) {
0303   std::map<std::string, LMFUnique*>::const_iterator i = m_foreignKeys.begin();
0304   std::map<std::string, LMFUnique*>::const_iterator e = m_foreignKeys.end();
0305   int count = 0;
0306   while (i != e) {
0307     if (i->second->getID() == 0) {
0308       i->second->writeDB();
0309       count++;
0310     }
0311     i++;
0312   }
0313   return count;
0314 }
0315 
0316 int LMFUnique::writeDB() noexcept(false) {
0317   clock_t start = 0;
0318   clock_t end = 0;
0319   if (_profiling) {
0320     start = clock();
0321   }
0322   // write the associated objects first (foreign keys must exist before use)
0323   writeForeignKeys();
0324   // see if this data is already in the DB
0325   if (!(this->fetchID())) {
0326     // check the connectioin
0327     this->checkConnection();
0328 
0329     // write new tag to the DB
0330     std::string sql = "";
0331     try {
0332       Statement* stmt = m_conn->createStatement();
0333 
0334       sql = writeDBSql(stmt);
0335       if (!sql.empty()) {
0336         if (m_debug) {
0337           cout << m_className + ": " + sql << endl;
0338         }
0339         stmt->executeUpdate();
0340       }
0341       m_conn->commit();
0342       m_conn->terminateStatement(stmt);
0343     } catch (SQLException& e) {
0344       debug();
0345       dump();
0346       throw(std::runtime_error(m_className + "::writeDB:  " + e.getMessage() + " while executing query " + sql));
0347     }
0348     // now get the id
0349     if (this->fetchID() == 0) {
0350       throw(std::runtime_error(m_className + "::writeDB:  Failed to write"));
0351     }
0352   }
0353   if (_profiling) {
0354     end = clock();
0355     if (m_debug) {
0356       std::cout << m_className << ":: Spent time in writeDB:" << ((double)(end - start)) / CLOCKS_PER_SEC << " s"
0357                 << endl;
0358     }
0359   }
0360   return m_ID;
0361 }