diff options
-rw-r--r-- | doc/src/object-indexes.qdoc | 9 | ||||
-rw-r--r-- | src/daemon/jsondbindex.cpp | 13 | ||||
-rw-r--r-- | src/daemon/jsondbindex.h | 7 | ||||
-rw-r--r-- | src/daemon/jsondbobjecttable.cpp | 11 | ||||
-rw-r--r-- | src/daemon/jsondbobjecttable.h | 5 | ||||
-rw-r--r-- | src/daemon/jsondbpartition.cpp | 47 | ||||
-rw-r--r-- | src/daemon/jsondbpartition.h | 6 | ||||
-rw-r--r-- | src/daemon/jsondbreducedefinition.cpp | 3 | ||||
-rw-r--r-- | src/daemon/schema/Index.json | 1 | ||||
-rw-r--r-- | tests/auto/client/test-jsondb-client.cpp | 63 | ||||
-rw-r--r-- | tests/auto/daemon/json/map-reduce.json | 4 |
11 files changed, 138 insertions, 31 deletions
diff --git a/doc/src/object-indexes.qdoc b/doc/src/object-indexes.qdoc index ecf92f7..505b0b0 100644 --- a/doc/src/object-indexes.qdoc +++ b/doc/src/object-indexes.qdoc @@ -52,6 +52,15 @@ specified, name defaults to propertyName. If propertyFunction is specified, then name must be specified. \row +\li objectType +\li An optional string or array of strings, naming the object types to +be indexed. If not specified, all objects in the main object table of +a partition will be indexed. + +If specified for non-view types, the index should have a name that is +distinct from its propertyName. + +\row \li propertyName \li A string or array of strings, naming the properties to be indexed. Mutually exclusive with propertyFunction. diff --git a/src/daemon/jsondbindex.cpp b/src/daemon/jsondbindex.cpp index 586fd00..6c95015 100644 --- a/src/daemon/jsondbindex.cpp +++ b/src/daemon/jsondbindex.cpp @@ -100,10 +100,12 @@ JsonDbCollator::CasePreference _q_correctCasePreferenceString(const QString &s) #else int _q_correctCollationString(const QString &s) { + Q_UNUSED(s); return 0; } int _q_correctCasePreferenceString(const QString &s) { + Q_UNUSED(s); return 0; } #endif //NO_COLLATION_SUPPORT @@ -130,13 +132,15 @@ QString _q_bytesToHexString(const QByteArray &ba) } JsonDbIndex::JsonDbIndex(const QString &fileName, const QString &indexName, const QString &propertyName, - const QString &propertyType, const QString &locale, const QString &collation, + const QString &propertyType, const QStringList &objectType, const QString &locale, const QString &collation, const QString &casePreference, Qt::CaseSensitivity caseSensitivity, JsonDbObjectTable *objectTable) : QObject(objectTable) , mObjectTable(objectTable) + , mIndexName(indexName) , mPropertyName(propertyName) , mPath(propertyName.split('.')) , mPropertyType(propertyType) + , mObjectType(objectType) , mLocale(locale) , mCollation(collation) , mCasePreference(casePreference) @@ -239,7 +243,7 @@ bool JsonDbIndex::validateIndex(const JsonDbObject &newIndex, const JsonDbObject message = QString("Changing old index propertyType from '%1' to '%2' not supported") .arg(oldIndex.value(JsonDbString::kPropertyTypeStr).toString()) .arg(newIndex.value(JsonDbString::kPropertyTypeStr).toString()); - else if (oldIndex.value(JsonDbString::kObjectTypeStr).toString() != newIndex.value(JsonDbString::kObjectTypeStr).toString()) + else if (oldIndex.value(JsonDbString::kObjectTypeStr) != newIndex.value(JsonDbString::kObjectTypeStr)) message = QString("Changing old index objectType from '%1' to '%2' not supported") .arg(oldIndex.value(JsonDbString::kObjectTypeStr).toString()) .arg(newIndex.value(JsonDbString::kObjectTypeStr).toString()); @@ -330,6 +334,9 @@ void JsonDbIndex::indexObject(const ObjectKey &objectKey, JsonDbObject &object, if (mPropertyName == JsonDbString::kUuidStr) return; + if (!mObjectType.isEmpty() && !mObjectType.contains(object.value(JsonDbString::kTypeStr).toString())) + return; + Q_ASSERT(!object.contains(JsonDbString::kDeletedStr) && !object.value(JsonDbString::kDeletedStr).toBool()); QList<QJsonValue> fieldValues = indexValues(object); @@ -371,6 +378,8 @@ void JsonDbIndex::deindexObject(const ObjectKey &objectKey, JsonDbObject &object { if (mPropertyName == JsonDbString::kUuidStr) return; + if (!mObjectType.isEmpty() && !mObjectType.contains(object.value(JsonDbString::kTypeStr).toString())) + return; if (!mBdb) open(); QList<QJsonValue> fieldValues = indexValues(object); diff --git a/src/daemon/jsondbindex.h b/src/daemon/jsondbindex.h index 2cc9bcf..05569aa 100644 --- a/src/daemon/jsondbindex.h +++ b/src/daemon/jsondbindex.h @@ -73,7 +73,7 @@ class JsonDbIndex : public QObject Q_OBJECT public: JsonDbIndex(const QString &fileName, const QString &indexName, const QString &propertyName, - const QString &propertyType, const QString &locale, const QString &collation, + const QString &propertyType, const QStringList &objectType, const QString &locale, const QString &collation, const QString &casePreference, Qt::CaseSensitivity caseSensitivity, JsonDbObjectTable *objectTable); ~JsonDbIndex(); @@ -81,6 +81,7 @@ public: QString propertyName() const { return mPropertyName; } QStringList fieldPath() const { return mPath; } QString propertyType() const { return mPropertyType; } + QStringList objectType() const { return mObjectType; } JsonDbManagedBtree *bdb(); @@ -114,9 +115,11 @@ private slots: private: JsonDbObjectTable *mObjectTable; QString mFileName; + QString mIndexName; QString mPropertyName; QStringList mPath; QString mPropertyType; + QStringList mObjectType; QString mLocale; QString mCollation; QString mCasePreference; @@ -167,7 +170,7 @@ public: QString collation; QString casePreference; Qt::CaseSensitivity caseSensitivity; - QString objectType; + QStringList objectType; bool lazy; QPointer<JsonDbIndex> index; }; diff --git a/src/daemon/jsondbobjecttable.cpp b/src/daemon/jsondbobjecttable.cpp index 0b6a094..7557783 100644 --- a/src/daemon/jsondbobjecttable.cpp +++ b/src/daemon/jsondbobjecttable.cpp @@ -250,7 +250,7 @@ QHash<QString, IndexSpec> JsonDbObjectTable::indexSpecs() const } bool JsonDbObjectTable::addIndex(const QString &indexName, const QString &propertyName, - const QString &propertyType, const QString &objectType, const QString &propertyFunction, + const QString &propertyType, const QStringList &objectTypes, const QString &propertyFunction, const QString &locale, const QString &collation, const QString &casePreference, Qt::CaseSensitivity caseSensitivity) { @@ -274,9 +274,9 @@ bool JsonDbObjectTable::addIndex(const QString &indexName, const QString &proper indexSpec.collation = collation; indexSpec.casePreference = casePreference; indexSpec.caseSensitivity = caseSensitivity; - indexSpec.objectType = objectType; + indexSpec.objectType = objectTypes; indexSpec.lazy = false; //lazy; - indexSpec.index = new JsonDbIndex(mFilename, name, propertyName, propertyType, locale, collation, casePreference, caseSensitivity, this); + indexSpec.index = new JsonDbIndex(mFilename, name, propertyName, propertyType, objectTypes, locale, collation, casePreference, caseSensitivity, this); if (!propertyFunction.isEmpty() && propertyName.isEmpty()) // propertyName takes precedence indexSpec.index->setPropertyFunction(propertyFunction); indexSpec.index->setCacheSize(jsondbSettings->cacheSize()); @@ -292,7 +292,10 @@ bool JsonDbObjectTable::addIndex(const QString &indexName, const QString &proper indexObject.insert(JsonDbString::kCollationStr, collation); indexObject.insert(JsonDbString::kCaseSensitiveStr, (bool)caseSensitivity); indexObject.insert(JsonDbString::kCasePreferenceStr, casePreference); - indexObject.insert(JsonDbString::kObjectTypeStr, objectType); + QJsonArray objectTypeList; + foreach (const QString objectType, objectTypes) + objectTypeList.append(objectType); + indexObject.insert(JsonDbString::kObjectTypeStr, objectTypeList); indexObject.insert("lazy", false); indexObject.insert(JsonDbString::kPropertyFunctionStr, propertyFunction); Q_ASSERT(!name.isEmpty()); diff --git a/src/daemon/jsondbobjecttable.h b/src/daemon/jsondbobjecttable.h index 78ba241..f122006 100644 --- a/src/daemon/jsondbobjecttable.h +++ b/src/daemon/jsondbobjecttable.h @@ -141,7 +141,7 @@ public: bool addIndex(const QString &indexName, const QString &propertyName = QString(), const QString &propertyType = QString("string"), - const QString &objectType = QString(), + const QStringList &objectTypes = QStringList(), const QString &propertyFunction = QString(), const QString &locale = QString(), const QString &collation = QString(), @@ -150,7 +150,8 @@ public: bool addIndexOnProperty(const QString &propertyName, const QString &propertyType = QString("string"), const QString &objectType = QString()) - { return addIndex(propertyName, propertyName, propertyType, objectType); } + { return addIndex(propertyName, propertyName, propertyType, + objectType.isEmpty() ? QStringList() : (QStringList() << objectType)); } bool removeIndex(const QString &indexName); void reindexObjects(const QString &indexName, const QStringList &path, quint32 stateNumber); void indexObject(const ObjectKey &objectKey, JsonDbObject object, quint32 stateNumber); diff --git a/src/daemon/jsondbpartition.cpp b/src/daemon/jsondbpartition.cpp index df9f8e5..310157a 100644 --- a/src/daemon/jsondbpartition.cpp +++ b/src/daemon/jsondbpartition.cpp @@ -684,33 +684,52 @@ void JsonDbPartition::initIndexes() QString indexName = JsonDbIndex::determineName(indexObject); QString propertyName = indexObject.value(JsonDbString::kPropertyNameStr).toString(); QString propertyType = indexObject.value(JsonDbString::kPropertyTypeStr).toString(); - QString objectType = indexObject.value(JsonDbString::kObjectTypeStr).toString(); QString propertyFunction = indexObject.value(JsonDbString::kPropertyFunctionStr).toString(); QString locale = indexObject.value(JsonDbString::kLocaleStr).toString(); QString collation = indexObject.value(JsonDbString::kCollationStr).toString(); QString casePreference = indexObject.value(JsonDbString::kCasePreferenceStr).toString(); + QStringList objectTypes; + QJsonValue objectTypeValue = indexObject.value(JsonDbString::kObjectTypeStr); + if (objectTypeValue.isString()) { + objectTypes.append(objectTypeValue.toString()); + } else if (objectTypeValue.isArray()) { + foreach (const QJsonValue objectType, objectTypeValue.toArray()) + objectTypes.append(objectType.toString()); + } + Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; if (indexObject.contains(JsonDbString::kCaseSensitiveStr)) caseSensitivity = (indexObject.value(JsonDbString::kCaseSensitiveStr).toBool() == true ? Qt::CaseSensitive : Qt::CaseInsensitive); - addIndex(indexName, propertyName, propertyType, objectType, propertyFunction, locale, collation, casePreference, caseSensitivity); + addIndex(indexName, propertyName, propertyType, objectTypes, propertyFunction, locale, collation, casePreference, caseSensitivity); } } } bool JsonDbPartition::addIndex(const QString &indexName, const QString &propertyName, - const QString &propertyType, const QString &objectType, const QString &propertyFunction, + const QString &propertyType, const QStringList &objectTypes, const QString &propertyFunction, const QString &locale, const QString &collation, const QString &casePreference, Qt::CaseSensitivity caseSensitivity) { Q_ASSERT(!indexName.isEmpty()); //qDebug() << "JsonDbBtreePartition::addIndex" << propertyName << objectType; - JsonDbObjectTable *table = findObjectTable(objectType); + JsonDbObjectTable *table = 0; + if (objectTypes.isEmpty()) + table = mainObjectTable(); + else + foreach (const QString &objectType, objectTypes) { + JsonDbObjectTable *t = findObjectTable(objectType); + if (table && (t != table)) { + qDebug() << "addIndex" << "index on multiple tables" << objectTypes; + return false; + } + table = t; + } const IndexSpec *indexSpec = table->indexSpec(indexName); if (indexSpec) return true; //if (gVerbose) qDebug() << "JsonDbBtreePartition::addIndex" << propertyName << objectType; - return table->addIndex(indexName, propertyName, propertyType, objectType, propertyFunction, locale, collation, casePreference, caseSensitivity); + return table->addIndex(indexName, propertyName, propertyType, objectTypes, propertyFunction, locale, collation, casePreference, caseSensitivity); } bool JsonDbPartition::removeIndex(const QString &indexName, const QString &objectType) @@ -1654,10 +1673,20 @@ void JsonDbPartition::updateBuiltInTypes(const JsonDbObject &object, const JsonD if (object.contains(JsonDbString::kCaseSensitiveStr)) caseSensitivity = object.value(JsonDbString::kCaseSensitiveStr).toBool(); + QStringList objectTypes; + QJsonValue v = object.value(JsonDbString::kObjectTypeStr); + if (v.isString()) { + objectTypes = (QStringList() << v.toString()); + } else if (v.isArray()) { + QJsonArray array = v.toArray(); + foreach (const QJsonValue objectType, array) + objectTypes.append(objectType.toString()); + } + addIndex(indexName, object.value(JsonDbString::kPropertyNameStr).toString(), object.value(JsonDbString::kPropertyTypeStr).toString(), - object.value(JsonDbString::kObjectTypeStr).toString(), + objectTypes, object.value(JsonDbString::kPropertyFunctionStr).toString(), object.value(JsonDbString::kLocaleStr).toString(), object.value(JsonDbString::kCollationStr).toString(), @@ -1750,7 +1779,8 @@ void JsonDbPartition::updateSchemaIndexes(const QString &schemaName, QJsonObject QString propertyType = (propertyInfo.contains("type") ? propertyInfo.value("type").toString() : "string"); QStringList kpath = path; kpath << k; - addIndexOnProperty(kpath.join("."), propertyType, schemaName); + QString propertyName = kpath.join("."); + addIndex(propertyName, propertyName, propertyType); } if (propertyInfo.contains("properties")) updateSchemaIndexes(schemaName, propertyInfo, path + (QStringList() << k)); @@ -1850,6 +1880,7 @@ void JsonDbPartition::initSchemas() { JsonDbObject nameIndex; nameIndex.insert(JsonDbString::kTypeStr, JsonDbString::kIndexTypeStr); + nameIndex.insert(JsonDbString::kNameStr, QLatin1String("capabilityName")); nameIndex.insert(JsonDbString::kPropertyNameStr, QLatin1String("name")); nameIndex.insert(JsonDbString::kPropertyTypeStr, QLatin1String("string")); nameIndex.insert(JsonDbString::kObjectTypeStr, QLatin1String("Capability")); @@ -1866,7 +1897,7 @@ void JsonDbPartition::initSchemas() } JsonDbObject capability = QJsonObject::fromVariantMap(parser.result().toMap()); QString name = capability.value("name").toString(); - GetObjectsResult getObjectResponse = getObjects("name", name, "Capability"); + GetObjectsResult getObjectResponse = getObjects("capabilityName", name, "Capability"); int count = getObjectResponse.data.size(); if (!count) { if (jsondbSettings->verbose()) diff --git a/src/daemon/jsondbpartition.h b/src/daemon/jsondbpartition.h index e4c06a3..f58c8ec 100644 --- a/src/daemon/jsondbpartition.h +++ b/src/daemon/jsondbpartition.h @@ -116,16 +116,12 @@ public: bool addIndex(const QString &indexName, const QString &propertyName, const QString &propertyType = QString("string"), - const QString &objectType = QString(), + const QStringList &objectTypes = QStringList(), const QString &propertyFunction = QString(), const QString &locale = QString(), const QString &collation = QString(), const QString &casePreference = QString(), Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive); - bool addIndexOnProperty(const QString &propertyName, - const QString &propertyType = QString("string"), - const QString &objectType = QString()) - { return addIndex(propertyName, propertyName, propertyType, objectType); } bool removeIndex(const QString &indexName, const QString &objectType = QString()); bool checkQuota(const JsonDbOwner *owner, int size) const; diff --git a/src/daemon/jsondbreducedefinition.cpp b/src/daemon/jsondbreducedefinition.cpp index 1bc4c71..6de9f43 100644 --- a/src/daemon/jsondbreducedefinition.cpp +++ b/src/daemon/jsondbreducedefinition.cpp @@ -136,9 +136,6 @@ void JsonDbReduceDefinition::releaseScriptEngine() void JsonDbReduceDefinition::initIndexes() { - // TODO: this index should not be automatic - mTargetTable->addIndexOnProperty(mSourceKeyName, QLatin1String("string"), mSourceType); - // TODO: this index should not be automatic mTargetTable->addIndexOnProperty(mTargetKeyName, QLatin1String("string"), mTargetType); mTargetTable->addIndexOnProperty(QLatin1String("_reduceUuid"), QLatin1String("string"), mTargetType); } diff --git a/src/daemon/schema/Index.json b/src/daemon/schema/Index.json index d98cd5b..7c60d15 100644 --- a/src/daemon/schema/Index.json +++ b/src/daemon/schema/Index.json @@ -18,7 +18,6 @@ "description": "Type of values stored in that property." }, "objectType": { - "type": "string", "description": "Object type to index. Optional." } } diff --git a/tests/auto/client/test-jsondb-client.cpp b/tests/auto/client/test-jsondb-client.cpp index 39c8a46..eb138d1 100644 --- a/tests/auto/client/test-jsondb-client.cpp +++ b/tests/auto/client/test-jsondb-client.cpp @@ -98,6 +98,7 @@ private slots: void update(); void find(); void index(); + void multiTypeIndex(); void registerNotification(); void notify_data(); @@ -692,6 +693,15 @@ void TestJsonDbClient::find() int id = 0; int count; + // create an index on the name property of com.test.NameIndex objects + QVariantMap index; + index.insert(JsonDbString::kTypeStr, JsonDbString::kIndexTypeStr); + index.insert(JsonDbString::kNameStr, QLatin1String("com.test.NameIndex")); + index.insert(JsonDbString::kPropertyNameStr, QLatin1String("name")); + index.insert(JsonDbString::kObjectTypeStr, QLatin1String("com.test.find-test")); + id = mClient->create(index); + waitForResponse1(id); + QStringList nameList; // Create a few items for (count = 0 ; names[count] ; count++ ) { @@ -724,7 +734,7 @@ void TestJsonDbClient::find() // Find one, sorted in reverse alphabetical order query = QVariantMap(); - query.insert("query", "[?_type=\"com.test.find-test\"][\\name]"); + query.insert("query", "[?_type=\"com.test.find-test\"][\\com.test.NameIndex]"); id = mClient->find(query); waitForResponse1(id); answer = mData.toMap().value("data").toList(); @@ -752,7 +762,7 @@ void TestJsonDbClient::find() // Read should fail query = QVariantMap(); - query.insert("query", "[?_type=\"com.test.find-test\"][\\name]"); + query.insert("query", "[?_type=\"com.test.find-test\"][\\com.test.NameIndex]"); id = mClient->find(query); waitForResponse1(id); answer = mData.toMap().value("data").toList(); @@ -823,6 +833,55 @@ void TestJsonDbClient::index() waitForResponse1(id); } +void TestJsonDbClient::multiTypeIndex() +{ + QVERIFY(mClient); + + QVariantMap query; + int id = 0; + int count; + + QStringList indexedTypes = (QStringList() + << QLatin1String("com.test.find-test1") + << QLatin1String("com.test.find-test2")); + // create an index on the name property of com.test.NameIndex objects + QVariantMap index; + index.insert(JsonDbString::kTypeStr, JsonDbString::kIndexTypeStr); + index.insert(JsonDbString::kNameStr, QLatin1String("com.test.MultiTypeIndex")); + index.insert(JsonDbString::kPropertyNameStr, QLatin1String("name")); + index.insert(JsonDbString::kObjectTypeStr, indexedTypes); + id = mClient->create(index); + waitForResponse1(id); + + QStringList objectTypes = (QStringList() + << QLatin1String("com.test.find-test1") + << QLatin1String("com.test.find-test2") + << QLatin1String("com.test.find-test3")); + QStringList nameList; + // Create a few items + for (count = 0 ; names[count] ; count++ ) { + nameList << names[count]; + foreach (const QString objectType, objectTypes) { + QVariantMap item; + item.insert("_type", objectType); + item.insert("name", names[count]); + id = mClient->create(item); + waitForResponse1(id); + } + } + + // Find all in the index + query = QVariantMap(); + query.insert("query", "[?name exists][/com.test.MultiTypeIndex]"); + id = mClient->find(query); + waitForResponse1(id); + QVariantList answer = mData.toMap().value("data").toList(); + //qDebug() << "answer" << mData.toMap(); + QCOMPARE(answer.size(), nameList.size() * 2); + foreach (QVariant v, answer) + QVERIFY(indexedTypes.contains(v.toMap().value(JsonDbString::kTypeStr).toString())); +} + void TestJsonDbClient::notify_data() { QTest::addColumn<QString>("partition"); diff --git a/tests/auto/daemon/json/map-reduce.json b/tests/auto/daemon/json/map-reduce.json index a04ef1c..2736a9c 100644 --- a/tests/auto/daemon/json/map-reduce.json +++ b/tests/auto/daemon/json/map-reduce.json @@ -46,7 +46,7 @@ "name": "Phone", "schema": { "type": "object", - "extends": "View" + "extends": {"$ref": "View"} } }, { @@ -54,7 +54,7 @@ "name": "PhoneCount", "schema": { "type": "object", - "extends": "View" + "extends": {"$ref": "View"} } }, { |