aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2016-06-03 16:14:21 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-06-03 14:37:26 +0000
commit6d63e3ba09954ce7b56b4b24432bd036e636b164 (patch)
tree0111e8864a53b6636d9bf07b5f8c4d9eb9931cbc
parentb6c64c2ef3b1fd314ea85be003fd88d43e36ee54 (diff)
Fix bug in SQL database integration with null values
Since commit 91d6a63ab317817990c3b2306860adbd8916cca4 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>
-rw-r--r--src/imports/localstorage/plugin.cpp18
-rw-r--r--tests/auto/qml/qqmlsqldatabase/data/nullvalues.js24
-rw-r--r--tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp3
3 files changed, 40 insertions, 5 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index b8d7030763..d32bb0069d 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -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()) {
diff --git a/tests/auto/qml/qqmlsqldatabase/data/nullvalues.js b/tests/auto/qml/qqmlsqldatabase/data/nullvalues.js
new file mode 100644
index 0000000000..322a7aea03
--- /dev/null
+++ b/tests/auto/qml/qqmlsqldatabase/data/nullvalues.js
@@ -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;
+}
diff --git a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
index b5b77ad10b..debafa3fe4 100644
--- a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
+++ b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
@@ -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.