PDA

View Full Version : QSqlQueryModel::setQuery - SIGSEGV



onamatic
18th January 2009, 13:11
I'm using Linux / Qt 4.5.0.

Most sql work is going fine except for this piece of code where I'm using QSqlQueryModel for the first time:



QSqlQuery query("SELECT name FROM videosource ");
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(query);


model->setQuery(query) blows out; top of stack is:

Thread [1] (Suspended: Signal 'SIGSEGV' received. Description: Segmentation fault.)
36 mysql_stmt_num_rows() 0x046afaa7
35 QSqlQuery::size() /media/OneTouch4-Main/internet/downloads/QT4.5Preview/qt-x11-opensource-src-4.5.0-snapshot-20081217/src/sql/kernel/qsqlquery.cpp:717 0x00232cfd
34 QSqlQueryModel::setQuery() /media/OneTouch4-Main/internet/downloads/QT4.5Preview/qt-x11-opensource-src-4.5.0-snapshot-20081217/src/sql/models/qsqlquerymodel.cpp:347 0x00246acf
...
mysql_stmt_num_rows() is presumably in a mysql library somewhere so I'm guessing there is an issue between QSql and mysql.

(The query "SELECT name FROM videosource" works fine in other situations.)

Anyone seen this kind of problem before?

wysota
19th January 2009, 08:28
Please check your code again, the problem has to be elsewhere. Are you using the database from multiple threads maybe?

onamatic
20th January 2009, 01:29
Thank you for your suggestion wysota.

I extracted the relevant bits of code and tested this threadless morsel:


int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("mythconverg");
bool trashok;
db.setPort(QString("3306").toInt(&trashok));
db.setUserName("mythtv");
db.setPassword("mythtv");
bool ok = db.open();
if (ok) qDebug() << "Open OK";
else qDebug() << "Open failed";
QSqlQueryModel amodel;
amodel.setQuery("SELECT sourceid FROM videosource"); //BANG! SIGSEGV
...
}

So then I reverted from the Qt 4.5.0 snapshot to 4.4.3. and setQuery then worked as advertised. I will try picking up the latest 4.5 snapshot tomorrow to see if that has fixed anything.

onamatic
20th January 2009, 16:04
I've just tried 4.5.0Beta1. It blows out too.

There is something fishy about the mysql driver; the working version (4.4.3) of libqsqlmysql.so is larger than the non-working 4.5.0 versions although they were all built the same way with the same set of header files. Am currently investigating but would appreciate any insights.

spirit
20th January 2009, 16:07
try to create QSqlQueryModel in the heap using operator new.

onamatic
21st January 2009, 01:33
Thanks spirit for the suggestion. Creating on the heap makes no difference.

Playing around with the debugger gave me the feeling that there was a linkage problem somewhere so in desperation I swapped the 4.5.0 mysql drivers (libqsqlmysql.so & libqsqlmysql.so.debug) for the 4.4.3 versions. Hey presto - everything works.

I'm not happy about this however as the libraries are not the same size between versions and I'm sure something will bite me soon.

I've tried recompiling the drivers and Qt itself with different sql options but no joy.

More suggestions please chaps!

wysota
21st January 2009, 09:06
Do the Qt SQL examples work properly?

onamatic
21st January 2009, 20:53
Thanks again wysota. Now why didn't I think of trying the examples?
Out of the box the sqlqyerymodel examples work fine, but then I found that they use the sqlite drivers.
If I modify them to use MySql drivers the behaviour is as before: OK with 4.4.3 driver, core dump with 4.5.0.

onamatic
23rd January 2009, 13:12
I've spent a day completely reinstalling MySql, QT and various devel packages; then compiling everything from scratch. Result: No difference at all! Qt4.4.3 works, Qt4.5.0Beta doesn't.

To recap:


QSqlQueryModel amodel;
amodel.setQuery("SELECT sourceid FROM videosource"); //BANG! SIGSEGV

Reason for segv: setQuery() eventually calls QMYSQLResult::size in file: $QTDIR/src/sql/drivers/mysql/qsql_mysql.cpp

Here's the code:

int QMYSQLResult::size()
{
if (isSelect())
if (d->d->preparedQuerys)
#if MYSQL_VERSION_ID >= 40108
return int(mysql_stmt_num_rows(d->stmt)); //<---we get here but d->stmt is null
#else
return -1;
#endif
else
return int(mysql_num_rows(d->result)); //<--- d->result is not null, maybe we should have got here
else
return -1;
}

When mysql_stmt_num_rows(d->stmt) is called it blows because d->stmt is 0x0.
Well I assume that's the reason; mysql_stmt_num_rows is in a mysql library and expects to see a "struct st_mysql_stmt" pointer.

I think I'll just put this down to a bug and move on - unless it rings any bells with anyone?

wysota
23rd January 2009, 14:28
Maybe the problem is not with Qt but with MySQL? Anyway you should report the problem to Qt Software - remember Qt4.5 is still in development phase.

onamatic
23rd January 2009, 16:32
Will do, thanks for your support.

onamatic
24th January 2009, 14:11
Solved!
The MySql driver in 4.5.0 incorrectly treat this code:

model.setQuery("SELECT sourceid FROM videosource");
as:

model.setQuery(QSqlQuery("SELECT sourceid FROM videosource"));
which is fine except that the QSqlQuery is later treated as a prepared query which it obviously isn't (see annotated code in previous post in this thread); the 4.4.3 driver doesn't make this mistake.
Workaround:

QSqlQueryModel model;
QSqlQuery query;
query.prepare("SELECT sourceid FROM videosource");
query.exec(); //must do this explicitly
model->setQuery(query);

I have reported this as a bug [#242208].
Thanks to all for help and support.

onamatic
25th January 2009, 22:06
Update:
The same bug rears its ugly head in this snippet:


sourcesTableModel = new QSqlTableModel();
sourcesTableModel->setTable("videosource");
sourcesTableModel->select(); //BANG! SIGSEGV

wysota
26th January 2009, 00:49
I assure you I'm working with QtSQL almost every day and such statements work just fine :) Your problem is related strictly to your installation and/or the version of Qt and/or MySQL you are using. If changing the version of Qt doesn't help, try changing the version of MySQL client library you are using.

onamatic
27th January 2009, 10:26
Thanks wysota - I had similar feedback from QT support regarding my bug report yesterday so I tried the latest snapshot; it works perfectly. :)

There had been several developments in qsql_mysql.cpp since the Beta1 release which were directly concerned with my problem.