[Qt-interest] QSqlDatabase

Robert Hairgrove evorgriahr at hispeed.ch
Thu Oct 1 13:27:56 CEST 2009


Riccardo Roasio wrote:
> Hi,
> 
> i have a probelm with a QSqlDatabase object, it gives me this warning :
> 
> QSqlDatabasePrivate::addDatabase: duplicate connection name
> 'qt_sql_default_connection', old connection removed.
> 
> How can i solve this issue?
> 
> The class that use the QSqlDatabase object is this one:
> 
> #ifndef MYSQLCONNECTION_H
> #define MYSQLCONNECTION_H
> 
> #include <QtSql>
> #include <QString>
> #include <QCoreApplication>
> #include <QSqlDatabase>
> #include <QSqlError>
> #include <QStringList>
> #include <QtDebug>
> #include <iostream>
> 
> #include "logger.h"
> 
> class MysqlConnection
> {
> 
> public:
>     MysqlConnection(QString host,QString database,QString
> username,QString password);
>     void close();
>     QSqlQuery query(QString q);
>     bool opened();
> 
> private:
>     QString username;
>     QString password;
>     QString database;
>     QString host;
>     QString connection;
>     QSqlDatabase db;
>     bool op;
> 
>     Logger *logger;
> };
> 
> #endif // MYSQLCONNECTION_H
> 
> 
> #include "mysqlconnection.h"
> 
> MysqlConnection::MysqlConnection(QString h,QString d,QString u,QString p)
> {
>     std::cout<<"1"<<std::endl;
>    logger=new Logger();
> 
>    logger->logOnFile(" MysqlConnection","MysqlConnection","Opening
> connection.");
> 
>    host=h;
>    database=d;
>    username=u;
>    password=p;
> 
>    logger->logOnFile(" MysqlConnection","MysqlConnection","Adding database.");
>    db = QSqlDatabase::addDatabase("QMYSQL");

(rest snipped)

Please read this:
http://doc.trolltech.com/4.5/qsqldatabase.html#addDatabase

It says:
"Warning: If you add a connection with the same name as an existing 
connection, the new connection replaces the old one. If you call this 
function more than once without specifying connectionName, the default 
connection will be the one replaced."

You have declared an object of QSqlDatabase as a member variable. It is 
initialized, i.e. default constructed, by the time the body of your 
constructor starts, as an invalid object since you have no constructor 
initialization list. Inside the body of the constructor, you assign a 
new database object to db which has the same effect as if you had called 
QSqlDatabase::addDatabase twice.

It is possible to get around this by initializing the member variable in 
the constructor's initialization list, i.e.:

MysqlConnection::MysqlConnection(QString h,QString d,
    QString u,QString p)
  : db(QSqlDatabase::addDatabase("QMYSQL", "my_connection"))
{
     std::cout<<"1"<<std::endl;
    logger=new Logger();

etc. Note that the default connection is not replaced here since you 
have given it a name. It would also work to leave off the name, but then 
the MySQL connection becomes the default connection; and if your 
MysqlConnection object is ever destroyed and created again, you would 
get the same error as before.

Unfortunately, there are other issues to worry about. You will need to 
call QSqlDatabase::removeDatabase("my_connection") AFTER the member 
object db is destroyed, which means you cannot do it inside the class 
(not even in the destructor since member variables are destroyed only 
after the destructor has run). Please refer to this document for details:
http://doc.trolltech.com/4.5/qsqldatabase.html#removeDatabase

Therefore, I think the only way to handle this properly is to make your 
internal member a pointer, create it with new and destroy it with 
delete. That way, you can handle the addDatabase() and removeDatabase() 
calls in the proper order. But maybe there is an easier way ... for 
example, you could probably make the member a static member, let it 
become the default connection, and just call open() and close() on it as 
you need to. When the application closes, I assume that the library 
would clean up things properly, but I'm not sure if there would be a 
leak somewhere. You would have to test it.



More information about the Qt-interest-old mailing list