PDA

View Full Version : Pass QSqlQuery result to object



KeineAhnung
23rd April 2014, 00:40
Hi there,

I am trying to pass on a QSqlQuery result, which is one line from a SQLite database, to an object. Is that possible and if so how should the syntax be?
I tried to use QSqlQuery as a data type but I guess that is not correct:

.../mainwindow.cpp:70: Error: no matching constructor for initialization of 'Employee'
team[sIndex] = Employee(qry, level);
^ ~~~~~~~~~~
.../employee.h:9: candidate constructor not viable: no known conversion from 'QSqlQuery *' to 'const QSqlQuery' for 1st argument; dereference the argument with *
Employee(const QSqlQuery &query, const QString &level);
^

If this would be the right way, what would be the correct data type?

My goal is to create a Qvector<Employee> called team that holds all the team members. The employee objects within the vector shall hold a bunch of information from a SQLite database. After selecting the right employee in my GUI the correct data (one row from the db) should be loaded and a new employee object should be created. Within the class Employee the basic data should be reworked. I am not interested in the basic data from the db but the parameters that could be calculated from the basic data. So I would like to pass on the query result to the object and have the class do all the conversion.
Is this a clever way to do that or am I barking up the wrong tree?
The code works as long as I use two QStrings, with the exception that I cannot declare the vector Qvector<Employee> team without the two arguments defined in the class. So far I was not able to find a work around that issue. How can I declare an empty vector from the class Employee without passing on any values?

Thanks for your input in advance!

ChrisW67
23rd April 2014, 01:41
The error you get is because the pointer-to-QSqlQuery you pass the constructor is not compatible with a reference-to-const-QSqlQuery the constructor is expecting.

You could:

adjust the expectations of the constructor to expect a pointer,
change how you call the constructor to use an actual instance (i.e. *qry),
look at passing a QSqlRecord obtained from QSqlQuery::record() by const-reference, or
extract the necessary fields and pass them individually to separate parameters of the constructor.

KeineAhnung
23rd April 2014, 07:44
Hi Chris,

thanks for the quick help. I guess I should learn more about pointers and instances. I went with the instance suggestion and now I get past this but it is still not compiling. As I thought, the issue is at declaring the vector:


Undefined symbols for architecture x86_64:
"Employee::Employee()", referenced from:
QVector<Employee>::defaultConstruct(Employee*, Employee*) in mainwindow.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Team.app/Contents/MacOS/Team] Error 1

So how can I declare a QVector with a custom class that needs an input that I do not have at that moment?
Here is how my class looks:


class Employee{
public:
Employee();
Employee(const QSqlQuery *query, const QString &level);
[...]
}

I thought by using Employee(); I can create an object of Employee without the need to pass on anything. Is this not correct?

ChrisW67
23rd April 2014, 08:35
Your linker error implies you are doing something odd with your QVector but we cannot see it.

This is what a working example looks like:


#include <QCoreApplication>
#include <QVector>
#include <QDebug>

// Typically in employee.h
class Employee {
public:
Employee();
Employee(const QString &name, const QString &job);

QString name() const;
QString job() const;
// ...

private:
QString m_name;
QString m_job;
};

// Typically in employee.cpp
Employee::Employee() { }
Employee::Employee(const QString &name, const QString &job): m_name(name), m_job(job) { }
QString Employee::name() const { return m_name; }
QString Employee::job() const { return m_job; }

// Typically in main.cpp
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

QVector<Employee> employees; // empty by default

employees << Employee();
employees.append(Employee("Tom", "Burger flipper"));

// This is similar to your initial example
// The vector does not already have index 2 so this will fail badly at run time. See QVector::operator[].
// employees[2] = Employee("Dick", "Burger wrapper");

qDebug() << employees.count();
foreach(const Employee &emp, employees) {
qDebug() << emp.name() << emp.job();
}

return 0;
}

KeineAhnung
23rd April 2014, 08:36
Okay, somehow I got it to work by adding {}


class Employee{
public:
Employee(){};
Employee(const QSqlQuery *query, const QString &level);
[...]
}

Can anyone tell me why this did the trick?

ChrisW67
23rd April 2014, 08:47
By adding {} you have defined the implementation of the default constructor that was, presumably, missing before.

KeineAhnung
23rd April 2014, 08:50
Thanks for the help! In this five minutes today I got further with my program than in the entire day yesterday...