1
0
Fork 0

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
This commit is contained in:
Vasiliy 2018-07-17 15:21:07 +03:00 committed by Andrey Abramov
parent 24dccfee90
commit a401934d62
20 changed files with 1479 additions and 769 deletions

View File

@ -186,14 +186,6 @@ During view modification the following directives apply:
impact performance and waste disk space for each commit call without any impact performance and waste disk space for each commit call without any
added benefits 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`) * consolidate: (optional; default: `none`)
a per-policy mapping of thresholds in the range `[0.0, 1.0]` to determine data 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 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`) * locale: (optional; default: `C`)
the default locale used for ordering processed attribute names 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 ### Link properties
* analyzers: (optional; default: `[ 'identity' ]`) * analyzers: (optional; default: `[ 'identity' ]`)

View File

@ -51,7 +51,6 @@ arangodb::LogTopic& logTopic() {
// --SECTION-- StaticStrings // --SECTION-- StaticStrings
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
std::string const StaticStrings::CollectionsField("collections");
std::string const StaticStrings::LinksField("links"); std::string const StaticStrings::LinksField("links");
std::string const StaticStrings::PropertiesField("properties"); std::string const StaticStrings::PropertiesField("properties");
std::string const StaticStrings::ViewIdField("view"); std::string const StaticStrings::ViewIdField("view");

View File

@ -37,12 +37,6 @@ static auto& DATA_SOURCE_TYPE = dataSourceType();
static auto& TOPIC = logTopic(); static auto& TOPIC = logTopic();
struct StaticStrings { 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 /// @brief the name of the field in the IResearch View definition denoting the
/// corresponding link definitions /// corresponding link definitions

View File

@ -664,7 +664,7 @@ IResearchView::IResearchView(
arangodb::velocypack::Slice const& info, arangodb::velocypack::Slice const& info,
arangodb::DatabasePathFeature const& dbPathFeature, arangodb::DatabasePathFeature const& dbPathFeature,
uint64_t planVersion uint64_t planVersion
): DBServerLogicalView(vocbase, info, planVersion), ): LogicalViewStorageEngine(vocbase, info, planVersion),
FlushTransaction(toString(*this)), FlushTransaction(toString(*this)),
_asyncFeature(nullptr), _asyncFeature(nullptr),
_asyncSelf(irs::memory::make_unique<AsyncSelf>(this)), _asyncSelf(irs::memory::make_unique<AsyncSelf>(this)),
@ -935,6 +935,136 @@ IResearchView::MemoryStore& IResearchView::activeMemoryStore() const {
return _memoryNode->_store; 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<std::string> 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<std::string> 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<IResearchLink*>(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) { bool IResearchView::apply(arangodb::transaction::Methods& trx) {
// called from IResearchView when this view is added to a transaction // called from IResearchView when this view is added to a transaction
return trx.addStatusChangeCallback(&_trxReadCallback); // add shapshot return trx.addStatusChangeCallback(&_trxReadCallback); // add shapshot
@ -1186,110 +1316,6 @@ arangodb::Result IResearchView::commit() {
return {TRI_ERROR_INTERNAL}; 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<std::string> 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<std::string> 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<IResearchLink*>(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( int IResearchView::insert(
transaction::Methods& trx, transaction::Methods& trx,
TRI_voc_cid_t cid, TRI_voc_cid_t cid,
@ -1301,7 +1327,6 @@ int IResearchView::insert(
if (_inRecovery) { if (_inRecovery) {
_storePersisted._writer->remove(FilterFactory::filter(cid, documentId.id())); _storePersisted._writer->remove(FilterFactory::filter(cid, documentId.id()));
store = &_storePersisted; store = &_storePersisted;
} else if (!trx.state()) { } else if (!trx.state()) {
return TRI_ERROR_BAD_PARAMETER; // 'trx' and transaction state required return TRI_ERROR_BAD_PARAMETER; // 'trx' and transaction state required
@ -1507,7 +1532,7 @@ int IResearchView::insert(
} }
if (isNew) { if (isNew) {
auto const res = create(static_cast<arangodb::DBServerLogicalView&>(*view)); auto const res = create(static_cast<arangodb::LogicalViewStorageEngine&>(*view));
if (!res.ok()) { if (!res.ok()) {
LOG_TOPIC(ERR, arangodb::iresearch::TOPIC) LOG_TOPIC(ERR, arangodb::iresearch::TOPIC)
@ -1963,6 +1988,7 @@ void IResearchView::FlushCallbackUnregisterer::operator()(IResearchView* view) c
} }
void IResearchView::verifyKnownCollections() { void IResearchView::verifyKnownCollections() {
// do not need to lock '_metaState' since only caller is a single-threaded recovery callback
auto cids = _metaState._collections; auto cids = _metaState._collections;
{ {

View File

@ -132,8 +132,9 @@ class PrimaryKeyIndexReader: public irs::index_reader {
/// which may be, but are not explicitly required to be, triggered via /// which may be, but are not explicitly required to be, triggered via
/// the IResearchLink or IResearchViewBlock /// the IResearchLink or IResearchViewBlock
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class IResearchView final: public arangodb::DBServerLogicalView, class IResearchView final
public arangodb::FlushTransaction { : public arangodb::LogicalViewStorageEngine,
public arangodb::FlushTransaction {
public: public:
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -284,20 +285,20 @@ class IResearchView final: public arangodb::DBServerLogicalView,
protected: protected:
///////////////////////////////////////////////////////////////////////////////
/// @brief drop this IResearch View
///////////////////////////////////////////////////////////////////////////////
arangodb::Result dropImpl() override;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief fill and return a JSON description of a IResearchView object /// @brief fill and return a JSON description of a IResearchView object
/// only fields describing the view itself, not 'link' descriptions /// only fields describing the view itself, not 'link' descriptions
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void getPropertiesVPack( virtual arangodb::Result appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool forPersistence bool forPersistence
) const override; ) const override;
///////////////////////////////////////////////////////////////////////////////
/// @brief drop this IResearch View
///////////////////////////////////////////////////////////////////////////////
arangodb::Result dropImpl() override;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief called when a view's properties are updated (i.e. delta-modified) /// @brief called when a view's properties are updated (i.e. delta-modified)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -257,9 +257,8 @@ using namespace basics;
namespace iresearch { namespace iresearch {
arangodb::Result IResearchViewCoordinator::appendVelocyPack( arangodb::Result IResearchViewCoordinator::appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool detailed,
bool forPersistence bool forPersistence
) const { ) const {
if (!builder.isOpenObject()) { 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( builder.add(
StaticStrings::PropertiesField, StaticStrings::PropertiesField,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) 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; arangodb::velocypack::Builder links;
IResearchViewMetaState metaState;
{ // links are not persisted, their definitions are part of the corresponding collections
if (!forPersistence) {
ReadMutex mutex(_mutex); ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified
@ -295,21 +294,12 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack(
for (auto& entry: _collections) { for (auto& entry: _collections) {
links.add(entry.second.first, entry.second.second.slice()); links.add(entry.second.first, entry.second.second.slice());
metaState._collections.emplace(entry.first);
} }
links.close(); 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.add(StaticStrings::LinksField, links.slice());
} }
builder.close(); // close PROPERTIES_FIELD
return arangodb::Result(); return arangodb::Result();
} }
@ -421,7 +411,7 @@ IResearchViewCoordinator::IResearchViewCoordinator(
TRI_vocbase_t& vocbase, TRI_vocbase_t& vocbase,
velocypack::Slice info, velocypack::Slice info,
uint64_t planVersion uint64_t planVersion
) : LogicalView(vocbase, info, planVersion) { ) : LogicalViewClusterInfo(vocbase, info, planVersion) {
TRI_ASSERT(ServerState::instance()->isCoordinator()); TRI_ASSERT(ServerState::instance()->isCoordinator());
} }

View File

@ -38,7 +38,7 @@ namespace iresearch {
/// @brief an abstraction over the distributed IResearch index implementing the /// @brief an abstraction over the distributed IResearch index implementing the
/// LogicalView interface /// LogicalView interface
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class IResearchViewCoordinator final : public arangodb::LogicalView { class IResearchViewCoordinator final : public arangodb::LogicalViewClusterInfo {
public: public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief acquire locks on the specified 'cid' during read-transactions /// @brief acquire locks on the specified 'cid' during read-transactions
@ -91,11 +91,10 @@ class IResearchViewCoordinator final : public arangodb::LogicalView {
) override; ) override;
protected: protected:
virtual Result appendVelocyPack( virtual Result appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool detailed,
bool forPersistence bool forPersistence
) const override ; ) const override;
private: private:
IResearchViewCoordinator( IResearchViewCoordinator(

View File

@ -190,16 +190,15 @@ IResearchViewDBServer::IResearchViewDBServer(
arangodb::velocypack::Slice const& info, arangodb::velocypack::Slice const& info,
arangodb::DatabasePathFeature const& dbPathFeature, arangodb::DatabasePathFeature const& dbPathFeature,
uint64_t planVersion uint64_t planVersion
): LogicalView(vocbase, info, planVersion) { ): LogicalViewClusterInfo(vocbase, info, planVersion) {
} }
IResearchViewDBServer::~IResearchViewDBServer() { IResearchViewDBServer::~IResearchViewDBServer() {
_collections.clear(); // ensure view distructors called before mutex is deallocated _collections.clear(); // ensure view distructors called before mutex is deallocated
} }
arangodb::Result IResearchViewDBServer::appendVelocyPack( arangodb::Result IResearchViewDBServer::appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool detailed,
bool //forPersistence bool //forPersistence
) const { ) const {
if (!builder.isOpenObject()) { 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( builder.add(
StaticStrings::PropertiesField, StaticStrings::PropertiesField,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) 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 SCOPED_LOCK(_meta->read()); // '_meta' can be asynchronously updated
if (!_meta->json(builder, &IResearchViewMeta::DEFAULT())) { if (!_meta->json(builder)) {
builder.close(); // close StaticStrings::PropertiesField
return arangodb::Result( return arangodb::Result(
TRI_ERROR_INTERNAL, TRI_ERROR_INTERNAL,
std::string("failure to generate definition while generating properties jSON for IResearch View in database '") + vocbase().name() + "'" 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(); return arangodb::Result();
} }
@ -690,7 +663,7 @@ arangodb::Result IResearchViewDBServer::updateProperties(
static const std::function<bool(irs::string_ref const& key)> propsAcceptor = []( static const std::function<bool(irs::string_ref const& key)> propsAcceptor = [](
irs::string_ref const& key irs::string_ref const& key
)->bool { )->bool {
return key != StaticStrings::CollectionsField && key != StaticStrings::LinksField; // ignored fields return key != StaticStrings::LinksField; // ignored fields
}; };
arangodb::velocypack::Builder props; arangodb::velocypack::Builder props;

View File

@ -50,7 +50,7 @@ namespace iresearch {
class AsyncMeta; class AsyncMeta;
class PrimaryKeyIndexReader; class PrimaryKeyIndexReader;
class IResearchViewDBServer final: public arangodb::LogicalView { class IResearchViewDBServer final: public arangodb::LogicalViewClusterInfo {
public: public:
virtual ~IResearchViewDBServer(); virtual ~IResearchViewDBServer();
@ -112,9 +112,8 @@ class IResearchViewDBServer final: public arangodb::LogicalView {
) const override; ) const override;
protected: protected:
virtual arangodb::Result appendVelocyPack( virtual arangodb::Result appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool detailed,
bool forPersistence bool forPersistence
) const override; ) const override;

View File

@ -26,6 +26,7 @@
#include "RestServer/ViewTypesFeature.h" #include "RestServer/ViewTypesFeature.h"
#include "Basics/StaticStrings.h" #include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ServerState.h" #include "Cluster/ServerState.h"
#include "StorageEngine/EngineSelectorFeature.h" #include "StorageEngine/EngineSelectorFeature.h"
#include "StorageEngine/StorageEngine.h" #include "StorageEngine/StorageEngine.h"
@ -33,16 +34,6 @@
#include "VocBase/ticks.h" #include "VocBase/ticks.h"
#include "VocBase/vocbase.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 { namespace arangodb {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -141,18 +132,70 @@ LogicalView::LogicalView(
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- DBServerLogicalView // --SECTION-- LogicalViewClusterInfo
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
DBServerLogicalView::DBServerLogicalView( LogicalViewClusterInfo::LogicalViewClusterInfo(
TRI_vocbase_t& vocbase, TRI_vocbase_t& vocbase,
VPackSlice const& definition, VPackSlice const& definition,
uint64_t planVersion uint64_t planVersion
): LogicalView(vocbase, definition, 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()) { if (deleted()) {
StorageEngine* engine = EngineSelectorFeature::ENGINE; StorageEngine* engine = EngineSelectorFeature::ENGINE;
TRI_ASSERT(engine); TRI_ASSERT(engine);
@ -161,7 +204,7 @@ DBServerLogicalView::~DBServerLogicalView() {
} }
} }
arangodb::Result DBServerLogicalView::appendVelocyPack( arangodb::Result LogicalViewStorageEngine::appendVelocyPack(
arangodb::velocypack::Builder& builder, arangodb::velocypack::Builder& builder,
bool detailed, bool detailed,
bool forPersistence bool forPersistence
@ -169,7 +212,7 @@ arangodb::Result DBServerLogicalView::appendVelocyPack(
if (!builder.isOpenObject()) { if (!builder.isOpenObject()) {
return arangodb::Result( return arangodb::Result(
TRI_ERROR_BAD_PARAMETER, 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 // includeSystem if we are persisting the properties
if (forPersistence) { if (forPersistence) {
// storage engine related properties // storage engine related properties
StorageEngine* engine = EngineSelectorFeature::ENGINE; auto* engine = EngineSelectorFeature::ENGINE;
if (!engine) { if (!engine) {
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
@ -192,26 +235,25 @@ arangodb::Result DBServerLogicalView::appendVelocyPack(
engine->getViewProperties(vocbase(), *this, builder); engine->getViewProperties(vocbase(), *this, builder);
} }
// implementation Information
if (detailed) { if (detailed) {
// implementation Information auto res = appendVelocyPackDetailed(builder, forPersistence);
builder.add(
PROPERTIES_FIELD, if (!res.ok()) {
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) return res;
); }
getPropertiesVPack(builder, forPersistence);
builder.close();
} }
// ensure that the object is still open // ensure that the object is still open
if (!builder.isOpenObject()) { if (!builder.isOpenObject()) {
return TRI_ERROR_INTERNAL; return arangodb::Result(TRI_ERROR_INTERNAL);
} }
return arangodb::Result(); return arangodb::Result();
} }
/*static*/ arangodb::Result DBServerLogicalView::create( /*static*/ arangodb::Result LogicalViewStorageEngine::create(
DBServerLogicalView const& view LogicalViewStorageEngine const& view
) { ) {
TRI_ASSERT(!ServerState::instance()->isCoordinator()); TRI_ASSERT(!ServerState::instance()->isCoordinator());
StorageEngine* engine = EngineSelectorFeature::ENGINE; 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()); TRI_ASSERT(!ServerState::instance()->isCoordinator());
StorageEngine* engine = EngineSelectorFeature::ENGINE; StorageEngine* engine = EngineSelectorFeature::ENGINE;
TRI_ASSERT(engine); TRI_ASSERT(engine);
@ -276,7 +318,7 @@ arangodb::Result DBServerLogicalView::drop() {
return res; return res;
} }
Result DBServerLogicalView::rename(std::string&& newName, bool doSync) { Result LogicalViewStorageEngine::rename(std::string&& newName, bool doSync) {
TRI_ASSERT(!ServerState::instance()->isCoordinator()); TRI_ASSERT(!ServerState::instance()->isCoordinator());
StorageEngine* engine = EngineSelectorFeature::ENGINE; StorageEngine* engine = EngineSelectorFeature::ENGINE;
TRI_ASSERT(engine); TRI_ASSERT(engine);
@ -304,7 +346,7 @@ Result DBServerLogicalView::rename(std::string&& newName, bool doSync) {
return engine->renameView(vocbase(), *this, oldName); return engine->renameView(vocbase(), *this, oldName);
} }
arangodb::Result DBServerLogicalView::updateProperties( arangodb::Result LogicalViewStorageEngine::updateProperties(
VPackSlice const& slice, VPackSlice const& slice,
bool partialUpdate, bool partialUpdate,
bool doSync bool doSync

View File

@ -184,11 +184,37 @@ class LogicalView : public LogicalDataSource {
}; // LogicalView }; // 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: public:
~DBServerLogicalView() override; ~LogicalViewStorageEngine() override;
arangodb::Result drop() override final; arangodb::Result drop() override final;
@ -204,7 +230,7 @@ class DBServerLogicalView : public LogicalView {
) override final; ) override final;
protected: protected:
DBServerLogicalView( LogicalViewStorageEngine(
TRI_vocbase_t& vocbase, TRI_vocbase_t& vocbase,
velocypack::Slice const& definition, velocypack::Slice const& definition,
uint64_t planVersion uint64_t planVersion
@ -216,25 +242,25 @@ class DBServerLogicalView : public LogicalView {
bool forPersistence bool forPersistence
) const override final; ) 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 /// @brief called by view factories during view creation to persist the view
/// to the storage engine /// 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 /// @brief drop implementation-specific parts of an existing view
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
virtual arangodb::Result dropImpl() = 0; 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) /// @brief called when a view's properties are updated (i.e. delta-modified)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -242,7 +268,7 @@ class DBServerLogicalView : public LogicalView {
velocypack::Slice const& slice, velocypack::Slice const& slice,
bool partialUpdate bool partialUpdate
) = 0; ) = 0;
}; // LogicalView };
} // namespace arangodb } // namespace arangodb

View File

@ -68,8 +68,8 @@ function IResearchFeatureDDLTestSuite () {
var view = db._createView("TestView", "arangosearch", {}); var view = db._createView("TestView", "arangosearch", {});
view.properties(addLink, true); // partial update view.properties(addLink, true); // partial update
let properties = view.properties(); let properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
var indexes = db.TestCollection0.getIndexes(); var indexes = db.TestCollection0.getIndexes();
assertEqual(2, indexes.length); assertEqual(2, indexes.length);
var link = indexes[1]; var link = indexes[1];
@ -94,8 +94,8 @@ function IResearchFeatureDDLTestSuite () {
for (let i = 0; i < 100; ++i) { for (let i = 0; i < 100; ++i) {
view.properties(addLink, true); // partial update view.properties(addLink, true); // partial update
let properties = view.properties(); let properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
var indexes = db.TestCollection0.getIndexes(); var indexes = db.TestCollection0.getIndexes();
assertEqual(2, indexes.length); assertEqual(2, indexes.length);
var link = indexes[1]; var link = indexes[1];
@ -104,8 +104,8 @@ function IResearchFeatureDDLTestSuite () {
assertEqual("arangosearch", link.type); assertEqual("arangosearch", link.type);
view.properties(removeLink, false); view.properties(removeLink, false);
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(0, properties.collections.length); assertEqual(0, Object.keys(properties.links).length);
assertEqual(1, db.TestCollection0.getIndexes().length); assertEqual(1, db.TestCollection0.getIndexes().length);
} }
}, },
@ -119,12 +119,12 @@ function IResearchFeatureDDLTestSuite () {
var addLink = { links: { "TestCollection0": {} } }; var addLink = { links: { "TestCollection0": {} } };
view.properties(addLink, true); // partial update view.properties(addLink, true); // partial update
let properties = view.properties(); let properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
db._drop("TestCollection0"); db._drop("TestCollection0");
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(0, properties.collections.length); assertEqual(0, Object.keys(properties.links).length);
}, },
testViewDDL: function() { testViewDDL: function() {
@ -139,26 +139,26 @@ function IResearchFeatureDDLTestSuite () {
var view = db._createView("TestView", "arangosearch", {}); var view = db._createView("TestView", "arangosearch", {});
var properties = view.properties(); var properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(0, properties.collections.length); assertEqual(0, Object.keys(properties.links).length);
var meta = { links: { "TestCollection0": {} } }; var meta = { links: { "TestCollection0": {} } };
view.properties(meta, true); // partial update view.properties(meta, true); // partial update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
meta = { links: { "TestCollection1": {} } }; meta = { links: { "TestCollection1": {} } };
view.properties(meta, true); // partial update view.properties(meta, true); // partial update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(2, properties.collections.length); assertEqual(2, Object.keys(properties.links).length);
meta = { links: { "TestCollection2": {} } }; meta = { links: { "TestCollection2": {} } };
view.properties(meta, false); // full update view.properties(meta, false); // full update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
// commit // commit

View File

@ -59,26 +59,26 @@ function iResearchFeatureAqlTestSuite () {
var view = db._createView("TestView", "arangosearch", {}); var view = db._createView("TestView", "arangosearch", {});
var properties = view.properties(); var properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(0, properties.collections.length); assertEqual(0, Object.keys(properties.links).length);
var meta = { links: { "TestCollection0": {} } }; var meta = { links: { "TestCollection0": {} } };
view.properties(meta, true); // partial update view.properties(meta, true); // partial update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
meta = { links: { "TestCollection1": {} } }; meta = { links: { "TestCollection1": {} } };
view.properties(meta, true); // partial update view.properties(meta, true); // partial update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(2, properties.collections.length); assertEqual(2, Object.keys(properties.links).length);
meta = { links: { "TestCollection2": {} } }; meta = { links: { "TestCollection2": {} } };
view.properties(meta, false); // full update view.properties(meta, false); // full update
properties = view.properties(); properties = view.properties();
assertTrue(Array === properties.collections.constructor); assertTrue(Object === properties.links.constructor);
assertEqual(1, properties.collections.length); assertEqual(1, Object.keys(properties.links).length);
// commit // commit

View File

@ -453,7 +453,7 @@ function dumpTestSuite () {
let view = db._view("UnitTestsDumpView"); let view = db._view("UnitTestsDumpView");
assertTrue(view !== null); assertTrue(view !== null);
let props = view.properties(); let props = view.properties();
assertEqual(props.collections.length, 1); assertEqual(Object.keys(props.links).length, 1);
assertTrue(props.hasOwnProperty("links")); assertTrue(props.hasOwnProperty("links"));
assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection")); assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection"));
} }

View File

@ -405,7 +405,7 @@ function dumpTestSuite () {
let view = db._view("UnitTestsDumpView"); let view = db._view("UnitTestsDumpView");
assertTrue(view !== null); assertTrue(view !== null);
let props = view.properties(); let props = view.properties();
assertEqual(props.collections.length, 1); assertEqual(Object.keys(props.links).length, 1);
assertTrue(props.hasOwnProperty("links")); assertTrue(props.hasOwnProperty("links"));
assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection")); assertTrue(props.links.hasOwnProperty("UnitTestsDumpViewCollection"));
} }

File diff suppressed because it is too large Load Diff

View File

@ -327,14 +327,12 @@ SECTION("test_defaults") {
// +system, +properties // +system, +properties
{ {
arangodb::iresearch::IResearchViewMeta expectedMeta; arangodb::iresearch::IResearchViewMeta expectedMeta;
arangodb::iresearch::IResearchViewMetaState expectedMetaState;
arangodb::velocypack::Builder builder; arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, true); view->toVelocyPack(builder, true, true);
builder.close(); builder.close();
auto slice = builder.slice(); auto slice = builder.slice();
arangodb::iresearch::IResearchViewMeta meta; arangodb::iresearch::IResearchViewMeta meta;
arangodb::iresearch::IResearchViewMetaState metaState;
std::string error; std::string error;
CHECK(8 == slice.length()); CHECK(8 == slice.length());
@ -347,23 +345,20 @@ SECTION("test_defaults") {
CHECK(false == slice.get("deleted").getBool()); CHECK(false == slice.get("deleted").getBool());
slice = slice.get("properties"); slice = slice.get("properties");
CHECK(slice.isObject()); CHECK(slice.isObject());
CHECK((3 == slice.length())); CHECK((2U == slice.length()));
CHECK((!slice.hasKey("links"))); // for persistence so no links CHECK((!slice.hasKey("links"))); // for persistence so no links
CHECK((meta.init(slice, error) && expectedMeta == meta)); CHECK((meta.init(slice, error) && expectedMeta == meta));
CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState));
} }
// -system, +properties // -system, +properties
{ {
arangodb::iresearch::IResearchViewMeta expectedMeta; arangodb::iresearch::IResearchViewMeta expectedMeta;
arangodb::iresearch::IResearchViewMetaState expectedMetaState;
arangodb::velocypack::Builder builder; arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, false); view->toVelocyPack(builder, true, false);
builder.close(); builder.close();
auto slice = builder.slice(); auto slice = builder.slice();
arangodb::iresearch::IResearchViewMeta meta; arangodb::iresearch::IResearchViewMeta meta;
arangodb::iresearch::IResearchViewMetaState metaState;
std::string error; std::string error;
CHECK(4 == slice.length()); CHECK(4 == slice.length());
@ -374,10 +369,9 @@ SECTION("test_defaults") {
CHECK(!slice.hasKey("deleted")); CHECK(!slice.hasKey("deleted"));
slice = slice.get("properties"); slice = slice.get("properties");
CHECK(slice.isObject()); 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((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length()));
CHECK((meta.init(slice, error) && expectedMeta == meta)); CHECK((meta.init(slice, error) && expectedMeta == meta));
CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState));
} }
// -system, -properties // -system, -properties

View File

@ -828,8 +828,7 @@ SECTION("test_toVelocyPack") {
CHECK((slice.hasKey("properties"))); CHECK((slice.hasKey("properties")));
auto props = slice.get("properties"); auto props = slice.get("properties");
CHECK((props.isObject())); CHECK((props.isObject()));
CHECK((1 == props.length())); CHECK((2U == props.length()));
CHECK((props.hasKey("collections") && props.get("collections").isArray() && 0 == props.get("collections").length()));
} }
// includeSystem // includeSystem
@ -987,12 +986,17 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((!slice.hasKey("links")));
} }
{ {
@ -1006,8 +1010,12 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1020,18 +1028,47 @@ SECTION("test_updateProperties") {
static auto visitor = [](TRI_voc_cid_t)->bool { return false; }; static auto visitor = [](TRI_voc_cid_t)->bool { return false; };
CHECK((true == view->visitCollections(visitor))); // no collections in view CHECK((true == view->visitCollections(visitor))); // no collections in view
arangodb::velocypack::Builder builder; // not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, false); view->toVelocyPack(builder, true, false);
builder.close(); 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.hasKey("commit") && slice.get("commit").isObject())); CHECK((slice.isObject()));
auto tmpSlice = slice.get("commit"); slice = slice.get("properties");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((slice.isObject()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((3U == slice.length()));
CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((false == slice.hasKey("links")));
}
} }
// update empty (full) // update empty (full)
@ -1056,12 +1093,17 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((!slice.hasKey("links")));
} }
{ {
@ -1075,8 +1117,12 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1089,18 +1135,47 @@ SECTION("test_updateProperties") {
static auto visitor = [](TRI_voc_cid_t)->bool { return false; }; static auto visitor = [](TRI_voc_cid_t)->bool { return false; };
CHECK((true == view->visitCollections(visitor))); // no collections in view CHECK((true == view->visitCollections(visitor))); // no collections in view
arangodb::velocypack::Builder builder; // not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, false); view->toVelocyPack(builder, true, false);
builder.close(); 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.hasKey("commit") && slice.get("commit").isObject())); CHECK((slice.isObject()));
auto tmpSlice = slice.get("commit"); slice = slice.get("properties");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((slice.isObject()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((3U == slice.length()));
CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
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<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((false == slice.hasKey("links")));
}
} }
// update non-empty (partial) // update non-empty (partial)
@ -1130,12 +1205,17 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((!slice.hasKey("links")));
} }
{ {
@ -1149,8 +1229,12 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1160,18 +1244,47 @@ SECTION("test_updateProperties") {
CHECK((true == view->visitCollections(visitor))); // no collections in view CHECK((true == view->visitCollections(visitor))); // no collections in view
arangodb::velocypack::Builder builder; // not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, false); view->toVelocyPack(builder, true, false);
builder.close(); 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.hasKey("commit") && slice.get("commit").isObject())); CHECK((slice.isObject()));
auto tmpSlice = slice.get("commit"); slice = slice.get("properties");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((slice.isObject()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((3U == slice.length()));
CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((false == slice.hasKey("links")));
}
} }
// update non-empty (full) // update non-empty (full)
@ -1204,12 +1317,17 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 42 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((!slice.hasKey("links")));
} }
{ {
@ -1223,8 +1341,12 @@ SECTION("test_updateProperties") {
builder.openObject(); builder.openObject();
wiew->toVelocyPack(builder, true, false); wiew->toVelocyPack(builder, true, false);
builder.close(); 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())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit"); auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1234,18 +1356,47 @@ SECTION("test_updateProperties") {
CHECK((true == view->visitCollections(visitor))); // no collections in view CHECK((true == view->visitCollections(visitor))); // no collections in view
arangodb::velocypack::Builder builder; // not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject(); builder.openObject();
view->toVelocyPack(builder, true, false); view->toVelocyPack(builder, true, false);
builder.close(); 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.hasKey("commit") && slice.get("commit").isObject())); CHECK((slice.isObject()));
auto tmpSlice = slice.get("commit"); slice = slice.get("properties");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>())); CHECK((slice.isObject()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>())); CHECK((3U == slice.length()));
CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length())); CHECK((slice.hasKey("commit") && slice.get("commit").isObject()));
auto tmpSlice = slice.get("commit");
CHECK((tmpSlice.hasKey("cleanupIntervalStep") && tmpSlice.get("cleanupIntervalStep").isNumber<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
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<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
CHECK((tmpSlice.hasKey("commitIntervalMsec") && tmpSlice.get("commitIntervalMsec").isNumber<size_t>() && 52 == tmpSlice.get("commitIntervalMsec").getNumber<size_t>()));
CHECK((false == slice.hasKey("links")));
}
} }
} }

View File

@ -42,20 +42,23 @@ std::shared_ptr<arangodb::LogicalView> makeTestView(
uint64_t planVersion, uint64_t planVersion,
arangodb::LogicalView::PreCommitCallback const& preCommit arangodb::LogicalView::PreCommitCallback const& preCommit
) { ) {
struct Impl: public arangodb::DBServerLogicalView { struct Impl: public arangodb::LogicalViewStorageEngine {
Impl( Impl(
TRI_vocbase_t& vocbase, TRI_vocbase_t& vocbase,
arangodb::velocypack::Slice const& info, arangodb::velocypack::Slice const& info,
uint64_t planVersion uint64_t planVersion
): arangodb::DBServerLogicalView(vocbase, info, planVersion) { ): arangodb::LogicalViewStorageEngine(vocbase, info, planVersion) {
} }
arangodb::Result create() { return DBServerLogicalView::create(*this); } virtual arangodb::Result appendVelocyPackDetailed(
virtual arangodb::Result dropImpl() override { return arangodb::Result(); }
virtual void getPropertiesVPack(
arangodb::velocypack::Builder&, arangodb::velocypack::Builder&,
bool bool
) const override { ) 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 void open() override {}
virtual arangodb::Result updateProperties( virtual arangodb::Result updateProperties(
arangodb::velocypack::Slice const&, arangodb::velocypack::Slice const&,

View File

@ -43,20 +43,23 @@ std::shared_ptr<arangodb::LogicalView> makeTestView(
uint64_t planVersion, uint64_t planVersion,
arangodb::LogicalView::PreCommitCallback const& preCommit arangodb::LogicalView::PreCommitCallback const& preCommit
) { ) {
struct Impl: public arangodb::DBServerLogicalView{ struct Impl: public arangodb::LogicalViewStorageEngine {
Impl( Impl(
TRI_vocbase_t& vocbase, TRI_vocbase_t& vocbase,
arangodb::velocypack::Slice const& info, arangodb::velocypack::Slice const& info,
uint64_t planVersion uint64_t planVersion
): DBServerLogicalView(vocbase, info, planVersion) { ): LogicalViewStorageEngine(vocbase, info, planVersion) {
} }
arangodb::Result create() { return DBServerLogicalView::create(*this); } virtual arangodb::Result appendVelocyPackDetailed(
virtual arangodb::Result dropImpl() override { return arangodb::Result(); }
virtual void getPropertiesVPack(
arangodb::velocypack::Builder&, arangodb::velocypack::Builder&,
bool bool
) const override { ) 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 void open() override {}
virtual arangodb::Result updateProperties( virtual arangodb::Result updateProperties(
arangodb::velocypack::Slice const&, arangodb::velocypack::Slice const&,