Isis 3 Programmer Reference
DatabaseFactory.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include <cstdlib>
10#include <string>
11#include <vector>
12#include <iostream>
13
14using namespace std;
15
16#include <QDebug>
17#include <QString>
18#include <QStringList>
19#include <QCoreApplication>
20#include <QSqlDatabase>
21
22#include "DatabaseFactory.h"
23#include "DbAccess.h"
24#include "Preference.h"
25#include "FileName.h"
26#include "IString.h"
27
28namespace Isis {
29
30
31 DatabaseFactory *DatabaseFactory::_factory = 0;
32
57 DatabaseFactory::DatabaseFactory() : _defProfName(""), _profiles(),
58 _defDatabase(""), _dbList() {
59
60 // insure the drivers are being loaded
62 // Checks the existance of the Qt application core. This is required in order
63 // ensure database driver plugins are loaded - if they exist.
64 QCoreApplication *cApp = QCoreApplication::instance();
65 if(cApp == 0) {
66 static char **argv = 0;
67
68 if(!argv) {
69 argv = new char*[2];
70 argv[0] = new char[1024];
71 strcpy(argv[0], "DatabaseFactory");
72 argv[1] = 0;
73 }
74
75 static int argc = 1;
76 new QCoreApplication(argc, argv);
77 }
78
79 // Initializes
80 init();
81
82 // This ensures this singleton is shut down when the application exists,
83 // so existing database connections are terminated.
84 qAddPostRoutine(DieAtExit);
85 }
86
93
108 delete _factory;
109 _factory = 0;
110 return;
111 }
112
130
152 bool DatabaseFactory::addAccessProfile(const QString &profileFile) {
153 try {
154 FileName dbconf(profileFile);
155 if(dbconf.fileExists()) {
156 DbAccess acp(profileFile);
157
158 // Add the top level one - may be replaced
159 const DbProfile &topProf = acp.getProfile();
160 _profiles.add(topProf.Name(), topProf);
161
162 // Now add each individual one
163 for(int i = 0 ; i < acp.profileCount() ; i++) {
164 const DbProfile &newProf = acp.getProfile(i);
165 _profiles.add(newProf.Name(), newProf);
166 }
167
168 // See if a default exists
169 if(acp.exists("DefaultProfile")) {
170 _defProfName = acp.value("DefaultProfile");
171 }
172 return (true);
173 }
174 }
175 catch(...) {
176 // upon any failure, we were unsuccessful
177 return (false);
178 }
179
180 // File did not exist
181 return (false);
182 }
195 _profiles.add(profile.Name(), profile);
196 return;
197 }
198
207 std::vector<QString> DatabaseFactory::getProfileList() const {
208 std::vector<QString> plist;
209 for(int i = 0 ; i < _profiles.size() ; i++) {
210 plist.push_back(_profiles.key(i).ToQt());
211 }
212 return (plist);
213 }
214
235 DbProfile DatabaseFactory::getProfile(const QString &name) const {
236 QString profName(name);
237 if(profName.isEmpty()) profName = _defProfName;
238
239 // Refer to user access if provided
240 if(!_profiles.exists(profName)) {
241 return(DbProfile(profName));
242 }
243 else {
244 return (_profiles.get(profName));
245 }
246 }
247
260 std::vector<QString> DatabaseFactory::available() const {
261 Drivers drivers = getResourceList(true, true);
262 std::vector<QString> dblist;
263 for(int i = 0 ; i < drivers.size() ; i++) {
264 dblist.push_back(drivers.key(i).ToQt());
265 }
266 return (dblist);
267 }
268
279 bool DatabaseFactory::isDriverAvailable(const QString &dbname) const {
280 Drivers drivers = getResourceList(true, false);
281 if(!drivers.exists(dbname)) {
282 return (false);
283 }
284 return (QSqlDatabase::isDriverAvailable(drivers.get(dbname)));
285 }
286
297 bool DatabaseFactory::isAvailable(const QString &dbname) const {
298 Drivers dbdrivers = getResourceList(false, true);
299 QString name(dbname);
300 if(name.isEmpty()) {
301 name = _defDatabase;
302 }
303 return (dbdrivers.exists(name));
304 }
305
315 bool DatabaseFactory::isConnected(const QString &dbname) const {
316 QString name(dbname);
317 if(name.isEmpty()) {
318 name = _defDatabase;
319 }
320 return (QSqlDatabase::contains(name));
321 }
322
335 bool DatabaseFactory::isPersistant(const QString &dbname) const {
336 return (_dbList.exists(dbname));
337 }
338
339
359 const QString &dbname) {
360
361
362 // Check driver availability
363 if(!isDriverAvailable(driver)) {
364 QString mess = "Driver [" + driver + "] for database [" + dbname
365 + "] does not exist";
366 throw IException(IException::Unknown, mess, _FILEINFO_);
367 }
368
369 // Create the database with the specified driver and name
370 Drivers drivers = getResourceList(true, false);
371 return (QSqlDatabase::addDatabase(drivers.get(driver), dbname));
372 }
373
385 QSqlDatabase DatabaseFactory::create(const QString &dbname) {
386
387 // Return an existing connection
388 if(_dbList.exists(dbname)) {
389 return (_dbList.get(dbname));
390 }
391
392 // One doesn't exist, throw an error
393 QString mess = "Database [" + dbname + "] does not exist";
394 throw IException(IException::Unknown, mess, _FILEINFO_);
395 }
396
415 void DatabaseFactory::add(const QSqlDatabase &db, const QString &name,
416 bool setAsDefault) {
417 _dbList.add(name, db);
418 if(setAsDefault) {
419 _defDatabase = name;
420 }
421 return;
422 }
423
435 void DatabaseFactory::destroy(const QString &name) {
436 remove(name);
437 QSqlDatabase::removeDatabase(name);
438 return;
439 }
440
450 void DatabaseFactory::remove(const QString &name) {
451 _dbList.remove(name);
452#if 0
453 if(IString::Equal(name, _defDatabase)) {
454 _defDatabase = "";
455 }
456#endif
457 return;
458 }
459
468 // Add the PostgreSQL database driver explicitly if it doesn't exist
469 loadDrivers();
470
471 // Use the users Preferences to determine if a default exists
473 return;
474 }
475
487 Preference &userPref = Preference::Preferences();
488 if(userPref.hasGroup("Database")) {
489 PvlGroup &dbgroup = userPref.findGroup("Database");
490 if(dbgroup.hasKeyword("AccessConfig")) {
491 addAccessProfile(dbgroup["AccessConfig"]);
492 }
493 // Get default profile name for later use
494 if(dbgroup.hasKeyword("DefaultProfile"))
495 _defProfName = (QString) dbgroup["DefaultProfile"];
496 }
497 return;
498 }
499
517 bool connections)
518 const {
519 QStringList dblist;
520 if(drivers) dblist += QSqlDatabase::drivers();
521 if(connections) dblist += QSqlDatabase::connectionNames();
522 Drivers dbDrivers;
523 for(int i = 0 ; i < dblist.size() ; i++) {
524 QString dbname(dblist.at(i));
525 dbDrivers.add(dbname, dbname);
526 }
527
528
529 // Now create pseudonyms for well known databases
530 // PostgreSQL and UPC
531 if(dbDrivers.exists("QPSQL")) {
532 dbDrivers.add("PostgreSQL", "QPSQL");
533 }
534
535 // MySQL and HiCAT
536 if(dbDrivers.exists("QMYSQL")) {
537 dbDrivers.add("MySQL", "QMYSQL");
538 }
539
540 // Oracle
541 if(dbDrivers.exists("QOCI")) {
542 dbDrivers.add("Oracle", "QOCI");
543 }
544
545 // SQLite
546 if(dbDrivers.exists("QSQLITE")) {
547 dbDrivers.add("SQLite", "QSQLITE");
548 }
549
550 return dbDrivers;
551 }
552
563 // Currently relying on Qt plugins - but that could change
564 // Hack to insure drivers are being loaded correctly
565 QSqlDatabase::drivers();
566 return;
567 }
568
577 while(_dbList.size() > 0) {
579 }
580 QStringList dblist = QSqlDatabase::connectionNames();
581 for(int i = 0 ; i < dblist.size() ; i++) {
582 QSqlDatabase::removeDatabase(dblist[i]);
583 }
584 return;
585 }
586
587}
const K & key(int nth) const
Returns the nth key in the collection.
int size() const
Returns the size of the collection.
int remove(const K &key)
Removes and entry from the list.
T & get(const K &key)
Returns the value associated with the name provided.
bool exists(const K &key) const
Checks the existance of a particular key in the list.
void add(const K &key, const T &value)
Adds the element to the list.
Create database interfaces using access profiles or generic drivers.
QSqlDatabase create(const QString &driver, const QString &dbname)
Create a database using the named driver.
static DatabaseFactory * getInstance()
Returns and instance of this DatabaseFactory singleton.
void destroy(const QString &dbname)
Removes the database from the connection pool and destroys it.
void remove(const QString &dbname)
Removes the database from the connection pool.
DatabaseFactory()
Constructor establishing the startup state of this singleton.
DbProfile getProfile(const QString &name="") const
Get the specified database access profile.
static DatabaseFactory * _factory
Pointer to self (singleton)
void add(const QSqlDatabase &db, const QString &name, bool setAsDefault=false)
Adds the database to the connection pool making it persistant.
bool isDriverAvailable(const QString &driver) const
Check for the existance of a specific database driver.
bool isPersistant(const QString &name) const
Checks if the database resource is persistant.
std::vector< QString > available() const
Determine what database drivers are available.
bool addAccessProfile(const QString &profileFile)
Establishes an access profile for subsequent database connections.
void selfDestruct()
Destroy all elements associated with this object.
Drivers getResourceList(bool drivers, bool connections) const
Get a list of available database drivers and connections.
static void DieAtExit()
Exit termination routine.
bool isAvailable(const QString &dbname="") const
Check for availablity of a database connection resource.
void addProfile(const DbProfile &profile)
Adds a database access profile to the list of profiles.
Databases _dbList
Maintains active databases.
void init()
Initializes this object upon instantiation.
void initPreferences()
Initializes user database preferences.
std::vector< QString > getProfileList() const
Return list of names of currently available profiles.
bool isConnected(const QString &dbname) const
Determines if the database resource is connected.
~DatabaseFactory()
Destructor implements self-destruction of this object.
void loadDrivers()
Load any drivers explicity.
QString _defDatabase
Name of default database.
Profiles _profiles
Maintain list of profiles.
CollectorMap< IString, QString, NoCaseStringCompare > Drivers
Define list of drivers and/or databases
QString _defProfName
Default profile name.
DbAccess manages programatic access to a database through profiles.
Definition DbAccess.h:106
A DbProfile is a container for access parameters to a database.
Definition DbProfile.h:51
QString Name() const
Returns the name of this property.
Definition DbProfile.h:104
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
bool Equal(const std::string &str) const
Compare a string to the object IString.
Definition IString.cpp:690
Reads user preferences from a data file.
Definition Preference.h:60
Contains multiple PvlContainers.
Definition PvlGroup.h:41
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.