From a401934d622d458180db0f1d11bd0b542bc74775 Mon Sep 17 00:00:00 2001 From: Vasiliy Date: Tue, 17 Jul 2018 15:21:07 +0300 Subject: [PATCH] issue 399.3: remove internal persisted proerty 'collections' from externally generated IResearchView jSON (#5874) * issue 399.3: remove internal persisted proerty 'collections' from externally generated IResearchView jSON * backport: address test failure * backport: address another test failure --- .../Books/Manual/Views/ArangoSearch/README.md | 20 - arangod/IResearch/IResearchCommon.cpp | 1 - arangod/IResearch/IResearchCommon.h | 6 - arangod/IResearch/IResearchView.cpp | 240 +-- arangod/IResearch/IResearchView.h | 17 +- .../IResearch/IResearchViewCoordinator.cpp | 38 +- arangod/IResearch/IResearchViewCoordinator.h | 7 +- arangod/IResearch/IResearchViewDBServer.cpp | 41 +- arangod/IResearch/IResearchViewDBServer.h | 5 +- arangod/VocBase/LogicalView.cpp | 102 +- arangod/VocBase/LogicalView.h | 56 +- .../aql/aql-view-arangosearch-ddl-cluster.js | 36 +- .../aql-view-arangosearch-ddl-noncluster.js | 16 +- js/server/tests/dump/dump-mmfiles.js | 2 +- js/server/tests/dump/dump-rocksdb.js | 2 +- tests/IResearch/IResearchView-test.cpp | 1348 ++++++++++++----- .../IResearchViewCoordinator-test.cpp | 10 +- .../IResearch/IResearchViewDBServer-test.cpp | 275 +++- tests/Utils/CollectionNameResolver-test.cpp | 13 +- tests/VocBase/vocbase-test.cpp | 13 +- 20 files changed, 1479 insertions(+), 769 deletions(-) diff --git a/Documentation/Books/Manual/Views/ArangoSearch/README.md b/Documentation/Books/Manual/Views/ArangoSearch/README.md index bf696745b9..d432b67723 100644 --- a/Documentation/Books/Manual/Views/ArangoSearch/README.md +++ b/Documentation/Books/Manual/Views/ArangoSearch/README.md @@ -186,14 +186,6 @@ During view modification the following directives apply: impact performance and waste disk space for each commit call without any added benefits - * commitTimeoutMsec: (optional; default: `5000`; to disable use: `0`) - try to commit as much as possible before *count* milliseconds - for the case where there are a lot of inserts/updates, a lower value will - cause a delay in the view accounting for them, due skipping of some commits - for the case where there are a lot of inserts/updates, a higher value will - cause higher memory consumption between commits due to accumulation of - document modifications while a commit is in progress - * consolidate: (optional; default: `none`) a per-policy mapping of thresholds in the range `[0.0, 1.0]` to determine data store segment merge candidates, if specified then only the listed policies @@ -235,18 +227,6 @@ During view modification the following directives apply: * locale: (optional; default: `C`) the default locale used for ordering processed attribute names -### View properties (unmodifiable) - -* collections: - an internally tracked list of collection identifiers which were explicitly - added to the current view by the user via view 'link' property modification - the list may have no-longer valid identifiers if the user did not explicitly - drop the link for the said collection identifier from the current view - invalid collection identifiers are removed during view property modification - among other things used for acquiring collection locks in transactions (i.e. - during a view query no documents will be returned for collections not in this - list) and generating view properties 'links' list - ### Link properties * analyzers: (optional; default: `[ 'identity' ]`) diff --git a/arangod/IResearch/IResearchCommon.cpp b/arangod/IResearch/IResearchCommon.cpp index 0617bf6d90..66a602a3d2 100644 --- a/arangod/IResearch/IResearchCommon.cpp +++ b/arangod/IResearch/IResearchCommon.cpp @@ -51,7 +51,6 @@ arangodb::LogTopic& logTopic() { // --SECTION-- StaticStrings // ----------------------------------------------------------------------------- -std::string const StaticStrings::CollectionsField("collections"); std::string const StaticStrings::LinksField("links"); std::string const StaticStrings::PropertiesField("properties"); std::string const StaticStrings::ViewIdField("view"); diff --git a/arangod/IResearch/IResearchCommon.h b/arangod/IResearch/IResearchCommon.h index cf89430ef2..60244367bc 100644 --- a/arangod/IResearch/IResearchCommon.h +++ b/arangod/IResearch/IResearchCommon.h @@ -37,12 +37,6 @@ static auto& DATA_SOURCE_TYPE = dataSourceType(); static auto& TOPIC = logTopic(); struct StaticStrings { - //////////////////////////////////////////////////////////////////////////////// - /// @brief the name of the field in the IResearch View definition denoting the - /// corresponding linked collections - //////////////////////////////////////////////////////////////////////////////// - static std::string const CollectionsField; - //////////////////////////////////////////////////////////////////////////////// /// @brief the name of the field in the IResearch View definition denoting the /// corresponding link definitions diff --git a/arangod/IResearch/IResearchView.cpp b/arangod/IResearch/IResearchView.cpp index 4bc6916145..133392fb4f 100644 --- a/arangod/IResearch/IResearchView.cpp +++ b/arangod/IResearch/IResearchView.cpp @@ -664,7 +664,7 @@ IResearchView::IResearchView( arangodb::velocypack::Slice const& info, arangodb::DatabasePathFeature const& dbPathFeature, uint64_t planVersion -): DBServerLogicalView(vocbase, info, planVersion), +): LogicalViewStorageEngine(vocbase, info, planVersion), FlushTransaction(toString(*this)), _asyncFeature(nullptr), _asyncSelf(irs::memory::make_unique(this)), @@ -935,6 +935,136 @@ IResearchView::MemoryStore& IResearchView::activeMemoryStore() const { return _memoryNode->_store; } +arangodb::Result IResearchView::appendVelocyPackDetailed( + arangodb::velocypack::Builder& builder, + bool forPersistence +) const { + if (!builder.isOpenObject()) { + return arangodb::Result(TRI_ERROR_BAD_PARAMETER); + } + + builder.add( + StaticStrings::PropertiesField, + arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) + ); + + auto closePropertiesField = // close StaticStrings::PropertiesField + irs::make_finally([&builder]()->void { builder.close(); }); + std::vector collections; + + { + ReadMutex mutex(_mutex); + SCOPED_LOCK(mutex); // '_metaState' can be asynchronously updated + + auto meta = std::atomic_load(&_meta); + SCOPED_LOCK(meta->read()); // '_meta' can be asynchronously updated + + if (!meta->json(builder)) { + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("failure to generate definition while generating properties jSON for IResearch View in database '") + vocbase().name() + "'" + ); + } + + if (forPersistence) { + _metaState.json(builder); + + return arangodb::Result(); // nothing more to output (persistent configuration does not need links) + } + + // add CIDs of known collections to list + for (auto& entry: _metaState._collections) { + // skip collections missing from vocbase or UserTransaction constructor will throw an exception + if (vocbase().lookupCollection(entry)) { + collections.emplace_back(std::to_string(entry)); + } + } + } + + arangodb::velocypack::Builder linksBuilder; + static std::vector const EMPTY; + + // use default lock timeout + arangodb::transaction::Options options; + + options.waitForSync = false; + options.allowImplicitCollections = false; + + try { + arangodb::transaction::Methods trx( + transaction::StandaloneContext::Create(vocbase()), + collections, // readCollections + EMPTY, // writeCollections + EMPTY, // exclusiveCollections + options + ); + auto res = trx.begin(); + + if (!res.ok()) { + return res; // nothing more to output + } + + auto* state = trx.state(); + + if (!state) { + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("failed to get transaction state while generating json for IResearch view '") + name() + "'" + ); + } + + arangodb::velocypack::ObjectBuilder linksBuilderWrapper(&linksBuilder); + + for (auto& collectionName: state->collectionNames()) { + for (auto& index: trx.indexesForCollection(collectionName)) { + if (index && arangodb::Index::IndexType::TRI_IDX_TYPE_IRESEARCH_LINK == index->type()) { + // TODO FIXME find a better way to retrieve an iResearch Link + // cannot use static_cast/reinterpret_cast since Index is not related to IResearchLink + auto* ptr = dynamic_cast(index.get()); + + if (!ptr || *ptr != *this) { + continue; // the index is not a link for the current view + } + + arangodb::velocypack::Builder linkBuilder; + + linkBuilder.openObject(); + + if (!ptr->json(linkBuilder, false)) { + LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) + << "failed to generate json for IResearch link '" << ptr->id() + << "' while generating json for IResearch view '" << id() << "'"; + continue; // skip invalid link definitions + } + + linkBuilder.close(); + linksBuilderWrapper->add(collectionName, linkBuilder.slice()); + } + } + } + + trx.commit(); + } catch (std::exception const& e) { + IR_LOG_EXCEPTION(); + + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("caught exception while generating json for IResearch view '") + name() + "': " + e.what() + ); + } catch (...) { + IR_LOG_EXCEPTION(); + + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("caught exception while generating json for IResearch view '") + name() + "'" + ); + } + + builder.add(StaticStrings::LinksField, linksBuilder.slice()); + + return arangodb::Result(); +} + bool IResearchView::apply(arangodb::transaction::Methods& trx) { // called from IResearchView when this view is added to a transaction return trx.addStatusChangeCallback(&_trxReadCallback); // add shapshot @@ -1186,110 +1316,6 @@ arangodb::Result IResearchView::commit() { return {TRI_ERROR_INTERNAL}; } -void IResearchView::getPropertiesVPack( - arangodb::velocypack::Builder& builder, bool forPersistence -) const { - ReadMutex mutex(_mutex); - SCOPED_LOCK(mutex); // '_metaState'/'_links' can be asynchronously updated - - { - auto meta = std::atomic_load(&_meta); - SCOPED_LOCK(meta->read()); // '_meta' can be asynchronously updated - - meta->json(builder); - } - - _metaState.json(builder); - - if (forPersistence) { - return; // nothing more to output (persistent configuration does not need links) - } - - TRI_ASSERT(builder.isOpenObject()); - std::vector collections; - - // add CIDs of known collections to list - for (auto& entry: _metaState._collections) { - // skip collections missing from vocbase or UserTransaction constructor will throw an exception - if (vocbase().lookupCollection(entry)) { - collections.emplace_back(std::to_string(entry)); - } - } - - arangodb::velocypack::Builder linksBuilder; - - static std::vector const EMPTY; - - // use default lock timeout - arangodb::transaction::Options options; - options.waitForSync = false; - options.allowImplicitCollections = false; - - try { - arangodb::transaction::Methods trx( - transaction::StandaloneContext::Create(vocbase()), - collections, // readCollections - EMPTY, // writeCollections - EMPTY, // exclusiveCollections - options - ); - - if (trx.begin().fail()) { - return; // nothing more to output - } - - auto* state = trx.state(); - - if (!state) { - return; // nothing more to output - } - - arangodb::velocypack::ObjectBuilder linksBuilderWrapper(&linksBuilder); - - for (auto& collectionName: state->collectionNames()) { - for (auto& index: trx.indexesForCollection(collectionName)) { - if (index && arangodb::Index::IndexType::TRI_IDX_TYPE_IRESEARCH_LINK == index->type()) { - // TODO FIXME find a better way to retrieve an iResearch Link - // cannot use static_cast/reinterpret_cast since Index is not related to IResearchLink - auto* ptr = dynamic_cast(index.get()); - - if (!ptr || *ptr != *this) { - continue; // the index is not a link for the current view - } - - arangodb::velocypack::Builder linkBuilder; - - linkBuilder.openObject(); - - if (!ptr->json(linkBuilder, false)) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "failed to generate json for IResearch link '" << ptr->id() - << "' while generating json for IResearch view '" << id() << "'"; - continue; // skip invalid link definitions - } - - linkBuilder.close(); - linksBuilderWrapper->add(collectionName, linkBuilder.slice()); - } - } - } - - trx.commit(); - } catch (std::exception const& e) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "caught exception while generating json for IResearch view '" << id() << "': " << e.what(); - IR_LOG_EXCEPTION(); - return; // do not add 'links' section - } catch (...) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "caught exception while generating json for IResearch view '" << id() << "'"; - IR_LOG_EXCEPTION(); - return; // do not add 'links' section - } - - builder.add(StaticStrings::LinksField, linksBuilder.slice()); -} - int IResearchView::insert( transaction::Methods& trx, TRI_voc_cid_t cid, @@ -1301,7 +1327,6 @@ int IResearchView::insert( if (_inRecovery) { _storePersisted._writer->remove(FilterFactory::filter(cid, documentId.id())); - store = &_storePersisted; } else if (!trx.state()) { return TRI_ERROR_BAD_PARAMETER; // 'trx' and transaction state required @@ -1507,7 +1532,7 @@ int IResearchView::insert( } if (isNew) { - auto const res = create(static_cast(*view)); + auto const res = create(static_cast(*view)); if (!res.ok()) { LOG_TOPIC(ERR, arangodb::iresearch::TOPIC) @@ -1963,6 +1988,7 @@ void IResearchView::FlushCallbackUnregisterer::operator()(IResearchView* view) c } void IResearchView::verifyKnownCollections() { + // do not need to lock '_metaState' since only caller is a single-threaded recovery callback auto cids = _metaState._collections; { diff --git a/arangod/IResearch/IResearchView.h b/arangod/IResearch/IResearchView.h index f879193338..e0b481139a 100644 --- a/arangod/IResearch/IResearchView.h +++ b/arangod/IResearch/IResearchView.h @@ -132,8 +132,9 @@ class PrimaryKeyIndexReader: public irs::index_reader { /// which may be, but are not explicitly required to be, triggered via /// the IResearchLink or IResearchViewBlock /////////////////////////////////////////////////////////////////////////////// -class IResearchView final: public arangodb::DBServerLogicalView, - public arangodb::FlushTransaction { +class IResearchView final + : public arangodb::LogicalViewStorageEngine, + public arangodb::FlushTransaction { public: /////////////////////////////////////////////////////////////////////////////// @@ -284,20 +285,20 @@ class IResearchView final: public arangodb::DBServerLogicalView, protected: - /////////////////////////////////////////////////////////////////////////////// - /// @brief drop this IResearch View - /////////////////////////////////////////////////////////////////////////////// - arangodb::Result dropImpl() override; - ////////////////////////////////////////////////////////////////////////////// /// @brief fill and return a JSON description of a IResearchView object /// only fields describing the view itself, not 'link' descriptions ////////////////////////////////////////////////////////////////////////////// - void getPropertiesVPack( + virtual arangodb::Result appendVelocyPackDetailed( arangodb::velocypack::Builder& builder, bool forPersistence ) const override; + /////////////////////////////////////////////////////////////////////////////// + /// @brief drop this IResearch View + /////////////////////////////////////////////////////////////////////////////// + arangodb::Result dropImpl() override; + ////////////////////////////////////////////////////////////////////////////// /// @brief called when a view's properties are updated (i.e. delta-modified) ////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/IResearch/IResearchViewCoordinator.cpp b/arangod/IResearch/IResearchViewCoordinator.cpp index f0f0cc6745..c552e1d951 100644 --- a/arangod/IResearch/IResearchViewCoordinator.cpp +++ b/arangod/IResearch/IResearchViewCoordinator.cpp @@ -257,9 +257,8 @@ using namespace basics; namespace iresearch { -arangodb::Result IResearchViewCoordinator::appendVelocyPack( +arangodb::Result IResearchViewCoordinator::appendVelocyPackDetailed( arangodb::velocypack::Builder& builder, - bool detailed, bool forPersistence ) const { if (!builder.isOpenObject()) { @@ -269,25 +268,25 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack( ); } - builder.add( - arangodb::StaticStrings::DataSourceType, - arangodb::velocypack::Value(type().name()) - ); - - if (!detailed) { - return arangodb::Result(); - } - builder.add( StaticStrings::PropertiesField, arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) ); - _meta.json(builder); // regular properites + + auto closePropertiesField = // close StaticStrings::PropertiesField + irs::make_finally([&builder]()->void { builder.close(); }); + + if (!_meta.json(builder)) { + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("failure to generate definition while generating properties jSON for IResearch View in database '") + vocbase().name() + "'" + ); + } arangodb::velocypack::Builder links; - IResearchViewMetaState metaState; - { + // links are not persisted, their definitions are part of the corresponding collections + if (!forPersistence) { ReadMutex mutex(_mutex); SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified @@ -295,21 +294,12 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack( for (auto& entry: _collections) { links.add(entry.second.first, entry.second.second.slice()); - metaState._collections.emplace(entry.first); } links.close(); - } - - metaState.json(builder); // FIXME TODO remove and fix JavaScript tests (no longer required) - - // links are not persisted, their definitions are part of the corresponding collections - if (!forPersistence) { builder.add(StaticStrings::LinksField, links.slice()); } - builder.close(); // close PROPERTIES_FIELD - return arangodb::Result(); } @@ -421,7 +411,7 @@ IResearchViewCoordinator::IResearchViewCoordinator( TRI_vocbase_t& vocbase, velocypack::Slice info, uint64_t planVersion -) : LogicalView(vocbase, info, planVersion) { +) : LogicalViewClusterInfo(vocbase, info, planVersion) { TRI_ASSERT(ServerState::instance()->isCoordinator()); } diff --git a/arangod/IResearch/IResearchViewCoordinator.h b/arangod/IResearch/IResearchViewCoordinator.h index 72bf8c6fe8..cbe76969fc 100644 --- a/arangod/IResearch/IResearchViewCoordinator.h +++ b/arangod/IResearch/IResearchViewCoordinator.h @@ -38,7 +38,7 @@ namespace iresearch { /// @brief an abstraction over the distributed IResearch index implementing the /// LogicalView interface /////////////////////////////////////////////////////////////////////////////// -class IResearchViewCoordinator final : public arangodb::LogicalView { +class IResearchViewCoordinator final : public arangodb::LogicalViewClusterInfo { public: //////////////////////////////////////////////////////////////////////////////// /// @brief acquire locks on the specified 'cid' during read-transactions @@ -91,11 +91,10 @@ class IResearchViewCoordinator final : public arangodb::LogicalView { ) override; protected: - virtual Result appendVelocyPack( + virtual Result appendVelocyPackDetailed( arangodb::velocypack::Builder& builder, - bool detailed, bool forPersistence - ) const override ; + ) const override; private: IResearchViewCoordinator( diff --git a/arangod/IResearch/IResearchViewDBServer.cpp b/arangod/IResearch/IResearchViewDBServer.cpp index d46460d763..319a93cbfd 100644 --- a/arangod/IResearch/IResearchViewDBServer.cpp +++ b/arangod/IResearch/IResearchViewDBServer.cpp @@ -190,16 +190,15 @@ IResearchViewDBServer::IResearchViewDBServer( arangodb::velocypack::Slice const& info, arangodb::DatabasePathFeature const& dbPathFeature, uint64_t planVersion -): LogicalView(vocbase, info, planVersion) { +): LogicalViewClusterInfo(vocbase, info, planVersion) { } IResearchViewDBServer::~IResearchViewDBServer() { _collections.clear(); // ensure view distructors called before mutex is deallocated } -arangodb::Result IResearchViewDBServer::appendVelocyPack( +arangodb::Result IResearchViewDBServer::appendVelocyPackDetailed( arangodb::velocypack::Builder& builder, - bool detailed, bool //forPersistence ) const { if (!builder.isOpenObject()) { @@ -209,26 +208,18 @@ arangodb::Result IResearchViewDBServer::appendVelocyPack( ); } - builder.add( - arangodb::StaticStrings::DataSourceType, - arangodb::velocypack::Value(type().name()) - ); - - if (!detailed) { - return arangodb::Result(); - } - builder.add( StaticStrings::PropertiesField, arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) ); + auto closePropertiesField = // close StaticStrings::PropertiesField + irs::make_finally([&builder]()->void { builder.close(); }); + { SCOPED_LOCK(_meta->read()); // '_meta' can be asynchronously updated - if (!_meta->json(builder, &IResearchViewMeta::DEFAULT())) { - builder.close(); // close StaticStrings::PropertiesField - + if (!_meta->json(builder)) { return arangodb::Result( TRI_ERROR_INTERNAL, std::string("failure to generate definition while generating properties jSON for IResearch View in database '") + vocbase().name() + "'" @@ -236,24 +227,6 @@ arangodb::Result IResearchViewDBServer::appendVelocyPack( } } - { - ReadMutex mutex(_mutex); - SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified - - builder.add( - StaticStrings::CollectionsField, - arangodb::velocypack::Value(arangodb::velocypack::ValueType::Array) - ); - - for (auto& entry: _collections) { - builder.add(arangodb::velocypack::Value(entry.first)); - } - - builder.close(); // close StaticStrings::CollectionsField - } - - builder.close(); // close StaticStrings::PropertiesField - return arangodb::Result(); } @@ -690,7 +663,7 @@ arangodb::Result IResearchViewDBServer::updateProperties( static const std::function propsAcceptor = []( irs::string_ref const& key )->bool { - return key != StaticStrings::CollectionsField && key != StaticStrings::LinksField; // ignored fields + return key != StaticStrings::LinksField; // ignored fields }; arangodb::velocypack::Builder props; diff --git a/arangod/IResearch/IResearchViewDBServer.h b/arangod/IResearch/IResearchViewDBServer.h index 8209b08f92..9d03503db3 100644 --- a/arangod/IResearch/IResearchViewDBServer.h +++ b/arangod/IResearch/IResearchViewDBServer.h @@ -50,7 +50,7 @@ namespace iresearch { class AsyncMeta; class PrimaryKeyIndexReader; -class IResearchViewDBServer final: public arangodb::LogicalView { +class IResearchViewDBServer final: public arangodb::LogicalViewClusterInfo { public: virtual ~IResearchViewDBServer(); @@ -112,9 +112,8 @@ class IResearchViewDBServer final: public arangodb::LogicalView { ) const override; protected: - virtual arangodb::Result appendVelocyPack( + virtual arangodb::Result appendVelocyPackDetailed( arangodb::velocypack::Builder& builder, - bool detailed, bool forPersistence ) const override; diff --git a/arangod/VocBase/LogicalView.cpp b/arangod/VocBase/LogicalView.cpp index ce63129da6..e9a5c3bf8c 100644 --- a/arangod/VocBase/LogicalView.cpp +++ b/arangod/VocBase/LogicalView.cpp @@ -26,6 +26,7 @@ #include "RestServer/ViewTypesFeature.h" #include "Basics/StaticStrings.h" #include "Basics/VelocyPackHelper.h" +#include "Cluster/ClusterInfo.h" #include "Cluster/ServerState.h" #include "StorageEngine/EngineSelectorFeature.h" #include "StorageEngine/StorageEngine.h" @@ -33,16 +34,6 @@ #include "VocBase/ticks.h" #include "VocBase/vocbase.h" -namespace { - -//////////////////////////////////////////////////////////////////////////////// -/// @brief the name of the field in the IResearch View definition denoting the -/// view properties -//////////////////////////////////////////////////////////////////////////////// -const std::string PROPERTIES_FIELD("properties"); - -} - namespace arangodb { // ----------------------------------------------------------------------------- @@ -141,18 +132,70 @@ LogicalView::LogicalView( } // ----------------------------------------------------------------------------- -// --SECTION-- DBServerLogicalView +// --SECTION-- LogicalViewClusterInfo // ----------------------------------------------------------------------------- -DBServerLogicalView::DBServerLogicalView( +LogicalViewClusterInfo::LogicalViewClusterInfo( TRI_vocbase_t& vocbase, VPackSlice const& definition, uint64_t planVersion ): LogicalView(vocbase, definition, planVersion) { - TRI_ASSERT(!ServerState::instance()->isCoordinator()); + TRI_ASSERT( + ServerState::instance()->isCoordinator() + || ServerState::instance()->isDBServer() + ); } -DBServerLogicalView::~DBServerLogicalView() { +arangodb::Result LogicalViewClusterInfo::appendVelocyPack( + arangodb::velocypack::Builder& builder, + bool detailed, + bool forPersistence +) const { + if (!builder.isOpenObject()) { + return arangodb::Result( + TRI_ERROR_BAD_PARAMETER, + std::string("invalid builder provided for LogicalView definition") + ); + } + + builder.add( + StaticStrings::DataSourceType, + arangodb::velocypack::Value(type().name()) + ); + + // implementation Information + if (detailed) { + auto res = appendVelocyPackDetailed(builder, forPersistence); + + if (!res.ok()) { + return res; + } + } + + // ensure that the object is still open + if (!builder.isOpenObject()) { + return arangodb::Result(TRI_ERROR_INTERNAL); + } + + return arangodb::Result(); +} + +// ----------------------------------------------------------------------------- +// --SECTION-- LogicalViewStorageEngine +// ----------------------------------------------------------------------------- + +LogicalViewStorageEngine::LogicalViewStorageEngine( + TRI_vocbase_t& vocbase, + VPackSlice const& definition, + uint64_t planVersion +): LogicalView(vocbase, definition, planVersion) { + TRI_ASSERT( + ServerState::instance()->isDBServer() + || ServerState::instance()->isSingleServer() + ); +} + +LogicalViewStorageEngine::~LogicalViewStorageEngine() { if (deleted()) { StorageEngine* engine = EngineSelectorFeature::ENGINE; TRI_ASSERT(engine); @@ -161,7 +204,7 @@ DBServerLogicalView::~DBServerLogicalView() { } } -arangodb::Result DBServerLogicalView::appendVelocyPack( +arangodb::Result LogicalViewStorageEngine::appendVelocyPack( arangodb::velocypack::Builder& builder, bool detailed, bool forPersistence @@ -169,7 +212,7 @@ arangodb::Result DBServerLogicalView::appendVelocyPack( if (!builder.isOpenObject()) { return arangodb::Result( TRI_ERROR_BAD_PARAMETER, - std::string("invalid builder provided for IResearchViewDBServer definition") + std::string("invalid builder provided for LogicalView definition") ); } @@ -183,7 +226,7 @@ arangodb::Result DBServerLogicalView::appendVelocyPack( // includeSystem if we are persisting the properties if (forPersistence) { // storage engine related properties - StorageEngine* engine = EngineSelectorFeature::ENGINE; + auto* engine = EngineSelectorFeature::ENGINE; if (!engine) { return TRI_ERROR_INTERNAL; @@ -192,26 +235,25 @@ arangodb::Result DBServerLogicalView::appendVelocyPack( engine->getViewProperties(vocbase(), *this, builder); } + // implementation Information if (detailed) { - // implementation Information - builder.add( - PROPERTIES_FIELD, - arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) - ); - getPropertiesVPack(builder, forPersistence); - builder.close(); + auto res = appendVelocyPackDetailed(builder, forPersistence); + + if (!res.ok()) { + return res; + } } // ensure that the object is still open if (!builder.isOpenObject()) { - return TRI_ERROR_INTERNAL; + return arangodb::Result(TRI_ERROR_INTERNAL); } return arangodb::Result(); } -/*static*/ arangodb::Result DBServerLogicalView::create( - DBServerLogicalView const& view +/*static*/ arangodb::Result LogicalViewStorageEngine::create( + LogicalViewStorageEngine const& view ) { TRI_ASSERT(!ServerState::instance()->isCoordinator()); StorageEngine* engine = EngineSelectorFeature::ENGINE; @@ -262,7 +304,7 @@ arangodb::Result DBServerLogicalView::appendVelocyPack( } } -arangodb::Result DBServerLogicalView::drop() { +arangodb::Result LogicalViewStorageEngine::drop() { TRI_ASSERT(!ServerState::instance()->isCoordinator()); StorageEngine* engine = EngineSelectorFeature::ENGINE; TRI_ASSERT(engine); @@ -276,7 +318,7 @@ arangodb::Result DBServerLogicalView::drop() { return res; } -Result DBServerLogicalView::rename(std::string&& newName, bool doSync) { +Result LogicalViewStorageEngine::rename(std::string&& newName, bool doSync) { TRI_ASSERT(!ServerState::instance()->isCoordinator()); StorageEngine* engine = EngineSelectorFeature::ENGINE; TRI_ASSERT(engine); @@ -304,7 +346,7 @@ Result DBServerLogicalView::rename(std::string&& newName, bool doSync) { return engine->renameView(vocbase(), *this, oldName); } -arangodb::Result DBServerLogicalView::updateProperties( +arangodb::Result LogicalViewStorageEngine::updateProperties( VPackSlice const& slice, bool partialUpdate, bool doSync diff --git a/arangod/VocBase/LogicalView.h b/arangod/VocBase/LogicalView.h index f2b6be45e8..7c1de176a8 100644 --- a/arangod/VocBase/LogicalView.h +++ b/arangod/VocBase/LogicalView.h @@ -184,11 +184,37 @@ class LogicalView : public LogicalDataSource { }; // LogicalView //////////////////////////////////////////////////////////////////////////////// -/// @class DBServerLogicalView +/// @brief a LogicalView base class for ClusterInfo view implementations //////////////////////////////////////////////////////////////////////////////// -class DBServerLogicalView : public LogicalView { +class LogicalViewClusterInfo: public LogicalView { + protected: + LogicalViewClusterInfo( + TRI_vocbase_t& vocbase, + velocypack::Slice const& definition, + uint64_t planVersion + ); + + virtual Result appendVelocyPack( + arangodb::velocypack::Builder& builder, + bool detailed, + bool forPersistence + ) const override final; + + ////////////////////////////////////////////////////////////////////////////// + /// @brief fill and return a jSON description of a View object implementation + ////////////////////////////////////////////////////////////////////////////// + virtual arangodb::Result appendVelocyPackDetailed( + velocypack::Builder& builder, + bool forPersistence + ) const = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief a LogicalView base class for StorageEngine view implementations +//////////////////////////////////////////////////////////////////////////////// +class LogicalViewStorageEngine: public LogicalView { public: - ~DBServerLogicalView() override; + ~LogicalViewStorageEngine() override; arangodb::Result drop() override final; @@ -204,7 +230,7 @@ class DBServerLogicalView : public LogicalView { ) override final; protected: - DBServerLogicalView( + LogicalViewStorageEngine( TRI_vocbase_t& vocbase, velocypack::Slice const& definition, uint64_t planVersion @@ -216,25 +242,25 @@ class DBServerLogicalView : public LogicalView { bool forPersistence ) const override final; + ////////////////////////////////////////////////////////////////////////////// + /// @brief fill and return a jSON description of a View object implementation + ////////////////////////////////////////////////////////////////////////////// + virtual arangodb::Result appendVelocyPackDetailed( + velocypack::Builder& builder, + bool forPersistence + ) const = 0; + ////////////////////////////////////////////////////////////////////////////// /// @brief called by view factories during view creation to persist the view /// to the storage engine ////////////////////////////////////////////////////////////////////////////// - static arangodb::Result create(DBServerLogicalView const& view); + static arangodb::Result create(LogicalViewStorageEngine const& view); ////////////////////////////////////////////////////////////////////////////// /// @brief drop implementation-specific parts of an existing view ////////////////////////////////////////////////////////////////////////////// virtual arangodb::Result dropImpl() = 0; - ////////////////////////////////////////////////////////////////////////////// - /// @brief fill and return a jSON description of a View object implementation - ////////////////////////////////////////////////////////////////////////////// - virtual void getPropertiesVPack( - velocypack::Builder& builder, - bool forPersistence - ) const = 0; - /////////////////////////////////////////////////////////////////////////////// /// @brief called when a view's properties are updated (i.e. delta-modified) /////////////////////////////////////////////////////////////////////////////// @@ -242,8 +268,8 @@ class DBServerLogicalView : public LogicalView { velocypack::Slice const& slice, bool partialUpdate ) = 0; -}; // LogicalView +}; } // namespace arangodb -#endif +#endif \ No newline at end of file diff --git a/js/common/tests/aql/aql-view-arangosearch-ddl-cluster.js b/js/common/tests/aql/aql-view-arangosearch-ddl-cluster.js index 95f2c3a9b9..39bf940460 100644 --- a/js/common/tests/aql/aql-view-arangosearch-ddl-cluster.js +++ b/js/common/tests/aql/aql-view-arangosearch-ddl-cluster.js @@ -68,8 +68,8 @@ function IResearchFeatureDDLTestSuite () { var view = db._createView("TestView", "arangosearch", {}); view.properties(addLink, true); // partial update let properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); var indexes = db.TestCollection0.getIndexes(); assertEqual(2, indexes.length); var link = indexes[1]; @@ -94,8 +94,8 @@ function IResearchFeatureDDLTestSuite () { for (let i = 0; i < 100; ++i) { view.properties(addLink, true); // partial update let properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); var indexes = db.TestCollection0.getIndexes(); assertEqual(2, indexes.length); var link = indexes[1]; @@ -104,8 +104,8 @@ function IResearchFeatureDDLTestSuite () { assertEqual("arangosearch", link.type); view.properties(removeLink, false); properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(0, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(0, Object.keys(properties.links).length); assertEqual(1, db.TestCollection0.getIndexes().length); } }, @@ -119,12 +119,12 @@ function IResearchFeatureDDLTestSuite () { var addLink = { links: { "TestCollection0": {} } }; view.properties(addLink, true); // partial update let properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); db._drop("TestCollection0"); properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(0, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(0, Object.keys(properties.links).length); }, testViewDDL: function() { @@ -139,26 +139,26 @@ function IResearchFeatureDDLTestSuite () { var view = db._createView("TestView", "arangosearch", {}); var properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(0, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(0, Object.keys(properties.links).length); var meta = { links: { "TestCollection0": {} } }; view.properties(meta, true); // partial update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); meta = { links: { "TestCollection1": {} } }; view.properties(meta, true); // partial update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(2, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(2, Object.keys(properties.links).length); meta = { links: { "TestCollection2": {} } }; view.properties(meta, false); // full update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); // commit diff --git a/js/common/tests/aql/aql-view-arangosearch-ddl-noncluster.js b/js/common/tests/aql/aql-view-arangosearch-ddl-noncluster.js index f49ffa4cb1..db50b53b78 100644 --- a/js/common/tests/aql/aql-view-arangosearch-ddl-noncluster.js +++ b/js/common/tests/aql/aql-view-arangosearch-ddl-noncluster.js @@ -59,26 +59,26 @@ function iResearchFeatureAqlTestSuite () { var view = db._createView("TestView", "arangosearch", {}); var properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(0, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(0, Object.keys(properties.links).length); var meta = { links: { "TestCollection0": {} } }; view.properties(meta, true); // partial update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); meta = { links: { "TestCollection1": {} } }; view.properties(meta, true); // partial update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(2, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(2, Object.keys(properties.links).length); meta = { links: { "TestCollection2": {} } }; view.properties(meta, false); // full update properties = view.properties(); - assertTrue(Array === properties.collections.constructor); - assertEqual(1, properties.collections.length); + assertTrue(Object === properties.links.constructor); + assertEqual(1, Object.keys(properties.links).length); // commit diff --git a/js/server/tests/dump/dump-mmfiles.js b/js/server/tests/dump/dump-mmfiles.js index cfdd3571e5..383e942209 100644 --- a/js/server/tests/dump/dump-mmfiles.js +++ b/js/server/tests/dump/dump-mmfiles.js @@ -453,7 +453,7 @@ function dumpTestSuite () { let view = db._view("UnitTestsDumpView"); assertTrue(view !== null); let props = view.properties(); - assertEqual(props.collections.length, 1); + assertEqual(Object.keys(props.links).length, 1); assertTrue(props.hasOwnProperty("links")); assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection")); } diff --git a/js/server/tests/dump/dump-rocksdb.js b/js/server/tests/dump/dump-rocksdb.js index 55cd3a4103..ed5f22c125 100644 --- a/js/server/tests/dump/dump-rocksdb.js +++ b/js/server/tests/dump/dump-rocksdb.js @@ -405,7 +405,7 @@ function dumpTestSuite () { let view = db._view("UnitTestsDumpView"); assertTrue(view !== null); let props = view.properties(); - assertEqual(props.collections.length, 1); + assertEqual(Object.keys(props.links).length, 1); assertTrue(props.hasOwnProperty("links")); assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection")); } diff --git a/tests/IResearch/IResearchView-test.cpp b/tests/IResearch/IResearchView-test.cpp index 55279302eb..eb8496fb70 100644 --- a/tests/IResearch/IResearchView-test.cpp +++ b/tests/IResearch/IResearchView-test.cpp @@ -304,7 +304,6 @@ SECTION("test_defaults") { CHECK((false == !view)); arangodb::iresearch::IResearchViewMeta expectedMeta; - arangodb::iresearch::IResearchViewMetaState expectedMetaState; arangodb::velocypack::Builder builder; builder.openObject(); @@ -313,7 +312,6 @@ SECTION("test_defaults") { auto slice = builder.slice(); arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; std::string error; CHECK(4 == slice.length()); @@ -322,9 +320,8 @@ SECTION("test_defaults") { CHECK((false == slice.hasKey("deleted"))); slice = slice.get("properties"); CHECK(slice.isObject()); - CHECK((4U == slice.length())); + CHECK((3U == slice.length())); CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); auto tmpSlice = slice.get("links"); CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); @@ -2856,30 +2853,56 @@ SECTION("test_update_overwrite") { expectedMeta._locale = irs::locale_utils::locale("en", true); CHECK((view->updateProperties(updateJson->slice(), false, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + std::string error; - CHECK(slice.isObject()); - CHECK(4 == slice.length()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(4 == slice.length()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // subsequent update (overwrite) @@ -2893,29 +2916,56 @@ SECTION("test_update_overwrite") { expectedMeta._locale = irs::locale_utils::locale("ru", true); CHECK((view->updateProperties(updateJson->slice(), false, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } } @@ -2945,44 +2995,72 @@ SECTION("test_update_overwrite") { expectedLinkMeta["testCollection0"]; // use defaults CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { - arangodb::iresearch::IResearchLinkMeta linkMeta; - auto key = itr.key(); - auto value = itr.value(); - CHECK((true == key.isString())); + for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { + arangodb::iresearch::IResearchLinkMeta linkMeta; + auto key = itr.key(); + auto value = itr.value(); + CHECK((true == key.isString())); - auto expectedItr = expectedLinkMeta.find(key.copyString()); - CHECK(( - true == value.isObject() - && expectedItr != expectedLinkMeta.end() - && linkMeta.init(value, error) - && expectedItr->second == linkMeta - )); - expectedLinkMeta.erase(expectedItr); + auto expectedItr = expectedLinkMeta.find(key.copyString()); + CHECK(( + true == value.isObject() + && expectedItr != expectedLinkMeta.end() + && linkMeta.init(value, error) + && expectedItr->second == linkMeta + )); + expectedLinkMeta.erase(expectedItr); + } + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); } CHECK((true == expectedLinkMeta.empty())); @@ -3001,44 +3079,72 @@ SECTION("test_update_overwrite") { expectedLinkMeta["testCollection1"]; // use defaults CHECK((view->updateProperties(updateJson->slice(), false, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { - arangodb::iresearch::IResearchLinkMeta linkMeta; - auto key = itr.key(); - auto value = itr.value(); - CHECK((true == key.isString())); + for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { + arangodb::iresearch::IResearchLinkMeta linkMeta; + auto key = itr.key(); + auto value = itr.value(); + CHECK((true == key.isString())); - auto expectedItr = expectedLinkMeta.find(key.copyString()); - CHECK(( - true == value.isObject() - && expectedItr != expectedLinkMeta.end() - && linkMeta.init(value, error) - && expectedItr->second == linkMeta - )); - expectedLinkMeta.erase(expectedItr); + auto expectedItr = expectedLinkMeta.find(key.copyString()); + CHECK(( + true == value.isObject() + && expectedItr != expectedLinkMeta.end() + && linkMeta.init(value, error) + && expectedItr->second == linkMeta + )); + expectedLinkMeta.erase(expectedItr); + } + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); } CHECK((true == expectedLinkMeta.empty())); @@ -3064,26 +3170,51 @@ SECTION("test_update_overwrite") { ); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("collections"); - CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); - tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - tmpSlice = tmpSlice.get("testCollection"); - CHECK((true == tmpSlice.isObject())); - tmpSlice = tmpSlice.get("includeAllFields"); - CHECK((true == tmpSlice.isBoolean() && true == tmpSlice.getBoolean())); + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + tmpSlice = tmpSlice.get("testCollection"); + CHECK((true == tmpSlice.isObject())); + tmpSlice = tmpSlice.get("includeAllFields"); + CHECK((true == tmpSlice.isBoolean() && true == tmpSlice.getBoolean())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } // update link @@ -3093,23 +3224,47 @@ SECTION("test_update_overwrite") { ); CHECK((view->updateProperties(updateJson->slice(), false, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - tmpSlice = tmpSlice.get("testCollection"); - CHECK((true == tmpSlice.isObject())); - tmpSlice = tmpSlice.get("includeAllFields"); - CHECK((true == tmpSlice.isBoolean() && false == tmpSlice.getBoolean())); + auto slice = builder.slice(); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + tmpSlice = tmpSlice.get("testCollection"); + CHECK((true == tmpSlice.isObject())); + tmpSlice = tmpSlice.get("includeAllFields"); + CHECK((true == tmpSlice.isBoolean() && false == tmpSlice.getBoolean())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } } } @@ -3140,29 +3295,56 @@ SECTION("test_update_partial") { expectedMeta._locale = irs::locale_utils::locale("en", true); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // test rollback on meta modification failure (as an example invalid value for 'locale') @@ -3180,29 +3362,56 @@ SECTION("test_update_partial") { CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // add a new link (in recovery) @@ -3226,24 +3435,49 @@ SECTION("test_update_partial") { CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); CHECK((false == persisted)); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK(( - true == slice.hasKey("links") - && slice.get("links").isObject() - && 1 == slice.get("links").length() - )); + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK(( + true == slice.hasKey("links") + && slice.get("links").isObject() + && 1 == slice.get("links").length() + )); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } // add a new link @@ -3269,44 +3503,72 @@ SECTION("test_update_partial") { CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); CHECK((true == persisted)); // link addition does modify and persist view meta - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { - arangodb::iresearch::IResearchLinkMeta linkMeta; - auto key = itr.key(); - auto value = itr.value(); - CHECK((true == key.isString())); + for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { + arangodb::iresearch::IResearchLinkMeta linkMeta; + auto key = itr.key(); + auto value = itr.value(); + CHECK((true == key.isString())); - auto expectedItr = expectedLinkMeta.find(key.copyString()); - CHECK(( - true == value.isObject() - && expectedItr != expectedLinkMeta.end() - && linkMeta.init(value, error) - && expectedItr->second == linkMeta - )); - expectedLinkMeta.erase(expectedItr); + auto expectedItr = expectedLinkMeta.find(key.copyString()); + CHECK(( + true == value.isObject() + && expectedItr != expectedLinkMeta.end() + && linkMeta.init(value, error) + && expectedItr->second == linkMeta + )); + expectedLinkMeta.erase(expectedItr); + } + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); } CHECK((true == expectedLinkMeta.empty())); @@ -3352,43 +3614,70 @@ SECTION("test_update_partial") { CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); CHECK((true == persisted)); // link addition does modify and persist view meta - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { - arangodb::iresearch::IResearchLinkMeta linkMeta; - auto key = itr.key(); - auto value = itr.value(); - CHECK((true == key.isString())); + for (arangodb::velocypack::ObjectIterator itr(tmpSlice); itr.valid(); ++itr) { + arangodb::iresearch::IResearchLinkMeta linkMeta; + auto key = itr.key(); + auto value = itr.value(); + CHECK((true == key.isString())); - auto expectedItr = expectedLinkMeta.find(key.copyString()); - CHECK(( - true == value.isObject() - && expectedItr != expectedLinkMeta.end() - && linkMeta.init(value, error) - && expectedItr->second == linkMeta - )); - expectedLinkMeta.erase(expectedItr); + auto expectedItr = expectedLinkMeta.find(key.copyString()); + CHECK(( + true == value.isObject() + && expectedItr != expectedLinkMeta.end() + && linkMeta.init(value, error) + && expectedItr->second == linkMeta + )); + expectedLinkMeta.erase(expectedItr); + } + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); } CHECK((true == expectedLinkMeta.empty())); @@ -3410,28 +3699,54 @@ SECTION("test_update_partial") { CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // remove link (in recovery) @@ -3528,29 +3843,56 @@ SECTION("test_update_partial") { CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } { @@ -3562,29 +3904,56 @@ SECTION("test_update_partial") { expectedMetaState._collections.clear(); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } } @@ -3603,29 +3972,56 @@ SECTION("test_update_partial") { CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // remove non-existant link @@ -3646,29 +4042,56 @@ SECTION("test_update_partial") { CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; - std::string error; + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - CHECK(slice.isObject()); - CHECK((4U == slice.length())); - CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + } - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 0 == tmpSlice.length())); + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + arangodb::iresearch::IResearchViewMeta meta; + arangodb::iresearch::IResearchViewMetaState metaState; + std::string error; + + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + CHECK((meta.init(slice, error) && expectedMeta == meta)); + CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); + CHECK((false == slice.hasKey("links"))); + } } // remove + add link to same collection (reindex) @@ -3687,20 +4110,47 @@ SECTION("test_update_partial") { ); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } // add + remove @@ -3716,20 +4166,48 @@ SECTION("test_update_partial") { CHECK((!initial.empty())); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + // not for persistence + { + arangodb::velocypack::Builder builder; - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } std::unordered_set actual; @@ -3757,26 +4235,51 @@ SECTION("test_update_partial") { ); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("collections"); - CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); - tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - tmpSlice = tmpSlice.get("testCollection"); - CHECK((true == tmpSlice.isObject())); - tmpSlice = tmpSlice.get("includeAllFields"); - CHECK((true == tmpSlice.isBoolean() && true == tmpSlice.getBoolean())); + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + tmpSlice = tmpSlice.get("testCollection"); + CHECK((true == tmpSlice.isObject())); + tmpSlice = tmpSlice.get("includeAllFields"); + CHECK((true == tmpSlice.isBoolean() && true == tmpSlice.getBoolean())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } // update link @@ -3786,24 +4289,51 @@ SECTION("test_update_partial") { ); CHECK((view->updateProperties(updateJson->slice(), true, false).ok())); - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); - auto slice = builder.slice(); - CHECK(slice.isObject()); - CHECK(slice.get("name").copyString() == "testView"); - CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); - CHECK(slice.get("deleted").isNone()); // no system properties - slice = slice.get("properties"); - auto tmpSlice = slice.get("links"); - CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); - tmpSlice = tmpSlice.get("testCollection"); - CHECK((true == tmpSlice.isObject())); - tmpSlice = tmpSlice.get("includeAllFields"); - CHECK((true == tmpSlice.isBoolean() && false == tmpSlice.getBoolean())); + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK(slice.get("deleted").isNone()); // no system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("links"); + CHECK((true == tmpSlice.isObject() && 1 == tmpSlice.length())); + tmpSlice = tmpSlice.get("testCollection"); + CHECK((true == tmpSlice.isObject())); + tmpSlice = tmpSlice.get("includeAllFields"); + CHECK((true == tmpSlice.isBoolean() && false == tmpSlice.getBoolean())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK(slice.isObject()); + CHECK((8U == slice.length())); + CHECK(slice.get("name").copyString() == "testView"); + CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); // has system properties + slice = slice.get("properties"); + CHECK(slice.isObject()); + CHECK((3U == slice.length())); + auto tmpSlice = slice.get("collections"); + CHECK((true == tmpSlice.isArray() && 1 == tmpSlice.length())); + CHECK((false == slice.hasKey("links"))); + } } } } diff --git a/tests/IResearch/IResearchViewCoordinator-test.cpp b/tests/IResearch/IResearchViewCoordinator-test.cpp index 9ebc51e0dd..6528299bdc 100644 --- a/tests/IResearch/IResearchViewCoordinator-test.cpp +++ b/tests/IResearch/IResearchViewCoordinator-test.cpp @@ -327,14 +327,12 @@ SECTION("test_defaults") { // +system, +properties { arangodb::iresearch::IResearchViewMeta expectedMeta; - arangodb::iresearch::IResearchViewMetaState expectedMetaState; arangodb::velocypack::Builder builder; builder.openObject(); view->toVelocyPack(builder, true, true); builder.close(); auto slice = builder.slice(); arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; std::string error; CHECK(8 == slice.length()); @@ -347,23 +345,20 @@ SECTION("test_defaults") { CHECK(false == slice.get("deleted").getBool()); slice = slice.get("properties"); CHECK(slice.isObject()); - CHECK((3 == slice.length())); + CHECK((2U == slice.length())); CHECK((!slice.hasKey("links"))); // for persistence so no links CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); } // -system, +properties { arangodb::iresearch::IResearchViewMeta expectedMeta; - arangodb::iresearch::IResearchViewMetaState expectedMetaState; arangodb::velocypack::Builder builder; builder.openObject(); view->toVelocyPack(builder, true, false); builder.close(); auto slice = builder.slice(); arangodb::iresearch::IResearchViewMeta meta; - arangodb::iresearch::IResearchViewMetaState metaState; std::string error; CHECK(4 == slice.length()); @@ -374,10 +369,9 @@ SECTION("test_defaults") { CHECK(!slice.hasKey("deleted")); slice = slice.get("properties"); CHECK(slice.isObject()); - CHECK((4 == slice.length())); + CHECK((3U == slice.length())); CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); CHECK((meta.init(slice, error) && expectedMeta == meta)); - CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState)); } // -system, -properties diff --git a/tests/IResearch/IResearchViewDBServer-test.cpp b/tests/IResearch/IResearchViewDBServer-test.cpp index ce68ad0aed..c7c27958d4 100644 --- a/tests/IResearch/IResearchViewDBServer-test.cpp +++ b/tests/IResearch/IResearchViewDBServer-test.cpp @@ -828,8 +828,7 @@ SECTION("test_toVelocyPack") { CHECK((slice.hasKey("properties"))); auto props = slice.get("properties"); CHECK((props.isObject())); - CHECK((1 == props.length())); - CHECK((props.hasKey("collections") && props.get("collections").isArray() && 0 == props.get("collections").length())); + CHECK((2U == props.length())); } // includeSystem @@ -987,12 +986,17 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 42 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((!slice.hasKey("links"))); } { @@ -1006,8 +1010,12 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 1 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); @@ -1020,18 +1028,47 @@ SECTION("test_updateProperties") { static auto visitor = [](TRI_voc_cid_t)->bool { return false; }; CHECK((true == view->visitCollections(visitor))); // no collections in view - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); - CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); - auto tmpSlice = slice.get("commit"); - CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); - CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); - CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + CHECK((8U == slice.length())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((false == slice.hasKey("links"))); + } } // update empty (full) @@ -1056,12 +1093,17 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 42 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((!slice.hasKey("links"))); } { @@ -1075,8 +1117,12 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 1 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); @@ -1089,18 +1135,47 @@ SECTION("test_updateProperties") { static auto visitor = [](TRI_voc_cid_t)->bool { return false; }; CHECK((true == view->visitCollections(visitor))); // no collections in view - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); - CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); - auto tmpSlice = slice.get("commit"); - CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); - CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); - CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + CHECK((8U == slice.length())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((false == slice.hasKey("links"))); + } } // update non-empty (partial) @@ -1130,12 +1205,17 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 1 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 42 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((!slice.hasKey("links"))); } { @@ -1149,8 +1229,12 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 2 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); @@ -1160,18 +1244,47 @@ SECTION("test_updateProperties") { CHECK((true == view->visitCollections(visitor))); // no collections in view - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); - CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); - auto tmpSlice = slice.get("commit"); - CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); - CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); - CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + CHECK((8U == slice.length())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((false == slice.hasKey("links"))); + } } // update non-empty (full) @@ -1204,12 +1317,17 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 1 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 42 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((!slice.hasKey("links"))); } { @@ -1223,8 +1341,12 @@ SECTION("test_updateProperties") { builder.openObject(); wiew->toVelocyPack(builder, true, false); builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 1 == slice.get("collections").length())); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((2U == slice.length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); auto tmpSlice = slice.get("commit"); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); @@ -1234,18 +1356,47 @@ SECTION("test_updateProperties") { CHECK((true == view->visitCollections(visitor))); // no collections in view - arangodb::velocypack::Builder builder; + // not for persistence + { + arangodb::velocypack::Builder builder; - builder.openObject(); - view->toVelocyPack(builder, true, false); - builder.close(); - auto slice = builder.slice().get("properties"); - CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); - CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); - auto tmpSlice = slice.get("commit"); - CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); - CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); - CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + builder.openObject(); + view->toVelocyPack(builder, true, false); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); + } + + // for persistence + { + arangodb::velocypack::Builder builder; + + builder.openObject(); + view->toVelocyPack(builder, true, true); + builder.close(); + + auto slice = builder.slice(); + CHECK((slice.isObject())); + CHECK((8U == slice.length())); + slice = slice.get("properties"); + CHECK((slice.isObject())); + CHECK((3U == slice.length())); + CHECK((slice.hasKey("collections") && slice.get("collections").isArray() && 0 == slice.get("collections").length())); + CHECK((slice.hasKey("commit") && slice.get("commit").isObject())); + auto tmpSlice = slice.get("commit"); + CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber())); + CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber() && 52 == tmpSlice.get("commitIntervalMsec").getNumber())); + CHECK((false == slice.hasKey("links"))); + } } } diff --git a/tests/Utils/CollectionNameResolver-test.cpp b/tests/Utils/CollectionNameResolver-test.cpp index e729f4c3cb..a96047886a 100644 --- a/tests/Utils/CollectionNameResolver-test.cpp +++ b/tests/Utils/CollectionNameResolver-test.cpp @@ -42,20 +42,23 @@ std::shared_ptr makeTestView( uint64_t planVersion, arangodb::LogicalView::PreCommitCallback const& preCommit ) { - struct Impl: public arangodb::DBServerLogicalView { + struct Impl: public arangodb::LogicalViewStorageEngine { Impl( TRI_vocbase_t& vocbase, arangodb::velocypack::Slice const& info, uint64_t planVersion - ): arangodb::DBServerLogicalView(vocbase, info, planVersion) { + ): arangodb::LogicalViewStorageEngine(vocbase, info, planVersion) { } - arangodb::Result create() { return DBServerLogicalView::create(*this); } - virtual arangodb::Result dropImpl() override { return arangodb::Result(); } - virtual void getPropertiesVPack( + virtual arangodb::Result appendVelocyPackDetailed( arangodb::velocypack::Builder&, bool ) const override { + return arangodb::Result(); } + arangodb::Result create() { + return LogicalViewStorageEngine::create(*this); + } + virtual arangodb::Result dropImpl() override { return arangodb::Result(); } virtual void open() override {} virtual arangodb::Result updateProperties( arangodb::velocypack::Slice const&, diff --git a/tests/VocBase/vocbase-test.cpp b/tests/VocBase/vocbase-test.cpp index 2163128924..8bc4b58f2a 100644 --- a/tests/VocBase/vocbase-test.cpp +++ b/tests/VocBase/vocbase-test.cpp @@ -43,20 +43,23 @@ std::shared_ptr makeTestView( uint64_t planVersion, arangodb::LogicalView::PreCommitCallback const& preCommit ) { - struct Impl: public arangodb::DBServerLogicalView{ + struct Impl: public arangodb::LogicalViewStorageEngine { Impl( TRI_vocbase_t& vocbase, arangodb::velocypack::Slice const& info, uint64_t planVersion - ): DBServerLogicalView(vocbase, info, planVersion) { + ): LogicalViewStorageEngine(vocbase, info, planVersion) { } - arangodb::Result create() { return DBServerLogicalView::create(*this); } - virtual arangodb::Result dropImpl() override { return arangodb::Result(); } - virtual void getPropertiesVPack( + virtual arangodb::Result appendVelocyPackDetailed( arangodb::velocypack::Builder&, bool ) const override { + return arangodb::Result(); } + arangodb::Result create() { + return LogicalViewStorageEngine::create(*this); + } + virtual arangodb::Result dropImpl() override { return arangodb::Result(); } virtual void open() override {} virtual arangodb::Result updateProperties( arangodb::velocypack::Slice const&,