Fix bug in SQL database integration with null values
Since commit 91d6a63ab3
a null JS value is
mapped to a QVariant(VoidStar) to properly create null JS values when
converting back again. However that broke the binding of values in the SQL
database, where it ended up mapping null to an empty string.
[ChangeLog][QtQml] Fix mapping of null JS values to null SQL values instead
of empty strings.
Task-number: QTBUG-53412
Change-Id: Icf1fea4674e9dd8bb5313e3770ed2d3f99849987
Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
This commit is contained in:
parent
b6c64c2ef3
commit
6d63e3ba09
|
@ -257,6 +257,15 @@ static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx)
|
|||
return qmlsqldatabase_rows_index(r, scope.engine, ctx->argc() ? ctx->args()[0].toUInt32() : 0);
|
||||
}
|
||||
|
||||
static QVariant toSqlVariant(QV4::ExecutionEngine *engine, const QV4::ScopedValue &value)
|
||||
{
|
||||
// toVariant() maps a null JS value to QVariant(VoidStar), but the SQL module
|
||||
// expects a null variant. (this is because of QTBUG-40880)
|
||||
if (value->isNull())
|
||||
return QVariant();
|
||||
return engine->toVariant(value, /*typehint*/-1);
|
||||
}
|
||||
|
||||
static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
|
||||
{
|
||||
QV4::Scope scope(ctx);
|
||||
|
@ -287,8 +296,9 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
|
|||
ScopedArrayObject array(scope, values);
|
||||
quint32 size = array->getLength();
|
||||
QV4::ScopedValue v(scope);
|
||||
for (quint32 ii = 0; ii < size; ++ii)
|
||||
query.bindValue(ii, scope.engine->toVariant((v = array->getIndexed(ii)), -1));
|
||||
for (quint32 ii = 0; ii < size; ++ii) {
|
||||
query.bindValue(ii, toSqlVariant(scope.engine, (v = array->getIndexed(ii))));
|
||||
}
|
||||
} else if (values->as<Object>()) {
|
||||
ScopedObject object(scope, values);
|
||||
ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
|
||||
|
@ -298,7 +308,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
|
|||
key = it.nextPropertyName(val);
|
||||
if (key->isNull())
|
||||
break;
|
||||
QVariant v = scope.engine->toVariant(val, -1);
|
||||
QVariant v = toSqlVariant(scope.engine, val);
|
||||
if (key->isString()) {
|
||||
query.bindValue(key->stringValue()->toQString(), v);
|
||||
} else {
|
||||
|
@ -307,7 +317,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
query.bindValue(0, scope.engine->toVariant(values, -1));
|
||||
query.bindValue(0, toSqlVariant(scope.engine, values));
|
||||
}
|
||||
}
|
||||
if (query.exec()) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
.import QtQuick.LocalStorage 2.0 as Sql
|
||||
|
||||
function test() {
|
||||
var db = Sql.LocalStorage.openDatabaseSync("QmlTestDB-nullvalues", "", "Test database from Qt autotests", 1000000);
|
||||
var r="transaction_not_finished";
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS NullValues(salutation TEXT, salutee TEXT)');
|
||||
tx.executeSql('INSERT INTO NullValues VALUES(?, ?)', [ 'hello', null ]);
|
||||
var firstRow = tx.executeSql("SELECT * FROM NullValues").rows.item(0);
|
||||
if (firstRow.salutation !== "hello")
|
||||
return
|
||||
if (firstRow.salutee === "") {
|
||||
r = "wrong_data_type"
|
||||
return
|
||||
}
|
||||
if (firstRow.salutee === null)
|
||||
r = "passed";
|
||||
}
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
|
@ -127,7 +127,7 @@ void tst_qqmlsqldatabase::checkDatabasePath()
|
|||
QVERIFY(engine->offlineStoragePath().contains("OfflineStorage"));
|
||||
}
|
||||
|
||||
static const int total_databases_created_by_tests = 12;
|
||||
static const int total_databases_created_by_tests = 13;
|
||||
void tst_qqmlsqldatabase::testQml_data()
|
||||
{
|
||||
QTest::addColumn<QString>("jsfile"); // The input file
|
||||
|
@ -149,6 +149,7 @@ void tst_qqmlsqldatabase::testQml_data()
|
|||
QTest::newRow("error-outsidetransaction") << "error-outsidetransaction.js"; // reuse above
|
||||
QTest::newRow("reopen1") << "reopen1.js";
|
||||
QTest::newRow("reopen2") << "reopen2.js"; // re-uses above DB
|
||||
QTest::newRow("null-values") << "nullvalues.js";
|
||||
|
||||
// If you add a test, you should usually use a new database in the
|
||||
// test - in which case increment total_databases_created_by_tests above.
|
||||
|
|
Loading…
Reference in New Issue