|
Isis 3.0 Object Programmers' Reference |
Home |
00001 00022 #include <string> 00023 #include <vector> 00024 #include <iostream> 00025 #include "DbProfile.h" 00026 #include "Database.h" 00027 #include "DatabaseFactory.h" 00028 #include "IString.h" 00029 00030 #include <QStringList> 00031 #include <QSqlError> 00032 00033 using namespace std; 00034 00035 namespace Isis { 00036 00037 QString Database::_actualConnectionName = ""; 00038 00046 Database::Database() : QSqlDatabase(), _name("") { } 00047 00066 Database::Database(Database::Access dbConn) : QSqlDatabase(init()), _name("") { 00067 _name = _actualConnectionName; 00068 if((dbConn == Connect) && isValid()) { 00069 if(!open()) { 00070 QString mess = "Failed to open database default database [" + _name; 00071 tossDbError(mess, _FILEINFO_); 00072 } 00073 } 00074 // Name cannot be set, so set to determined name 00075 } 00076 00088 Database::Database(const QString &name, Database::Access dbConn) : 00089 QSqlDatabase(init(name)), _name(name) { 00090 _name = _actualConnectionName; 00091 if((dbConn == Connect) && isValid()) { 00092 if(!open()) { 00093 QString mess = "Failed to open database specified as " + _name; 00094 tossDbError(mess, _FILEINFO_); 00095 } 00096 } 00097 } 00098 00117 Database::Database(const QString &connName, const QString &driverType) : 00118 QSqlDatabase(init(connName, driverType)), _name(connName) { 00119 _name = _actualConnectionName; 00120 } 00121 00137 Database::Database(const DbProfile &profile, Database::Access dbConn) : 00138 QSqlDatabase(init(profile, DoNotConnect)), 00139 _name(profile.Name()) { 00140 _name = _actualConnectionName; 00141 if((dbConn == Connect) && isValid()) { 00142 if(!open()) { 00143 QString mess = "Failed to open database with profile " + _name; 00144 tossDbError(mess, _FILEINFO_); 00145 } 00146 } 00147 } 00148 00159 Database::Database(const QSqlDatabase &other, const QString &newName) : 00160 QSqlDatabase(QSqlDatabase::cloneDatabase(other, newName)), 00161 _name(newName) { } 00162 00163 00173 Database::~Database() { 00174 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00175 if(!factory->isPersistant(_name)) { 00176 if(isOpen()) { 00177 close(); 00178 } 00179 factory->remove(_name); 00180 } 00181 } 00182 00204 void Database::makePersistant() { 00205 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00206 if(!factory->isPersistant(_name)) { 00207 factory->add(*this, _name); 00208 } 00209 return; 00210 } 00211 00220 bool Database::isPersistant() const { 00221 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00222 return (factory->isPersistant(_name)); 00223 } 00224 00239 void Database::setAsDefault() { 00240 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00241 if(!factory->isPersistant(_name)) { 00242 factory->add(*this, _name); 00243 } 00244 factory->setDefault(_name); 00245 return; 00246 } 00247 00267 void Database::remove(const QString &name) { 00268 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00269 factory->destroy(name); 00270 return; 00271 } 00272 00288 bool Database::addAccessConfig(const QString &confFile) { 00289 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00290 return (factory->addAccessProfile(confFile)); 00291 } 00292 00325 DbProfile Database::getProfile(const QString &name) { 00326 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00327 return (factory->getProfile(name)); 00328 } 00329 00356 QSqlDatabase Database::init(const QString &connName, 00357 const QString &driverType) { 00358 00359 _actualConnectionName = connName; 00360 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00361 00362 // First test for condition where both name and type are not provided. 00363 // This tests for the default profile and returns it if it exists, 00364 // otherwise it returns a default database. 00365 if(connName.isEmpty() && driverType.isEmpty()) { 00366 if(factory->isAvailable(factory->getDefault())) { 00367 _actualConnectionName = factory->getDefault(); 00368 return (factory->create(_actualConnectionName)); 00369 } 00370 00371 // No default is established so retreive the default profile 00372 DbProfile profile = factory->getProfile(); 00373 if(profile.isValid()) { 00374 return (init(profile, DoNotConnect)); 00375 } 00376 } 00377 00378 // If only the name and no driver is provided, get an existing connection 00379 if((!connName.isEmpty()) && (driverType.isEmpty())) { 00380 if(factory->isAvailable(connName)) { 00381 _actualConnectionName = connName; 00382 return (factory->create(connName)); 00383 } 00384 else { 00385 // See if the database exists by profile 00386 DbProfile profile = factory->getProfile(connName); 00387 return (init(profile, DoNotConnect)); 00388 } 00389 } 00390 00391 // Finally, a driver and optional name is provided. This condition sets up 00392 // a named database for subsequent definition later 00393 return (factory->create(driverType, connName)); 00394 } 00395 00396 00416 QSqlDatabase Database::init(const DbProfile &profile, Database::Access dbConn) { 00417 if(!profile.isValid()) { 00418 ostringstream mess; 00419 mess << "Database/profile [" << profile.Name() << "] is not valid!" << ends; 00420 throw IException(IException::Programmer, mess.str(), _FILEINFO_); 00421 } 00422 00423 _actualConnectionName = profile.Name(); 00424 DatabaseFactory *factory = DatabaseFactory::getInstance(); 00425 00426 // initialize the database 00427 try { 00428 00429 // If we reach here, it is a valid profile. Create the database and 00430 // return it as initialized from the profile contents 00431 QSqlDatabase db = factory->create(profile("Type"), profile("Name")); 00432 _actualConnectionName = profile("Name"); 00433 configureAccess(db, profile); 00434 00435 // Go ahead and connect if requested 00436 if(dbConn == Connect) { 00437 if(!db.open()) { 00438 QString mess = "Failed to connect to database using profile " + 00439 profile("Name"); 00440 tossDbError(mess, _FILEINFO_); 00441 } 00442 } 00443 return (db); 00444 } 00445 catch(IException &ie) { 00446 QString mess = "Unable to create database from " + profile.Name(); 00447 throw IException(ie, IException::User, mess, _FILEINFO_); 00448 } 00449 catch(...) { 00450 QString mess = "Unknown exception while creating database from profile " 00451 + profile.Name(); 00452 throw IException(IException::User, mess, _FILEINFO_); 00453 } 00454 } 00455 00468 void Database::configureAccess(QSqlDatabase &db, const DbProfile &profile) { 00469 if(profile.exists("Host")) { 00470 db.setHostName(profile("Host")); 00471 } 00472 00473 if(profile.exists("DbName")) { 00474 db.setDatabaseName(profile("DbName")); 00475 } 00476 00477 if(profile.exists("User")) { 00478 db.setUserName(profile("User")); 00479 } 00480 00481 if(profile.exists("Password")) { 00482 db.setPassword(profile("Password")); 00483 } 00484 00485 if(profile.exists("Port")) { 00486 bool ok; 00487 db.setPort(profile("Port").toInt(&ok)); 00488 if(!ok) { 00489 ostringstream mess; 00490 mess << "Invalid port number [" << profile("Port") << "] in profile " 00491 << profile("Name") << ends; 00492 throw IException(IException::User, mess.str().c_str(), _FILEINFO_); 00493 } 00494 } 00495 00496 if(profile.exists("Options")) { 00497 db.setConnectOptions(profile("Options")); 00498 } 00499 return; 00500 } 00501 00512 Database Database::clone(const QString &name) const { 00513 return (Database(*this, name)); 00514 } 00515 00524 QStringList Database::getTables() const { 00525 return (tables(QSql::Tables)); 00526 } 00527 00537 QStringList Database::getViews() const { 00538 return (tables(QSql::Views)); 00539 } 00540 00549 QStringList Database::getSystemTables() const { 00550 return (tables(QSql::SystemTables)); 00551 } 00552 00563 void Database::tossDbError(const QString &message, const char *f, int l) const { 00564 QString errmess = message + " - DatabaseError = " + 00565 lastError().text(); 00566 throw IException(IException::Programmer, errmess, f, l); 00567 } 00568 00569 }