USGS

Isis 3.0 Object Programmers' Reference

Home

Database.cpp

Go to the documentation of this file.
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 }