diff options
author | Kevin Simons <kevin.simons@nokia.com> | 2012-03-22 22:37:09 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-23 11:12:31 +0100 |
commit | 0cccd2a43899afbf212f0357b36a91ab0aa84cda (patch) | |
tree | 4cfb6f159469efba2f8c52619214564b9559cbf5 | |
parent | f2b546dab332214d02204f07bf9213eb48f5c470 (diff) |
Support arbitrary JSON terms in "contains" queries
Fixes Bug #3395.
Change-Id: I1cb9859aba5d557af456aa90880a39a8f30c4d09
Reviewed-by: Jamey Hicks <jamey.hicks@nokia.com>
Reviewed-by: Denis Dzyubenko <denis.dzyubenko@nokia.com>
-rw-r--r-- | src/daemon/jsondbquery.cpp | 53 | ||||
-rw-r--r-- | tests/auto/queries/dataset.json | 17 | ||||
-rw-r--r-- | tests/auto/queries/testjsondbqueries.cpp | 24 |
3 files changed, 91 insertions, 3 deletions
diff --git a/src/daemon/jsondbquery.cpp b/src/daemon/jsondbquery.cpp index 4e29930..be38e2c 100644 --- a/src/daemon/jsondbquery.cpp +++ b/src/daemon/jsondbquery.cpp @@ -41,6 +41,8 @@ #include <QDebug> #include <QFile> +#include <QJsonDocument> +#include <QStack> #include <QString> #include <QStringList> @@ -341,6 +343,57 @@ JsonDbQuery *JsonDbQuery::parse(const QString &query, const QJsonObject &binding term.regExp().setCaseSensitivity(Qt::CaseInsensitive); //qDebug() << "pattern" << tvs.mid(2, eor-2); term.regExp().setPattern(tvs.mid(2, eor-2)); + } else if (op == "contains") { + bool ok = true;; + + QString value = tokenizer.pop(); + if (value == "[" || value == "{") { + QStack<QString> tokenStack; + tokenStack.push(value); + QString tkn = value; + + while (ok && !tkn.isEmpty()) { + tkn = tokenizer.pop(); + if (tkn == "]" && tokenStack.isEmpty()) { + tokenizer.push(tkn); + break; + } else { + value += tkn; + if (tkn == "]") { + if (tokenStack.pop() != "[") + ok = false; + } else if (tkn == "}") { + if (tokenStack.pop() != "{") + ok = false; + } + } + } + + if (ok) { + QJsonParseError parserError; + QJsonDocument parsedValue = QJsonDocument::fromJson(value.toUtf8(), &parserError); + if (parserError.error != QJsonParseError::NoError) { + ok = false; + } else { + if (parsedValue.isArray()) + term.setValue(parsedValue.array()); + else + term.setValue(parsedValue.object()); + } + } + } else { + parseJsonLiteral(value, &term, bindings, &ok); + } + + if (!ok) { + parsedQuery->queryExplanation.append(QString("Failed to parse query value '%1' in query '%2' %3 op %4") + .arg(value) + .arg(parsedQuery->query) + .arg(fieldSpec) + .arg(op)); + parseError = true; + break; + } } else if ((op != "exists") && (op != "notExists")) { QString value = tokenizer.pop(); bool ok = true;; diff --git a/tests/auto/queries/dataset.json b/tests/auto/queries/dataset.json index 8585e44..7697e29 100644 --- a/tests/auto/queries/dataset.json +++ b/tests/auto/queries/dataset.json @@ -18,8 +18,6 @@ "num-demon-bunnies":3, "num-russian-bunnies":2 }, - - { "_type" : "dragon", "name": "marcia d'arcy", @@ -151,5 +149,20 @@ "name": "thomas reim", "type":"russian", "age": 8 + }, + { + "_type" : "dog", + "name" : "rover", + "friends" : ["spike", "reggie"] + }, + { + "_type" : "dog", + "name" : "spike", + "friends" : [ { "name" : "rover", "dog" : true }, { "name" : "puffy", "dog" : false } ] + }, + { + "_type" : "dog", + "name" : "reggie", + "friends" : [ ["larrry", "curly", "moe"], ["spike", "rover"] ] } ] diff --git a/tests/auto/queries/testjsondbqueries.cpp b/tests/auto/queries/testjsondbqueries.cpp index 700c132..d5218b6 100644 --- a/tests/auto/queries/testjsondbqueries.cpp +++ b/tests/auto/queries/testjsondbqueries.cpp @@ -98,6 +98,7 @@ private slots: void queryNotEqual(); void queryQuotedProperties(); void querySortedByIndexName(); + void queryContains(); void queryInvalid(); private: @@ -427,10 +428,31 @@ void TestJsonDbQueries::querySortedByIndexName() QVERIFY(confirmEachObject(queryResult.data, CheckSortOrder<double>("age", QList<double>() << 8 << 8 << 6 << 6 << 4 << 4 << 2 << 2 << 0 << 0))); } +void TestJsonDbQueries::queryContains() +{ + JsonDbQueryResult queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains \"spike\" ]")); + QVERIFY(queryResult.error.isNull()); + QCOMPARE(queryResult.data.count(), 1); + queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains { \"name\" : \"puffy\", \"dog\" : false } ]")); + QVERIFY(queryResult.error.isNull()); + QCOMPARE(queryResult.data.count(), 1); + queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains [\"spike\", \"rover\"] ]")); + QVERIFY(queryResult.error.isNull()); + QCOMPARE(queryResult.data.count(), 1); + + // invalid queries + queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains { \"name\" : \"puffy\" \"dog\" : false } ]")); + QVERIFY(!queryResult.error.isNull()); + queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains [\"spike\", \"rover\" ]")); + QVERIFY(!queryResult.error.isNull()); + queryResult = find(mOwner, QLatin1String("[?_type = \"dog\"][?friends contains \"spike\", \"rover\" ] ]")); + QVERIFY(!queryResult.error.isNull()); +} + void TestJsonDbQueries::queryInvalid() { JsonDbQueryResult queryResult = find(mOwner, QLatin1String("foo")); - QVERIFY(queryResult.data.isEmpty()); + QVERIFY(!queryResult.error.isNull()); } QTEST_MAIN(TestJsonDbQueries) |