PDA

View Full Version : QSqlQuery.clear() not clearing?



GreyGeek
5th May 2006, 22:59
My first production app has one annoying problem.

After a clerk makes about 150 record entries a/o changes the app throws an ORA-01000 error, meaning that MAX_OPEN_CURSORS has been reached. That value is 300 per user session.

I decided early on that I wanted to 'reuse' my queries so I thought I had designed them that way.

First, I declared the query in the header:


public:
QSqlQuery persQry;
...

then, in the class intializer code I put the same line.

In each function which used persQry I used the following method


myappclass::somefunction(){
...
QString somestr = "SELECT * ......";
persQry.clear();
persQry.exec(somestr);
...

}

Our Oracle Admin watched the cursor count and said that every time "persQry.exe(somestr);" was executed the cursor count would increase and never decrease. "persQry.clear();" made no difference at all.

The QT Assistance says that


void QSqlQuery::clear ()
Clears the result set and releases any resources held by the query. You should rarely if ever need to call this function.

Apparently it's only refering to QT resources, not Oracle cursors.
:confused:

Unless there is something I overlooked I'm going to have to rewrite the code using pointers on the heap instead of automatic variables on the stack. But, how do I know that the same problem won't still exist..? The Assistant didn't distuingish between queries made on the stack or the heap. persQry.clear() should clear the result set (cursor) and "any" resources.

jacek
5th May 2006, 23:04
What is that "myappclass" class? How many instances it has?

GreyGeek
6th May 2006, 05:19
homestead.h


#ifndef HOMESTEAD_H
#define HOMESTEAD_H
#include <QMainWindow>
class homestead : public QMainWindow
.....
{
Q_OBJECT

public:
homestead(QWidget *parent = 0);
....
QSqlQuery persQry;
....
...
}

and
homestead.cpp


/*
Program: homestead.cpp
*/
#include "homestead.h"
#include "wholenamedlg.h"
#include "historydialog.h"
...

homestead::homestead(QWidget *parent) : QMainWindow(parent) {
ui.setupUi(this); // draw the gui interface
...
// create global query objects
QSqlQuery persQry;
...
}
void homestead::searchAll() {
.....
QString queryStr = "";
...
if (ui.rbProprtyID->isChecked()) {
// user is searching for property id
requestString.append(" in Property");
ui.leStatus->setText(requestString);
queryStr = this->propPIDqryStr; // default property id select
queryStr.append(ui.leSearch->text()); // append property id
propQry.clear();
propQry.exec(queryStr);
if (propQry.first()){
// found property record, now fetch associated persinfo record
foundProp = true;
queryStr = this->persPIDqryStr;
queryStr.append(ui.leSearch->text());
persQry.clear();
persQry.exec(queryStr);
if (persQry.first()) {
foundPers = true;
}
...
}
...

and main.cpp


.....
int main( int argc, char * argv[] ) {
QString strRejected = "";
QApplication app(argc, argv);
app.setQuitOnLastWindowClosed(false);
dlgLogin dlg;
if( dlg.exec() == QDialog::Accepted ){
QSqlDatabase hapdb = QSqlDatabase::addDatabase(DBDRIVER);
hapdb.setHostName(DBHOST);
hapdb.setDatabaseName(DBNAME);
hapdb.setUserName(dlg.dui.leUserName->text());
hapdb.setPassword(dlg.dui.leUserPassword->text());
if ( hapdb.open() ) {
homestead ht;
ht.RevID = dlg.dui.leUserName->text();
ht.show();
app.setQuitOnLastWindowClosed(true);
return app.exec();
} else {
strRejected = QString("The Login was rejected because: %1").arg(hapdb.lastError().text()).toLatin1();
QMessageBox::information(0,"Login Rejected!",strRejected,
QMessageBox::Ok,QMessageBox::NoButton,QMessageBox: :NoButton);
return 1;
}
} else {
strRejected = QString("User Canceled the login!").toLatin1();
QMessageBox::information(0,"Login Rejected!",strRejected,
QMessageBox::Ok,QMessageBox::NoButton,QMessageBox: :NoButton);
return 2;
}
}


A cursor is created each time "persQry.exec(queryStr): is executed but it is not released by persQry.clear*() the next time the searchAll function is called.
The Oracle cursor count continues to increase until MAX_OPEN_CURSOR is reached.

zlatko
6th May 2006, 09:04
Why are you create in constructor global instance of QSqlQuery?

jacek
6th May 2006, 14:58
homestead::homestead(QWidget *parent) : QMainWindow(parent) {
ui.setupUi(this); // draw the gui interface
...
// create global query objects
QSqlQuery persQry;
...
}
This doesn't create a global object, but a local variable.


A cursor is created each time "persQry.exec(queryStr): is executed but it is not released by persQry.clear*() the next time the searchAll function is called.
The Oracle cursor count continues to increase until MAX_OPEN_CURSOR is reached.
Everything looks OK, so it's probably a Qt bug.

GreyGeek
6th May 2006, 15:40
This doesn't create a global object, but a local variable.

True, but it's "global" to all the functions in the homestead class, so I don't have to pass the query object from function to function.


Everything looks OK, so it's probably a Qt bug.

I came to your conclusions too, but I'm a relative newbie to QT and C++, and was not absolutely sure. I value yours and Wyota's opinions highly and hoped you'd answer, which is why I posted my question. We have a support contract and I've posted the question to the QT support staff. I'll let you know what they tell me.

Rats! I was hoping that it was my coding error., :( , and that it could be fixed quickly with a minor change or the addition of some "secret" paramter in the query intialization. But, it looks like it will only be fixed by a support patch or by upgrading QT 4.1 itself. That was something I was puttng off until I finished my second project, which I am deep into.

jacek
6th May 2006, 16:06
True, but it's "global" to all the functions in the homestead class, so I don't have to pass the query object from function to function.
Unfortunately it's not --- you are writing about this variable:

class homestead : public QMainWindow
{
...
QSqlQuery persQry; // <---
...
}
While this one:
homestead::homestead(QWidget *parent) : QMainWindow(parent) {
...
// create global query objects
QSqlQuery persQry; // <---
...
}
Is a local variable and it will be destroyed when the constructor ends.

Here's a classic example of this error: http://www.qtcentre.org/forum/showthread.php?t=2078