PDA

View Full Version : QSqlDatabase coneciton removal!



cbarmpar
27th September 2008, 00:02
Hi all,

In my program i have a main class (kentrko) which creates a QSqlDatabase* object. I want to pass this object to a dialogue to detect whether the connection is opened or closed and if not to open it. The code works fine and compiles but i receive the following error when I am opening the dialogue window again:


QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.


kentriko class:


#include "kentriko.h"
#include <QMdiSubWindow>

kentriko::kentriko(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.actionAnalisi, SIGNAL(triggered()), this, SLOT(anixe_analisi()));
connect(ui.actionSindesi, SIGNAL(triggered()), this, SLOT(anixe_sindesi()));
*db = QSqlDatabase::addDatabase("QMYSQL");
}

void kentriko::anixe_sindesi(){
sindesi *sindesi1= new sindesi(0,db) ;
sindesi1->show();
}


and the kentriko header:


#ifndef KENTRIKO_H
#define KENTRIKO_H
#include <QtGui/QMainWindow>
#include "ui_kentriko.h"
#include <QtSql>
#include "../parathrira/sindesi/sindesi.h"// i klasi silogi ine orismeni apo tin sindesi giayto xreazete edo to header
#include "../parathrira/analisi/analisi.h"
class kentriko : public QMainWindow
{
Q_OBJECT
public:
kentriko(QWidget *parent = 0);
~kentriko();
QSqlDatabase *db;
public slots:
void anixe_analisi ();
void anixe_sindesi ();
};

the dialog that i want to pass the db and manipulate it is:



#ifndef SINDESI_H
#define SINDESI_H
#include <QtSql>
#include <QtGui/QDialog>
#include "ui_sindesi.h"

class sindesi : public QDialog
{
Q_OBJECT

public:
sindesi(QWidget *parent , QSqlDatabase* db);
~sindesi();
QSqlDatabase* db3;
public slots:
void sindesou();
void aposindesou();

private:
Ui::sindesiClass ui;
};

#endif // SINDESI_H


and the implementation:


#include "sindesi.h"
#include <QtSql>
sindesi::sindesi(QWidget *parent,QSqlDatabase* db)
: QDialog(parent)
{
db3=db;
ui.setupUi(this);
connect(ui.sindesi, SIGNAL(clicked()), this, SLOT(sindesou()));
connect(ui.aposindesi, SIGNAL(clicked()), this, SLOT(aposindesou()));
}
void sindesi::sindesou() {
if (db3->isOpen())
ui.pliroforia_2->setText("ine idi anixti");
if (!db3->isOpen()) {
db3->setDatabaseName(ui.pinakas->text());
db3->setUserName(ui.onoma->text());
db3->setPassword(ui.kodikos->text());
db3->setHostName("127.0.0.1");
db3->setPort(3306);
if (!db3->open()) {
ui.katastasi->setText("Not connected");
} else {
ui.katastasi->setText("connected");
}
} else {
ui.katastasi->setText("It has already been connected");
}
}

Any ideas why is this happening?

Many thanks in advance.

wysota
27th September 2008, 00:28
There is no point in passing the database object around. You can always retrieve it using QSqlDatabase::database().

caduel
27th September 2008, 10:05
Error causes:

you are trying to create a connection while one of the same name is still existing
you are trying to delete a QDatabase while it is still in use


Are you trying to delete the connection (perhaps in ~sindesi)?
You can only remove the connection once all its user have stopped using it (e.g. been destroyed).

Show us the rest of your code. The code shown looks ok.
Most likely you create two instances of the kentriko class or something like that.

cbarmpar
27th September 2008, 11:46
I have attached the full code.

I have now modified it and found something strange. I pass the db object to the dialogue and then copy it to another object so it can be visibe to the rest of the class. By manipulating the copy of the objcect is like manipulating the original object which cant be true in c++.

in my example i use pointers but the result would have been exactly the same if i have passed the object to the sindesi object and then coppied to another object which is visible to the entire class.

I found in the documentation :


To make programming more convenient, QSqlDatabase is a value class. Any changes done to a database connection through one QSqlDatabase object will affect other QSqlDatabase objects representing the same connection.

I dont know if that expllains the fact that when i am coping the QSqlDatabase object and using this copy is like i am using the original.

to demonstarte that i will show the two versions of the code which shouldnt be equivalnet but they are:

the pointers version:


kentriko class implementation:
#include "kentriko.h"
#include <QMdiSubWindow>

kentriko::kentriko(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.actionAnalisi, SIGNAL(triggered()), this, SLOT(anixe_analisi()));
connect(ui.actionSindesi, SIGNAL(triggered()), this, SLOT(anixe_sindesi()));
db = QSqlDatabase::addDatabase("QMYSQL");
}
void kentriko::anixe_sindesi(){
sindesi *sindesi1 = new sindesi(0,&db);
sindesi1->show();
}

and the header file:
#ifndef KENTRIKO_H
#define KENTRIKO_H

#include <QtGui/QMainWindow>
#include "ui_kentriko.h"
#include <QtSql>
#include "../parathrira/sindesi/sindesi.h"// i klasi silogi ine orismeni apo tin sindesi giayto xreazete edo to header
#include "../parathrira/analisi/analisi.h"

class kentriko : public QMainWindow
{
Q_OBJECT

public:
kentriko(QWidget *parent = 0);
~kentriko();
QSqlDatabase db;

public slots:
void anixe_analisi ();
void anixe_sindesi ();

private:
Ui::kentrikoClass ui;
};



and the dialogue class:


#include "sindesi.h"
#include <QtSql>
sindesi::sindesi(QWidget *parent,QSqlDatabase* db)
: QDialog(parent)
{
db5= db;// in thsi case i pass the pointer
ui.setupUi(this);
connect(ui.sindesi, SIGNAL(clicked()), this, SLOT(sindesou()));
connect(ui.aposindesi, SIGNAL(clicked()), this, SLOT(aposindesou()));
}
void sindesi::sindesou() {
if (!db5->isOpen()) {
db5->setDatabaseName(ui.pinakas->text());
db5->setUserName(ui.onoma->text());
db5->setPassword(ui.kodikos->text());
db5->setHostName("127.0.0.1");
db5->setPort(3306);
if (!db5->open()) {
ui.katastasi->setText("not connected");
} else {
ui.katastasi->setText("connected");
}
} else {
ui.katastasi->setText("it has already been connected");
}
}

and the header:
#ifndef SINDESI_H
#define SINDESI_H
#include <QtSql>
#include <QtGui/QDialog>
#include "ui_sindesi.h"

class sindesi : public QDialog
{
Q_OBJECT

public:
sindesi(QWidget *parent,QSqlDatabase *db);
~sindesi();
QSqlDatabase *db5;
public slots:
void sindesou();
void aposindesou();

private:
Ui::sindesiClass ui;
};


and below the version where the whole object is passed:
kentriko class implementation:

#include "kentriko.h"
#include <QMdiSubWindow>

kentriko::kentriko(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.actionAnalisi, SIGNAL(triggered()), this, SLOT(anixe_analisi()));
connect(ui.actionSindesi, SIGNAL(triggered()), this, SLOT(anixe_sindesi()));
db = QSqlDatabase::addDatabase("QMYSQL");
}
void kentriko::anixe_sindesi(){
sindesi *sindesi1 = new sindesi(0,&db);
sindesi1->show();
}

and the header file:
#ifndef KENTRIKO_H
#define KENTRIKO_H

#include <QtGui/QMainWindow>
#include "ui_kentriko.h"
#include <QtSql>
#include "../parathrira/sindesi/sindesi.h"// i klasi silogi ine orismeni apo tin sindesi giayto xreazete edo to header
#include "../parathrira/analisi/analisi.h"

class kentriko : public QMainWindow
{
Q_OBJECT

public:
kentriko(QWidget *parent = 0);
~kentriko();
QSqlDatabase db;

public slots:
void anixe_analisi ();
void anixe_sindesi ();

private:
Ui::kentrikoClass ui;
};


and the dialogue class:


#include "sindesi.h"
#include <QtSql>
sindesi::sindesi(QWidget *parent,QSqlDatabase db)
: QDialog(parent)
{
db5= db;// here i pass and copy the whole object and via the db5 the db is still accesible
ui.setupUi(this);
connect(ui.sindesi, SIGNAL(clicked()), this, SLOT(sindesou()));
connect(ui.aposindesi, SIGNAL(clicked()), this, SLOT(aposindesou()));
}
void sindesi::sindesou() {
if (!db5.isOpen()) {
db5.setDatabaseName(ui.pinakas->text());
db5.setUserName(ui.onoma->text());
db5.setPassword(ui.kodikos->text());
db5.setHostName("127.0.0.1");
db5.setPort(3306);
if (!db5.open()) {
ui.katastasi->setText("not connected");
} else {
ui.katastasi->setText("connected");
}
} else {
ui.katastasi->setText("it has already been connected");
}
}

and the header:
#ifndef SINDESI_H
#define SINDESI_H
#include <QtSql>
#include <QtGui/QDialog>
#include "ui_sindesi.h"

class sindesi : public QDialog
{
Q_OBJECT

public:
sindesi(QWidget *parent,QSqlDatabase db);
~sindesi();
QSqlDatabase db5;
public slots:
void sindesou();
void aposindesou();

private:
Ui::sindesiClass ui;
};


I am not sure if that supposed to be correct but in both cases works exactly the same.

Many thanks in advance.
Regards