Browse Source

Plug database connection leak. Script bindings no longer use default connection.

Neal Wilson 11 years ago
parent
commit
be18697e70
1 changed files with 40 additions and 48 deletions
  1. 40
    48
      src/typica.w

+ 40
- 48
src/typica.w View File

3369
 	public:@/
3369
 	public:@/
3370
 		SqlQueryConnection(const QString &query = QString());
3370
 		SqlQueryConnection(const QString &query = QString());
3371
 		~SqlQueryConnection();
3371
 		~SqlQueryConnection();
3372
-		QSqlQuery* operator->();
3372
+		QSqlQuery* operator->() const;
3373
 	private:@/
3373
 	private:@/
3374
 		QString connection;
3374
 		QString connection;
3375
 		QSqlQuery *q;
3375
 		QSqlQuery *q;
3409
 object.
3409
 object.
3410
 
3410
 
3411
 @<SqlQueryConnection implementation@>=
3411
 @<SqlQueryConnection implementation@>=
3412
-QSqlQuery* SqlQueryConnection::operator->()
3412
+QSqlQuery* SqlQueryConnection::operator->() const
3413
 {
3413
 {
3414
 	return q;
3414
 	return q;
3415
 }
3415
 }
3448
 @<Functions for scripting@>=
3448
 @<Functions for scripting@>=
3449
 QScriptValue constructQSqlQuery(QScriptContext *, QScriptEngine *engine)
3449
 QScriptValue constructQSqlQuery(QScriptContext *, QScriptEngine *engine)
3450
 {
3450
 {
3451
+	SqlQueryConnection *obj = new SqlQueryConnection();
3451
 	QScriptValue object =
3452
 	QScriptValue object =
3452
-	     engine->toScriptValue<void *>(new SqlQueryConnection());
3453
+	     engine->toScriptValue<void *>(obj);
3453
 	setQSqlQueryProperties(object, engine);
3454
 	setQSqlQueryProperties(object, engine);
3454
 	return object;
3455
 	return object;
3455
 }
3456
 }
3478
 @<Functions for scripting@>=
3479
 @<Functions for scripting@>=
3479
 QScriptValue QSqlQuery_exec(QScriptContext *context, QScriptEngine *engine)
3480
 QScriptValue QSqlQuery_exec(QScriptContext *context, QScriptEngine *engine)
3480
 {
3481
 {
3481
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3482
+	QSqlQuery *q = getself<SqlQueryConnection *>(context)->operator->();
3482
 	QScriptValue retval;
3483
 	QScriptValue retval;
3483
 	if(context->argumentCount() == 1)
3484
 	if(context->argumentCount() == 1)
3484
 	{
3485
 	{
3485
 		retval = QScriptValue(engine,
3486
 		retval = QScriptValue(engine,
3486
-		                      query->exec(argument<QString>(0, context)));
3487
+		                      q->exec(argument<QString>(0, context)));
3487
 	}
3488
 	}
3488
 	else
3489
 	else
3489
 	{
3490
 	{
3490
-		retval = QScriptValue(engine, query->exec());
3491
+		retval = QScriptValue(engine, q->exec());
3491
 	}
3492
 	}
3492
-	if(query->lastError().isValid())
3493
+	if(q->lastError().isValid())
3493
 	{
3494
 	{
3494
-		qDebug() << query->lastQuery();
3495
-		qDebug() << query->lastError().text();
3495
+		qDebug() << q->lastQuery();
3496
+		qDebug() << q->lastError().text();
3496
 	}
3497
 	}
3497
 	return retval;
3498
 	return retval;
3498
 }
3499
 }
3499
 
3500
 
3500
 QScriptValue QSqlQuery_executedQuery(QScriptContext *context, QScriptEngine *)
3501
 QScriptValue QSqlQuery_executedQuery(QScriptContext *context, QScriptEngine *)
3501
 {
3502
 {
3502
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3503
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3503
 	return QScriptValue(query->lastQuery());
3504
 	return QScriptValue(query->lastQuery());
3504
 }
3505
 }
3505
 
3506
 
3506
 QScriptValue QSqlQuery_next(QScriptContext *context, QScriptEngine *engine)
3507
 QScriptValue QSqlQuery_next(QScriptContext *context, QScriptEngine *engine)
3507
 {
3508
 {
3508
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3509
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3509
 	return QScriptValue(engine, query->next());
3510
 	return QScriptValue(engine, query->next());
3510
 }
3511
 }
3511
 
3512
 
3512
 QScriptValue QSqlQuery_value(QScriptContext *context, QScriptEngine *engine)
3513
 QScriptValue QSqlQuery_value(QScriptContext *context, QScriptEngine *engine)
3513
 {
3514
 {
3514
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3515
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3515
 	return QScriptValue(engine,
3516
 	return QScriptValue(engine,
3516
 	                    query->value(argument<int>(0, context)).toString());
3517
 	                    query->value(argument<int>(0, context)).toString());
3517
 }
3518
 }
3522
 @<Functions for scripting@>=
3523
 @<Functions for scripting@>=
3523
 QScriptValue QSqlQuery_prepare(QScriptContext *context, QScriptEngine *engine)
3524
 QScriptValue QSqlQuery_prepare(QScriptContext *context, QScriptEngine *engine)
3524
 {
3525
 {
3525
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3526
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3526
 	return QScriptValue(engine, query->prepare(argument<QString>(0, context)));
3527
 	return QScriptValue(engine, query->prepare(argument<QString>(0, context)));
3527
 }
3528
 }
3528
 
3529
 
3529
 QScriptValue QSqlQuery_bind(QScriptContext *context, QScriptEngine *)
3530
 QScriptValue QSqlQuery_bind(QScriptContext *context, QScriptEngine *)
3530
 {
3531
 {
3531
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3532
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3532
 	query->bindValue(argument<QString>(0, context),
3533
 	query->bindValue(argument<QString>(0, context),
3533
 	                 argument<QVariant>(1, context));
3534
 	                 argument<QVariant>(1, context));
3534
 	return QScriptValue();
3535
 	return QScriptValue();
3537
 QScriptValue QSqlQuery_bindFileData(QScriptContext *context,
3538
 QScriptValue QSqlQuery_bindFileData(QScriptContext *context,
3538
                                     QScriptEngine *)
3539
                                     QScriptEngine *)
3539
 {
3540
 {
3540
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3541
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3541
 	QString placeholder = argument<QString>(0, context);
3542
 	QString placeholder = argument<QString>(0, context);
3542
 	QString filename = argument<QString>(1, context);
3543
 	QString filename = argument<QString>(1, context);
3543
 	QFile file(filename);
3544
 	QFile file(filename);
3554
 QScriptValue QSqlQuery_bindDeviceData(QScriptContext *context,
3555
 QScriptValue QSqlQuery_bindDeviceData(QScriptContext *context,
3555
                                       QScriptEngine *)
3556
                                       QScriptEngine *)
3556
 {
3557
 {
3557
-	SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
3558
+	QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
3558
 	QString placeholder = argument<QString>(0, context);
3559
 	QString placeholder = argument<QString>(0, context);
3559
 	QIODevice *device = argument<QIODevice *>(1, context);
3560
 	QIODevice *device = argument<QIODevice *>(1, context);
3560
 	device->reset();
3561
 	device->reset();
3680
 @<Functions for scripting@>=
3681
 @<Functions for scripting@>=
3681
 QScriptValue annotationFromRecord(QScriptContext *context, QScriptEngine *)
3682
 QScriptValue annotationFromRecord(QScriptContext *context, QScriptEngine *)
3682
 {
3683
 {
3683
-	SqlQueryConnection query;
3684
+	SqlQueryConnection h;
3685
+	QSqlQuery *query = h.operator->();
3684
 	QString q = "SELECT file FROM files WHERE id = :file";
3686
 	QString q = "SELECT file FROM files WHERE id = :file";
3685
-	query.prepare(q);
3686
-	query.bindValue(":file", argument<int>(0, context));
3687
-	query.exec();
3688
-	query.next();
3689
-	QByteArray array = query.value(0).toByteArray();
3687
+	query->prepare(q);
3688
+	query->bindValue(":file", argument<int>(0, context));
3689
+	query->exec();
3690
+	query->next();
3691
+	QByteArray array = query->value(0).toByteArray();
3690
 	QBuffer buffer(&array);
3692
 	QBuffer buffer(&array);
3691
 	buffer.open(QIODevice::ReadOnly);
3693
 	buffer.open(QIODevice::ReadOnly);
3692
 	QXmlQuery xquery;
3694
 	QXmlQuery xquery;
11798
 @ The |database()| method provides access to a database connection for use by
11800
 @ The |database()| method provides access to a database connection for use by
11799
 database aware widgets.
11801
 database aware widgets.
11800
 
11802
 
11801
-\danger Behavior observed on Linux is that this does create a new connection
11802
-which the caller will successfully open, but a |QSqlQuery| created with the
11803
-newly opened |QSqlDatabase| will instead continue to execute queries on the
11804
-default connection instead of the new connection. Replacing the call to
11805
-|QSqlDatabase::database()| with one that does not open the default connection
11806
-or rather than cloning that connection creating a new non-default connection
11807
-results in query execution failing because the connection is not open despite
11808
-the call to |open()| succeeding and |isValid()| and |isOpen()| both returning
11809
-true. If this behavior can be replicated on other platforms, this entire
11810
-exercise would be pointless. At present I believe this to be a bug in Qt, but I
11811
-have not identified it.
11812
-
11813
 @<Application Implementation@>=
11803
 @<Application Implementation@>=
11814
 QSqlDatabase Application::database()
11804
 QSqlDatabase Application::database()
11815
 {
11805
 {
11816
 	QString connectionName;
11806
 	QString connectionName;
11817
-	QSqlDatabase connection = QSqlDatabase::database();
11807
+	QSqlDatabase connection =
11808
+		QSqlDatabase::database(QLatin1String(QSqlDatabase::defaultConnection), false);
11818
 	do
11809
 	do
11819
 	{
11810
 	{
11820
 		connectionName = QUuid::createUuid().toString();
11811
 		connectionName = QUuid::createUuid().toString();
11821
 	} while (QSqlDatabase::connectionNames().contains(connectionName));
11812
 	} while (QSqlDatabase::connectionNames().contains(connectionName));
11822
-	return QSqlDatabase::cloneDatabase(connection, connectionName);
11813
+	return QSqlDatabase::cloneDatabase(connection, QString(connectionName));
11823
 }
11814
 }
11824
 
11815
 
11825
 @** Table editor for ordered arrays with SQL relations.
11816
 @** Table editor for ordered arrays with SQL relations.
12265
 @<SqlComboBox Implementation@>=
12256
 @<SqlComboBox Implementation@>=
12266
 void SqlComboBox::addSqlOptions(QString query)
12257
 void SqlComboBox::addSqlOptions(QString query)
12267
 {
12258
 {
12268
-	SqlQueryConnection *dbquery = new SqlQueryConnection;
12259
+	SqlQueryConnection h;
12260
+	QSqlQuery *dbquery = h.operator->();
12269
 	if(!dbquery->exec(query))
12261
 	if(!dbquery->exec(query))
12270
 	{
12262
 	{
12271
 		QSqlError error = dbquery->lastError();
12263
 		QSqlError error = dbquery->lastError();
12285
 		}
12277
 		}
12286
 		addItem(displayValue, dataValue);
12278
 		addItem(displayValue, dataValue);
12287
 	}
12279
 	}
12288
-	delete dbquery;
12289
 }
12280
 }
12290
 
12281
 
12291
 @ The constructor initializes some private member data. A size policy is also
12282
 @ The constructor initializes some private member data. A size policy is also
13207
 change to the table and the next child element, if any, will be processed.
13198
 change to the table and the next child element, if any, will be processed.
13208
 
13199
 
13209
 @<Add SQL query results to report table@>=
13200
 @<Add SQL query results to report table@>=
13210
-SqlQueryConnection query;
13211
-query.prepare(currentElement.text());
13201
+SqlQueryConnection h;
13202
+QSqlQuery *query = h.operator->();
13203
+query->prepare(currentElement.text());
13212
 foreach(QString key, bindings.uniqueKeys())
13204
 foreach(QString key, bindings.uniqueKeys())
13213
 {
13205
 {
13214
 	if(currentElement.text().contains(key))
13206
 	if(currentElement.text().contains(key))
13215
 	{
13207
 	{
13216
-		query.bindValue(key, bindings.value(key));
13208
+		query->bindValue(key, bindings.value(key));
13217
 	}
13209
 	}
13218
 }
13210
 }
13219
-query.exec();
13220
-if(!query.next())
13211
+query->exec();
13212
+if(!query->next())
13221
 {
13213
 {
13222
 	continue;
13214
 	continue;
13223
 }
13215
 }
13224
-if(query.record().count() > columns)
13216
+if(query->record().count() > columns)
13225
 {
13217
 {
13226
-	table->appendColumns(query.record().count() - columns);
13218
+	table->appendColumns(query->record().count() - columns);
13227
 }
13219
 }
13228
 do
13220
 do
13229
 {
13221
 {
13230
 	table->appendRows(1);
13222
 	table->appendRows(1);
13231
 	rows++;
13223
 	rows++;
13232
 	currentRow++;
13224
 	currentRow++;
13233
-	for(int j = 0; j < query.record().count(); j++)
13225
+	for(int j = 0; j < query->record().count(); j++)
13234
 	{
13226
 	{
13235
 		QTextTableCell cell = table->cellAt(currentRow, j);
13227
 		QTextTableCell cell = table->cellAt(currentRow, j);
13236
 		cursor = cell.firstCursorPosition();
13228
 		cursor = cell.firstCursorPosition();
13237
-		cursor.insertText(query.value(j).toString());
13229
+		cursor.insertText(query->value(j).toString());
13238
 	}
13230
 	}
13239
-} while(query.next());
13231
+} while(query->next());
13240
 
13232
 
13241
 @ It is sometimes desirable to add fixed data such as column headers to a table.
13233
 @ It is sometimes desirable to add fixed data such as column headers to a table.
13242
 This is done with the {\tt <row>} element.
13234
 This is done with the {\tt <row>} element.

Loading…
Cancel
Save