I want to use QSqlTableModel since it seems easier to use. It does however not find my tables.
qDebug() << "connecting";
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName(dbHostName);
db.setPort(dbPort);
db.setUserName(dbUserName);
db.setPassword(dbPassword);
// Connect to database sys to get some info to test (basic communication)
db.setDatabaseName("sys");
// Check if opened and if so get some data
if(db.open()){
qDebug() << "DB succesfully opened";
} else {
qDebug() << "DB failed to open";
return;
}
QSqlTableModel* runsSimulationViewModel = new QSqlTableModel();
runsSimulationViewModel->setTable("results.runs_simulation_view");
qDebug() << runsSimulationViewModel->lastError();
//ERROR: QSqlError("", "Unable to find table results.runs_simulation_view", "")
QSqlQuery anotherQuery;
anotherQuery.prepare("SELECT * FROM results.runs_simulation_view");
if(!anotherQuery.exec()) {
qDebug() << anotherQuery.lastError();
} else {
anotherQuery.next();
qDebug() << anotherQuery.value("simulation_id").toInt();
//Prints "3", which is the first value for this field in the table
}
QSqlQuery works, but QSqlTableView cannot find this (SQL) view (and also no tables).
What am I missing?
Related
I want to insert data into an SQLite database using QSqlDatabase and QSqlTableModel.
The database is being created in an SqlDatabaseController class:
SqlDatabaseController.h
// ...
class SqlDatabaseController : public QObject
{
Q_OBJECT
// ...
private:
QSqlDatabase _database;
SqlContactModel* _contactModel { nullptr };
// ...
SqlDatabaseController.cpp
SqlDatabaseController::SqlDatabaseController(QObject *parent) : QObject(parent)
{
// create database driver
_database = QSqlDatabase::database();
_contactModel = new SqlContactModel(this, _database);
}
// ...
void SqlDatabaseController::connectToDatabase(const QString &name, const QString &pwd)
if (!_database.isValid()) {
_database = QSqlDatabase::addDatabase("QSQLITE");
if (!_database.isValid()) {
qFatal("[SQL] SqlDatabaseController: Cannot add database: %s", qPrintable(_database.lastError().text()));
}
}
const QDir writeDir { QStandardPaths::writableLocation(QStandardPaths::AppDataLocation).append("/").append(name) };
if (!writeDir.exists() && !writeDir.mkpath(".")) {
qFatal("[SQL] SqlDatabaseController: Failed to create writable directory at %s", qPrintable(writeDir.absolutePath()));
}
// Ensure that we have a writable location on all devices.
const QString fileName { writeDir.absolutePath() + "/db.sqlite3" };
// When using the SQLite driver, open() will create the SQLite database if it doesn't exist.
_database.setDatabaseName(fileName);
if (!_database.open()) {
qFatal("[SQL] SqlDatabaseController: Cannot open database: %s", qPrintable(_database.lastError().text()));
QFile::remove(fileName);
return;
}
emit databaseConnected();
}
For model data storing, I'm subclassing QSqlTableModel:
SqlContactModel.cpp
SqlContactModel::SqlContactModel(QObject* parent, QSqlDatabase db) :
QSqlTableModel(parent, db),
_tableName("Contacts")
{
}
As you can see, I'm passing the database to the TableModel so it's able to use this database for all queries.
Afterwards, I'm creating the tables:
SqlContactModel.cpp
void SqlContactModel::create()
{
createTable();
setTable(_tableName);
setSort(2, Qt::DescendingOrder);
// Ensures that the model is sorted correctly after submitting a new row.
setEditStrategy(QSqlTableModel::OnManualSubmit);
}
// ...
void SqlContactModel::createTable()
{
qDebug() << "[SQL] Creating table" << _tableName << "for database" << QSqlDatabase::database().databaseName() << ".";
if (QSqlDatabase::database().tables().contains(_tableName)) {
qDebug() << "[SQL] Database table" << _tableName << "already exists. Exiting createTable().";
emit contactTableCreated();
return;
}
QSqlQuery query { "SOME_QUERY" };
if (!query.exec()) {
qFatal("[SQL] SqlContactModel: Failed to create table: %s", qPrintable(query.lastError().text()));
return;
}
if (!submitAll()) {
qFatal("[SQL] SqlContactModel: Failed to submit createTable query: %s", qPrintable(lastError().text()));
}
emit contactTableCreated();
qDebug() << "Done creating table" << _tableName << ".";
}
Now, I want to insert something into my table like this:
SqlContactModel.cpp
// ...
void SqlContactModel::addContact(const QString& contactName, const QString& id, const QByteArray& avatar)
{
QSqlQuery query;
query.prepare("INSERT OR REPLACE INTO '" +
_tableName +
"'(id, name" +
(avatar.isEmpty() ? "" : ", avatar") +
") VALUES (:Id, :Name" + (avatar.isEmpty() ? "" : ", :Avatar") +
")");
query.bindValue(":Id", id);
query.bindValue(":Name", contactName);
if (!avatar.isEmpty()) {
query.bindValue(":Avatar", avatar);
}
if (!query.exec()) {
qFatal("[SQL] SqlContactModel: Unable to execute query in addContact: %s", qPrintable(query.lastError().text()));
return;
}
for (auto const& table : QSqlDatabase::database().tables()) {
qDebug() << "Table: " << table;
}
if (!submitAll()) { // <-- here's where it breaks
qFatal("[SQL] SqlContactModel: Failed to submit addContact query: %s", qPrintable(lastError().text()));
return;
}
qDebug() << "[SQL] Added contact " << contactName << "(" << id << ") to table " << _tableName << ".";
// emit contactListChanged();
}
The query executes just fine and the data is being stored in the database, however since I'm using setEditStrategy(QSqlTableModel::OnManualSubmit); on my model, I would need to call submitAll() on my model to be updated properly. When calling submitAll(), however, I keep getting an error:
[SQL] SqlContactModel: Failed to submit addContact query: Unable to find table Contacts.
As you can see in the code above, I iterated through all tables of the database and I get the following output:
Table: "Contacts"
Table: "Conversations"
which is why I'm quite sure the table does exist.
Is this some kind of encoding error or why is submitAll() not able to find my table Contacts in the database? What am I missing here?
Thanks in advance.
Juggling between receiving 2 different errors.
void summary::on_pushButton_saveSummary_clicked()
{
if(db.open())
{
query.exec("insert or replace into [PN:"+partNum+" CN:"+chargeNum+"](total, defects, rust) values(1, 2, 3)");
if (!query.exec())
{
qDebug() << query.lastError();
qDebug() << query.exec()<<endl;
}
}
else
{
qDebug() << db.lastError();
}
}
The above gives error: QSqlError("", "Unable to fetch row", "No query")
While:
void summary::on_pushButton_saveSummary_clicked()
{
if(db.open())
{
qDebug() << "db open";
int a = 3;
int b = 1;
int c = 3;
query.prepare("insert into [PN:"+partNum+" CN:"+chargeNum+"](total, defects, rust) values(:total, :defects, :rust)");
query.bindValue(":total", a);
query.bindValue(":defects", b);
query.bindValue(":rust", c);
if (!query.exec())
{
qDebug() << query.lastError();
qDebug() << query.exec()<<endl;
}
}
else
{
qDebug() << db.lastError();
}
}
Yields: QSqlError("", "Parameter count mismatch", "")
The Constructor has:
db.setDatabaseName("/home/igraves/Databases/testdb");
db.open();
QString partNum = "134345";
QString chargeNum = "3452";
query.prepare("create table if not exists [PN:"+partNum+" CN:"+chargeNum+"](total int, defects int, rust int)");
query.exec();
The table is being create, I can see it. So I am guessing syntax? Although it is as the Qt wiki writes it...
Edit:
Adding some .h stuff
QString partNum;
QString chargeNum;
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
QSqlQuery query;
Answer: It was my QString variables being temporary, after the constructor was done, they went out of scope. Changed my .h
QString partNum = "124124";
QString chargeNum = "234234";
I see at least the following errors:
You do not set the database path.
Do not open the database when creating the table.
"134345" and "3452" are being assigned to temporary variables instead of class members
Considering the above, the following must be in the constructor:
partNum = "134345";
chargeNum = "3452";
db.setDatabaseName("/path/of/database.db");
if(db.open())
query.exec(QString("create table if not exists [PN:%1 CN:%2](total int, defects int, rust int)")
.arg(partNum)
.arg(chargeNum));
I am using sqlite database in qt. Database created when i use setDatabase("") function. But i dont know how to check same database is exist or not. Here is my code:
//add database driver
db = QSqlDatabase::addDatabase ("QSQLITE");
//create database
if(db.databaseName () == db_Name){
qDebug() << "Database exist or not created." << endl;
} else {
db.setDatabaseName (db_Name);
qDebug() << "Database created." << endl;
}
//opening connection
db.open ();
//if connection created
if(db.isOpen ()){
qDebug() << "Database connected." << endl;
} else {
qDebug() << "Database not connected." << endl;
}
I get the Database created. message. How to check ? Thanks.
You can simply check the database file whether it exists using QFile:
if (QFile::exists(db_Name)) {
// database exists
}
SQLite creates an empty database when you try to open a nonexisting file.
So if you want to know if you need to create the tables for your application, just run a query to check whether these tables exist:
SELECT * FROM sqlite_master WHERE name = 'MyTable';
While trying to connect to a MS SQL database the app crashes.
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setHostName("test");
db.setDatabaseName("test");
db.setUserName("test");
db.setPassword("test");
qDebug() << "Is driver available:" << db.isDriverAvailable("QODBC");
qDebug() << "Drivers:" << db.drivers();
qDebug() << "Db is valid:" << db.isValid();
qDebug() << "Last error:" << db.lastError();
if (!db.open()) // Crashes here
qDebug() << "Database error";
I saw some posts where unixODBC and FreeTDS is a solution but I was unable to get it working.
The output of qDebug() calls is:
Is driver available: true
Drivers: ("QSQLITE", "QMYSQL", "QMYSQL3", "QODBC", "QODBC3", "QPSQL", "QPSQL7")
Db is valid: true
Last error: QSqlError("", "", "")
The code below doesn't work for catching sql errors with Qt and sqlite. I've also tried isNull. I'm getting a blank string for lasterror.text() and -1 for error number with working queries. I don't understand why isEmpty or isNull aren't working.
if (!query.lastError().text().isEmpty())
{
logfile(sqlstatement);
logfile("SqLite error:" + query.lastError().text());
logfile("SqLite error code:"+ QString::number( query.lastError().number() ));
}
Do you really execute your query?
Take a look at way of doing access do SQLite DB + logging in OpenSource application Mixxx (Opening database, applying query):
...
#define LOG_FAILED_QUERY(query) qDebug() << __FILE__ << __LINE__ << "FAILED QUERY [" \
<< (query).executedQuery() << "]" << (query).lastError()
...
// Check if you have QSQLITE2/QSQLITE driver avaiable
qDebug() << "Available QtSQL drivers:" << QSqlDatabase::drivers();
m_db.setHostName(...);
m_db.setDatabaseName(...);
m_db.setUserName(...);
m_db.setPassword(...);
bool ok = m_db.open();
qDebug() << "DB status:" << m_db.databaseName() << "=" << ok;
if (m_db.lastError().isValid()) {
qDebug() << "Error loading database:" << m_db.lastError();
}
...
QSqlQuery query(m_database);
query.setForwardOnly(true);
query.prepare(queryString);
if (!query.exec()) {
LOG_FAILED_QUERY(query);
return;
}
And be sure that this works :)