Доброго времени суток.
Понадобилось написать функцию, которая проверяет доступность БД.
Есть три СУБД: на Оракле, на ПосгреСКЛ и на МССКЛ.
Функция, возвращающая конечный результат:
bool CommonFunctions::isConnectedToDataBase(DataBaseInfo dbInfo)
{
switch (dbInfo.dbType) {
case dbOracle:
return isConnectToOracleDataBase(dbInfo);
case dbMSSQL:
return isConnectedToMS_SQL_dataBase(dbInfo);
case dbPosgreSQL:
return isConnectedToPosgreSQL_dataBase(dbInfo);
}
return false;
}
Для Оракле:
bool CommonFunctions::isConnectToOracleDataBase(DataBaseInfo dbInfo)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI","Oracle_connection");
db.setDatabaseName(dbInfo.dataBaseName);
db.setHostName(dbInfo.ipAddress);
db.setPort(dbInfo.port);
db.setUserName(dbInfo.userName);
db.setPassword(dbInfo.password);
if(!db.open())
{
db.removeDatabase("Oracle_connection");
return false;
}
QSqlQuery query(db);
query.exec("select * from v$version");
bool retBool = false;
if(!query.lastError().type())
{
retBool = query.first();
}
if(db.isOpen())
{
db.close();
}
db.removeDatabase("Oracle_connection");
return retBool;
}
Для МССКЛ:
bool CommonFunctions::isConnectedToMS_SQL_dataBase(DataBaseInfo dbInfo)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC3","MS_SQL_connection");
db.setDatabaseName(getODBCconnectionSettings(dbInfo));
if(!db.open())
{
db.removeDatabase("MS_SQL_connection");
return false;
}
QSqlQuery query(db);
query.exec("select @@version");
bool retBool = false;
if(!query.lastError().type())
{
retBool = query.first();
}
if(db.isOpen())
{
db.close();
}
db.removeDatabase("MS_SQL_connection");
return retBool;
}
Для Посгре:
bool CommonFunctions::isConnectedToPosgreSQL_dataBase(DataBaseInfo dbInfo)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL","PosgreSQL_connection");
db.setDatabaseName(dbInfo.dataBaseName);
db.setHostName(dbInfo.ipAddress);
db.setPort(dbInfo.port);
db.setUserName(dbInfo.userName);
db.setPassword(dbInfo.password);
if(!db.open())
{
db.removeDatabase("PosgreSQL_connection");
return false;
}
QSqlQuery query(db);
query.exec("select version()");
bool retBool = false;
if(!query.lastError().type())
{
retBool = query.first();
}
if(db.isOpen())
{
db.close();
}
db.removeDatabase("PosgreSQL_connection");
return retBool;
}
Ну, и вспомогательная функция для соединения с QODBC:
QString CommonFunctions::getODBCconnectionSettings(DataBaseInfo dbInfo)
{
return "DRIVER={SQL Server};Server=" + dbInfo.ipAddress + "," + QString::number(dbInfo.port) +";Database=" + dbInfo.dataBaseName + ";Uid=" + dbInfo.userName + ";Pwd=" + dbInfo.password + ";WSID=.";
}
Сначала я создавал подключение к БД таким образом:
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
Но после вызова следующей функции появлялись варнинги о том, что старое соединение удалено, хотя перед возвращением результата я делаю db.close().
Тогда я прочитал, что надо в таком случае указать имя соединения, и я сделал подключение следующим образом:
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI","Oracle_connection");
добавив имя соединения.
С тремя разными соединениями это прокатывает, но как только я вызываю ещё раз проверку соединения, например для Оракла, то опять появляется сообщение, что старое соединение удалено.
Тогда я решил, что после db.close() сделаю следующее:
db.removeDatabase("Oracle_connection");
И тут начались варнинги с вылетами приложения:
QSqlDatabasePrivate::removeDatabase: connection 'MS_SQL_connection' is still in use, all queries will cease to work.
Вопрос в следующем. Есть данные для подключения к БД.
Мне нужно получить ТОЛЬКО информацию о том, есть ли подключение и посылается ли тестовый sql-запрос.
То есть, в функции создаётся соединение, а перед тем, как возвратить результат оно должно полностью закрыться и удалиться из программы.
То есть: есть данные для БД, нужно возвратить её работоспособность и не хранить никаких соединений.
Что я делаю не так, и как это грамотно сделать?
Спасибо.