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
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' ]`)

View File

@ -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");

View File

@ -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

View File

@ -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<AsyncSelf>(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<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) {
// 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<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(
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<arangodb::DBServerLogicalView&>(*view));
auto const res = create(static_cast<arangodb::LogicalViewStorageEngine&>(*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;
{

View File

@ -132,7 +132,8 @@ 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,
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)
//////////////////////////////////////////////////////////////////////////////

View File

@ -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());
}

View File

@ -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,9 +91,8 @@ class IResearchViewCoordinator final : public arangodb::LogicalView {
) override;
protected:
virtual Result appendVelocyPack(
virtual Result appendVelocyPackDetailed(
arangodb::velocypack::Builder& builder,
bool detailed,
bool forPersistence
) const override;

View File

@ -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<bool(irs::string_ref const& key)> 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;

View File

@ -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;

View File

@ -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);
}
if (detailed) {
// implementation Information
builder.add(
PROPERTIES_FIELD,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object)
);
getPropertiesVPack(builder, forPersistence);
builder.close();
if (detailed) {
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

View File

@ -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,7 +268,7 @@ class DBServerLogicalView : public LogicalView {
velocypack::Slice const& slice,
bool partialUpdate
) = 0;
}; // LogicalView
};
} // namespace arangodb

View File

@ -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

View File

@ -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

View File

@ -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"));
}

View File

@ -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"));
}

View File

@ -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,6 +2853,8 @@ SECTION("test_update_overwrite") {
expectedMeta._locale = irs::locale_utils::locale("en", true);
CHECK((view->updateProperties(updateJson->slice(), false, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -2864,7 +2863,6 @@ SECTION("test_update_overwrite") {
auto slice = builder.slice();
arangodb::iresearch::IResearchViewMeta meta;
arangodb::iresearch::IResearchViewMetaState metaState;
std::string error;
CHECK(slice.isObject());
@ -2874,14 +2872,39 @@ SECTION("test_update_overwrite") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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)
{
arangodb::iresearch::IResearchViewMeta expectedMeta;
@ -2893,6 +2916,8 @@ SECTION("test_update_overwrite") {
expectedMeta._locale = irs::locale_utils::locale("ru", true);
CHECK((view->updateProperties(updateJson->slice(), false, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -2910,13 +2935,38 @@ SECTION("test_update_overwrite") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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")));
}
}
}
// overwrite links
@ -2945,6 +2995,8 @@ SECTION("test_update_overwrite") {
expectedLinkMeta["testCollection0"]; // use defaults
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -2962,9 +3014,8 @@ SECTION("test_update_overwrite") {
CHECK(slice.get("deleted").isNone()); // no system properties
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() && 1 == tmpSlice.length()));
@ -2984,6 +3035,33 @@ SECTION("test_update_overwrite") {
));
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()));
CHECK((false == logicalCollection0->getIndexes().empty()));
@ -3001,6 +3079,8 @@ SECTION("test_update_overwrite") {
expectedLinkMeta["testCollection1"]; // use defaults
CHECK((view->updateProperties(updateJson->slice(), false, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3018,9 +3098,8 @@ SECTION("test_update_overwrite") {
CHECK(slice.get("deleted").isNone()); // no system properties
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() && 1 == tmpSlice.length()));
@ -3040,6 +3119,33 @@ SECTION("test_update_overwrite") {
));
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()));
CHECK((true == logicalCollection0->getIndexes().empty()));
@ -3064,6 +3170,8 @@ SECTION("test_update_overwrite") {
);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3076,9 +3184,9 @@ SECTION("test_update_overwrite") {
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(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()));
@ -3086,6 +3194,29 @@ SECTION("test_update_overwrite") {
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
{
auto updateJson = arangodb::velocypack::Parser::fromJson(
@ -3093,6 +3224,8 @@ SECTION("test_update_overwrite") {
);
CHECK((view->updateProperties(updateJson->slice(), false, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3111,6 +3244,28 @@ SECTION("test_update_overwrite") {
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,6 +3295,8 @@ SECTION("test_update_partial") {
expectedMeta._locale = irs::locale_utils::locale("en", true);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3157,14 +3314,39 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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')
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3180,6 +3362,8 @@ SECTION("test_update_partial") {
CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3197,14 +3381,39 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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)
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3226,6 +3435,8 @@ SECTION("test_update_partial") {
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
CHECK((false == persisted));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3246,6 +3457,29 @@ SECTION("test_update_partial") {
));
}
// 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
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3269,6 +3503,8 @@ SECTION("test_update_partial") {
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
CHECK((true == persisted)); // link addition does modify and persist view meta
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3286,9 +3522,8 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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() && 1 == tmpSlice.length()));
@ -3308,6 +3543,33 @@ SECTION("test_update_partial") {
));
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,6 +3614,8 @@ SECTION("test_update_partial") {
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
CHECK((true == persisted)); // link addition does modify and persist view meta
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3368,9 +3632,8 @@ SECTION("test_update_partial") {
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((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() && 1 == tmpSlice.length()));
@ -3390,6 +3653,32 @@ SECTION("test_update_partial") {
));
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,6 +3699,8 @@ SECTION("test_update_partial") {
CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3426,14 +3717,38 @@ SECTION("test_update_partial") {
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((3U == slice.length()));
CHECK((meta.init(slice, error) && expectedMeta == meta));
CHECK((metaState.init(slice, error) && expectedMetaState == metaState));
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)
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3528,6 +3843,8 @@ SECTION("test_update_partial") {
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3545,14 +3862,39 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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() && 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")));
}
}
{
auto updateJson = arangodb::velocypack::Parser::fromJson("{ \
\"links\": { \
@ -3562,6 +3904,8 @@ SECTION("test_update_partial") {
expectedMetaState._collections.clear();
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3579,13 +3923,38 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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 link from non-existant collection
@ -3603,6 +3972,8 @@ SECTION("test_update_partial") {
CHECK((TRI_ERROR_BAD_PARAMETER == view->updateProperties(updateJson->slice(), true, false).errorNumber()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3620,14 +3991,39 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3646,6 +4042,8 @@ SECTION("test_update_partial") {
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3663,14 +4061,39 @@ SECTION("test_update_partial") {
CHECK(slice.get("deleted").isNone()); // no system properties
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()));
}
// 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)
{
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
@ -3687,6 +4110,8 @@ SECTION("test_update_partial") {
);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3699,10 +4124,35 @@ SECTION("test_update_partial") {
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
{
auto updateJson = arangodb::velocypack::Parser::fromJson(
@ -3716,6 +4166,9 @@ SECTION("test_update_partial") {
CHECK((!initial.empty()));
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3728,8 +4181,33 @@ SECTION("test_update_partial") {
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<TRI_idx_iid_t> actual;
@ -3757,6 +4235,8 @@ SECTION("test_update_partial") {
);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3769,9 +4249,9 @@ SECTION("test_update_partial") {
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(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()));
@ -3779,6 +4259,29 @@ SECTION("test_update_partial") {
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
{
auto updateJson = arangodb::velocypack::Parser::fromJson(
@ -3786,6 +4289,8 @@ SECTION("test_update_partial") {
);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
// not for persistence
{
arangodb::velocypack::Builder builder;
builder.openObject();
@ -3798,6 +4303,8 @@ SECTION("test_update_partial") {
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");
@ -3805,6 +4312,29 @@ SECTION("test_update_partial") {
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")));
}
}
}
}

View File

@ -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

View File

@ -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<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((!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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1020,13 +1028,19 @@ SECTION("test_updateProperties") {
static auto visitor = [](TRI_voc_cid_t)->bool { return false; };
CHECK((true == view->visitCollections(visitor))); // no collections in view
// 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()));
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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1034,6 +1048,29 @@ SECTION("test_updateProperties") {
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)
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testCollection\" }");
@ -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<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((!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<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1089,13 +1135,19 @@ SECTION("test_updateProperties") {
static auto visitor = [](TRI_voc_cid_t)->bool { return false; };
CHECK((true == view->visitCollections(visitor))); // no collections in view
// 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()));
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<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1103,6 +1155,29 @@ SECTION("test_updateProperties") {
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)
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testCollection\" }");
@ -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<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((!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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1160,13 +1244,19 @@ SECTION("test_updateProperties") {
CHECK((true == view->visitCollections(visitor))); // no collections in view
// 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()));
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<size_t>() && 24 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1174,6 +1264,29 @@ SECTION("test_updateProperties") {
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)
{
auto collection0Json = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testCollection\" }");
@ -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<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((!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<size_t>() && 10 == tmpSlice.get("cleanupIntervalStep").getNumber<size_t>()));
@ -1234,19 +1356,48 @@ SECTION("test_updateProperties") {
CHECK((true == view->visitCollections(visitor))); // no collections in view
// 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()));
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<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")));
}
}
}
SECTION("test_visitCollections") {

View File

@ -42,20 +42,23 @@ std::shared_ptr<arangodb::LogicalView> 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&,

View File

@ -43,20 +43,23 @@ std::shared_ptr<arangodb::LogicalView> 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&,