PDA

View Full Version : QSqlDatabase as protected member results in "Driver not loaded"



croscato
4th February 2014, 23:50
Hi.

I'm trying to implement a generic connection class using Qt for my projects.

The code looks like this:

connection.h


#ifndef CONNECTION_H
#define CONNECTION_H

#include <QtSql/QSqlDatabase>

class Connection
{
public:
bool open();
void close();
bool isOpen() const;

QString databaseName() const;
QString hostName() const;
QString userName() const;
QString password() const;
int port() const;

QString lastError() const;

operator QSqlDatabase();
operator QSqlDatabase*();

protected:
void setDatabaseName(const QString &databaseName);
void setHostName(const QString &hostName);
void setUserName(const QString &userName);
void setPassword(const QString &password);
void setPort(int port);

protected:
QSqlDatabase m_db;
};

#endif // CONNECTION_H


connection.cpp


#include <QtSql/QSqlError>

#include "connection.h"

bool Connection::open()
{
return m_db.open();
}

void Connection::close()
{
if (isOpen())
m_db.close();
}

bool Connection::isOpen() const
{
return m_db.isOpen();
}

QString Connection::databaseName() const
{
return m_db.databaseName();
}

QString Connection::hostName() const
{
return m_db.hostName();
}

QString Connection::userName() const
{
return m_db.userName();
}

QString Connection::password() const
{
return m_db.password();
}

int Connection::port() const
{
return m_db.port();
}

QString Connection::lastError() const
{
return m_db.lastError().databaseText();
}

Connection::operator QSqlDatabase()
{
return m_db;
}

Connection::operator QSqlDatabase *()
{
return &m_db;
}

void Connection::setDatabaseName(const QString &databaseName)
{
if (isOpen())
close();

if (m_db.databaseName() != databaseName)
m_db.setDatabaseName(databaseName);
}

void Connection::setHostName(const QString &hostName)
{
if (isOpen())
close();

m_db.setHostName(hostName);
}

void Connection::setUserName(const QString &userName)
{
if (isOpen())
close();

m_db.setUserName(userName);
}

void Connection::setPassword(const QString &password)
{
if (isOpen())
close();

m_db.setPassword(password);
}

void Connection::setPort(int port)
{
if (isOpen())
close();

m_db.setPort(port);
}


sqliteconnection.h


#ifndef SQLITECONNECTION_H
#define SQLITECONNECTION_H

class Connection;

class SQLiteConnection : public Connection
{
public:
SQLiteConnection();
SQLiteConnection(const QString &databaseName);

bool open(const QString &databaseName);
};

#endif // SQLITECONNECTION_H


sqliteconnection.cpp


#include <QtCore/QUuid>

#include "connection.h"
#include "sqliteconnection.h"

SQLiteConnection::SQLiteConnection()
{
m_db = QSqlDatabase::addDatabase("QSQLITE", QUuid::createUuid().toString());
}

SQLiteConnection::SQLiteConnection(const QString &databaseName)
{
SQLiteConnection();

Connection::setDatabaseName(databaseName);
}

bool SQLiteConnection::open(const QString &databaseName)
{
Connection::setDatabaseName(databaseName);

return Connection::open();
}


main.cpp


#include <QtWidgets/QApplication>

#include "monetae.h"

#include "db/connection.h"
#include "db/sqliteconnection.h"
#include "db/mysqlconnection.h"

#include <QtSql/QSqlQuery>
#include <QtCore/QDebug>

int main(int argc, char *argv[])
{
QApplication application(argc, argv);

Connection con = SQLiteConnection("~/test.sq3");

if (con.open() == false) {
qDebug() << con.lastError();

return -1;
}

QSqlQuery qry(con);

qry.exec("CREATE TABLE TEST (ID INTEGER, NAME VARCHAR(10))");

return 0;


The problem is that con.open() fails and con.lastError() returns "Driver not loaded". But if m_db is a private member in SqliteConnection and not a protected member in Connection everything works fine.

anda_skoa
5th February 2014, 09:31
My guess is that you are not initializing m_db in the constructor you are using, only in the SQLiteConnection's default constructor.

I would recommend something like this so that this won't happen



class Connection
{
protected:
Connection(const QString &driver, const QString &dbName)
m_db(QSqlDatabase::addDatabase(driver, dbName))
{
}
};



SQLiteConnection::SQLiteConnection()
: Connection("QSQLITE", QUuid::createUuid().toString())
{
}

SQLiteConnection::SQLiteConnection(const QString &databaseName)
: Connection("QSQLITE", databaseName)
{
}


Cheers,
_

croscato
6th February 2014, 01:03
Many thanks anda_skoa!

You sugestion work like a charm.