1
0
Fork 0

a bit of index cleanup

This commit is contained in:
jsteemann 2016-11-02 22:44:06 +01:00
parent cae493f060
commit 2fdf65c3a4
22 changed files with 54 additions and 598 deletions

View File

@ -48,10 +48,7 @@ static std::vector<std::vector<arangodb::basics::AttributeName>> const IndexAttr
{{arangodb::basics::AttributeName("_from", false)},
{arangodb::basics::AttributeName("_to", false)}};
////////////////////////////////////////////////////////////////////////////////
/// @brief hashes an edge key
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementKey(void*, VPackSlice const* key) {
TRI_ASSERT(key != nullptr);
// we can get away with the fast hash function here, as edge
@ -59,10 +56,7 @@ static uint64_t HashElementKey(void*, VPackSlice const* key) {
return SimpleIndexElement::hash(*key);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashes an edge
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementEdge(void*, SimpleIndexElement const& element, bool byKey) {
if (byKey) {
return element.hash();
@ -72,10 +66,7 @@ static uint64_t HashElementEdge(void*, SimpleIndexElement const& element, bool b
return fasthash64(&revisionId, sizeof(revisionId), 0x56781234);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if key and element match
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualKeyEdge(void* userData, VPackSlice const* left, SimpleIndexElement const& right) {
TRI_ASSERT(left != nullptr);
IndexLookupContext* context = static_cast<IndexLookupContext*>(userData);
@ -90,18 +81,12 @@ static bool IsEqualKeyEdge(void* userData, VPackSlice const* left, SimpleIndexEl
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks for elements are equal
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualElementEdge(void*, SimpleIndexElement const& left, SimpleIndexElement const& right) {
return left.revisionId() == right.revisionId();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks for elements are equal
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualElementEdgeByKey(void* userData, SimpleIndexElement const& left, SimpleIndexElement const& right) {
IndexLookupContext* context = static_cast<IndexLookupContext*>(userData);
try {
@ -429,10 +414,7 @@ void EdgeIndex::buildSearchValueFromArray(TRI_edge_direction_e dir,
builder.close();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a selectivity estimate for the index
////////////////////////////////////////////////////////////////////////////////
double EdgeIndex::selectivityEstimate() const {
if (_edgesFrom == nullptr ||
_edgesTo == nullptr ||
@ -448,20 +430,14 @@ double EdgeIndex::selectivityEstimate() const {
return estimate;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the memory usage for the index
////////////////////////////////////////////////////////////////////////////////
size_t EdgeIndex::memory() const {
TRI_ASSERT(_edgesFrom != nullptr);
TRI_ASSERT(_edgesTo != nullptr);
return _edgesFrom->memoryUsage() + _edgesTo->memoryUsage();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index
////////////////////////////////////////////////////////////////////////////////
void EdgeIndex::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
@ -470,10 +446,7 @@ void EdgeIndex::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
builder.add("sparse", VPackValue(false));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index figures
////////////////////////////////////////////////////////////////////////////////
void EdgeIndex::toVelocyPackFigures(VPackBuilder& builder) const {
Index::toVelocyPackFigures(builder);
builder.add("buckets", VPackValue(_numBuckets));
@ -576,10 +549,7 @@ int EdgeIndex::unload() {
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief provides a size hint for the edge index
////////////////////////////////////////////////////////////////////////////////
int EdgeIndex::sizeHint(arangodb::Transaction* trx, size_t size) {
// we assume this is called when setting up the index and the index
// is still empty
@ -604,10 +574,7 @@ int EdgeIndex::sizeHint(arangodb::Transaction* trx, size_t size) {
return _edgesTo->resize(&context, size + 2049);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether the index supports the condition
////////////////////////////////////////////////////////////////////////////////
bool EdgeIndex::supportsFilterCondition(
arangodb::aql::AstNode const* node,
arangodb::aql::Variable const* reference, size_t itemsInIndex,
@ -618,10 +585,7 @@ bool EdgeIndex::supportsFilterCondition(
estimatedCost);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given Condition
////////////////////////////////////////////////////////////////////////////////
IndexIterator* EdgeIndex::iteratorForCondition(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -662,10 +626,7 @@ IndexIterator* EdgeIndex::iteratorForCondition(
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* EdgeIndex::specializeCondition(
arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) const {
@ -674,12 +635,9 @@ arangodb::aql::AstNode* EdgeIndex::specializeCondition(
return matcher.specializeOne(this, node, reference);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Transform the list of search slices to search values.
/// This will multiply all IN entries and simply return all other
/// entries.
//////////////////////////////////////////////////////////////////////////////
void EdgeIndex::expandInSearchValues(VPackSlice const slice,
VPackBuilder& builder) const {
TRI_ASSERT(slice.isArray());
@ -711,7 +669,6 @@ void EdgeIndex::expandInSearchValues(VPackSlice const slice,
}
builder.close();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given VelocyPackSlices.
/// The searchValue is a an Array with exactly two Entries.
/// If the first is set it means we are searching for _from (OUTBOUND),
@ -726,8 +683,6 @@ void EdgeIndex::expandInSearchValues(VPackSlice const slice,
/// Reverse is not supported, hence ignored
/// NOTE: The iterator is only valid as long as the slice points to
/// a valid memory region.
////////////////////////////////////////////////////////////////////////////////
IndexIterator* EdgeIndex::iteratorForSlice(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -771,10 +726,7 @@ IndexIterator* EdgeIndex::iteratorForSlice(
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator
////////////////////////////////////////////////////////////////////////////////
IndexIterator* EdgeIndex::createEqIterator(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -798,10 +750,7 @@ IndexIterator* EdgeIndex::createEqIterator(
return new EdgeIndexIterator(_collection, trx, mmdr, this, isFrom ? _edgesFrom : _edgesTo, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator
////////////////////////////////////////////////////////////////////////////////
IndexIterator* EdgeIndex::createInIterator(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -832,10 +781,7 @@ IndexIterator* EdgeIndex::createInIterator(
return new EdgeIndexIterator(_collection, trx, mmdr, this, isFrom ? _edgesFrom : _edgesTo, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a single value node to the iterator's keys
////////////////////////////////////////////////////////////////////////////////
void EdgeIndex::handleValNode(VPackBuilder* keys,
arangodb::aql::AstNode const* valNode) const {
if (!valNode->isStringValue() || valNode->getStringLength() == 0) {

View File

@ -118,10 +118,7 @@ class EdgeIndex final : public Index {
arangodb::velocypack::Builder&);
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief typedef for hash tables
//////////////////////////////////////////////////////////////////////////////
public:
IndexType type() const override {
return Index::TRI_IDX_TYPE_EDGE_INDEX;
@ -172,16 +169,12 @@ class EdgeIndex final : public Index {
arangodb::aql::AstNode* specializeCondition(
arangodb::aql::AstNode*, arangodb::aql::Variable const*) const override;
//////////////////////////////////////////////////////////////////////////////
/// @brief Transform the list of search slices to search values.
/// This will multiply all IN entries and simply return all other
/// entries.
//////////////////////////////////////////////////////////////////////////////
void expandInSearchValues(arangodb::velocypack::Slice const,
arangodb::velocypack::Builder&) const override;
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given VelocyPackSlices.
/// The searchValue is a an Array with exactly two Entries, one of them
/// has to be NONE.
@ -195,8 +188,6 @@ class EdgeIndex final : public Index {
/// Reverse is not supported, hence ignored
/// NOTE: The iterator is only valid as long as the slice points to
/// a valid memory region.
////////////////////////////////////////////////////////////////////////////////
IndexIterator* iteratorForSlice(arangodb::Transaction*,
ManagedDocumentResult*,
arangodb::velocypack::Slice const,

View File

@ -34,11 +34,8 @@
using namespace arangodb;
////////////////////////////////////////////////////////////////////////////////
/// @brief walk over the attribute. Also Extract sub-attributes and elements in
/// list.
////////////////////////////////////////////////////////////////////////////////
static void ExtractWords(std::vector<std::string>& words,
VPackSlice const value,
size_t minWordLength,
@ -116,10 +113,7 @@ size_t FulltextIndex::memory() const {
return TRI_MemoryFulltextIndex(_fulltextIndex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index
////////////////////////////////////////////////////////////////////////////////
void FulltextIndex::toVelocyPack(VPackBuilder& builder,
bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
@ -250,11 +244,8 @@ int FulltextIndex::cleanup() {
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief callback function called by the fulltext index to determine the
/// words to index for a specific document
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> FulltextIndex::wordlist(VPackSlice const& doc) {
std::vector<std::string> words;
try {

View File

@ -95,22 +95,13 @@ class FulltextIndex final : public Index {
std::vector<std::string> wordlist(arangodb::velocypack::Slice const&);
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief the indexed attribute (path)
//////////////////////////////////////////////////////////////////////////////
std::vector<std::string> _attr;
//////////////////////////////////////////////////////////////////////////////
/// @brief the fulltext index
//////////////////////////////////////////////////////////////////////////////
TRI_fts_index_t* _fulltextIndex;
//////////////////////////////////////////////////////////////////////////////
/// @brief minimum word length
//////////////////////////////////////////////////////////////////////////////
int _minWordLength;
};
}

View File

@ -82,10 +82,7 @@ GeoIndex::~GeoIndex() {
size_t GeoIndex::memory() const { return GeoIndex_MemoryUsage(_geoIndex); }
////////////////////////////////////////////////////////////////////////////////
/// @brief return a JSON representation of the index
////////////////////////////////////////////////////////////////////////////////
void GeoIndex::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
// Basic index
Index::toVelocyPack(builder, withFigures);
@ -326,10 +323,7 @@ GeoCoordinates* GeoIndex::withinQuery(arangodb::Transaction* trx, double lat,
return GeoIndex_PointsWithinRadius(_geoIndex, &gc, radius);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up the nearest points
////////////////////////////////////////////////////////////////////////////////
GeoCoordinates* GeoIndex::nearQuery(arangodb::Transaction* trx, double lat,
double lon, size_t count) const {
GeoCoordinate gc;

View File

@ -48,10 +48,7 @@ class GeoIndex final : public Index {
~GeoIndex();
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief geo index variants
//////////////////////////////////////////////////////////////////////////////
enum IndexVariant {
INDEX_GEO_NONE = 0,
INDEX_GEO_INDIVIDUAL_LAT_LON,
@ -90,17 +87,11 @@ class GeoIndex final : public Index {
int unload() override;
//////////////////////////////////////////////////////////////////////////////
/// @brief looks up all points within a given radius
//////////////////////////////////////////////////////////////////////////////
GeoCoordinates* withinQuery(arangodb::Transaction*, double, double,
double) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief looks up the nearest points
//////////////////////////////////////////////////////////////////////////////
GeoCoordinates* nearQuery(arangodb::Transaction*, double, double,
size_t) const;
@ -124,31 +115,19 @@ class GeoIndex final : public Index {
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief attribute paths
//////////////////////////////////////////////////////////////////////////////
std::vector<std::string> _location;
std::vector<std::string> _latitude;
std::vector<std::string> _longitude;
//////////////////////////////////////////////////////////////////////////////
/// @brief the geo index variant (geo1 or geo2)
//////////////////////////////////////////////////////////////////////////////
IndexVariant _variant;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether the index is a geoJson index (latitude / longitude
/// reversed)
//////////////////////////////////////////////////////////////////////////////
bool _geoJson;
//////////////////////////////////////////////////////////////////////////////
/// @brief the actual geo index
//////////////////////////////////////////////////////////////////////////////
GeoIdx* _geoIndex;
};
}

View File

@ -203,10 +203,7 @@ void LookupBuilder::buildNextSearchValue() {
_builder->close(); // End of search Array
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if two elements are equal
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualElementElementUnique(void*,
HashIndexElement const* left,
HashIndexElement const* right) {
@ -214,10 +211,7 @@ static bool IsEqualElementElementUnique(void*,
return left->revisionId() == right->revisionId();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if two elements are equal
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualElementElementMulti(void* userData,
HashIndexElement const* left,
HashIndexElement const* right) {
@ -247,18 +241,12 @@ static bool IsEqualElementElementMulti(void* userData,
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief given a key generates a hash integer
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashKey(void*, VPackSlice const* key) {
return HashIndexElement::hash(*key);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if a key corresponds to an element
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualKeyElementMulti(void* userData,
VPackSlice const* left,
HashIndexElement const* right) {
@ -283,10 +271,7 @@ static bool IsEqualKeyElementMulti(void* userData,
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if a key corresponds to an element
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualKeyElementUnique(void* userData, VPackSlice const* left,
uint64_t, HashIndexElement const* right) {
return IsEqualKeyElementMulti(userData, left, right);
@ -429,10 +414,7 @@ void HashIndexIteratorVPack::reset() {
_iterator.reset();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the unique array
////////////////////////////////////////////////////////////////////////////////
HashIndex::UniqueArray::UniqueArray(
size_t numPaths,
TRI_HashArray_t* hashArray, HashElementFunc* hashElement,
@ -446,10 +428,7 @@ HashIndex::UniqueArray::UniqueArray(
TRI_ASSERT(_isEqualElElByKey != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the unique array
////////////////////////////////////////////////////////////////////////////////
HashIndex::UniqueArray::~UniqueArray() {
if (_hashArray != nullptr) {
auto cb = [this](HashIndexElement* element) -> bool {
@ -463,10 +442,7 @@ HashIndex::UniqueArray::~UniqueArray() {
delete _isEqualElElByKey;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the multi array
////////////////////////////////////////////////////////////////////////////////
HashIndex::MultiArray::MultiArray(size_t numPaths,
TRI_HashArrayMulti_t* hashArray,
HashElementFunc* hashElement,
@ -480,10 +456,7 @@ HashIndex::MultiArray::MultiArray(size_t numPaths,
TRI_ASSERT(_isEqualElElByKey != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the multi array
////////////////////////////////////////////////////////////////////////////////
HashIndex::MultiArray::~MultiArray() {
if (_hashArray != nullptr) {
auto cb = [this](HashIndexElement* element) -> bool {
@ -536,10 +509,7 @@ HashIndex::HashIndex(TRI_idx_iid_t iid, LogicalCollection* collection,
func.release();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the index
////////////////////////////////////////////////////////////////////////////////
HashIndex::~HashIndex() {
if (_unique) {
delete _uniqueArray;
@ -548,10 +518,7 @@ HashIndex::~HashIndex() {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns a selectivity estimate for the index
////////////////////////////////////////////////////////////////////////////////
double HashIndex::selectivityEstimate() const {
if (_unique) {
return 1.0;
@ -568,10 +535,7 @@ double HashIndex::selectivityEstimate() const {
return estimate;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the index memory usage
////////////////////////////////////////////////////////////////////////////////
size_t HashIndex::memory() const {
size_t elementSize = HashIndexElement::baseMemoryUsage(_paths.size());
@ -584,20 +548,14 @@ size_t HashIndex::memory() const {
_multiArray->_hashArray->memoryUsage());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a velocypack representation of the index
////////////////////////////////////////////////////////////////////////////////
void HashIndex::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
builder.add("unique", VPackValue(_unique));
builder.add("sparse", VPackValue(_sparse));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a velocypack representation of the index figures
////////////////////////////////////////////////////////////////////////////////
void HashIndex::toVelocyPackFigures(VPackBuilder& builder) const {
TRI_ASSERT(builder.isOpenObject());
builder.add("memory", VPackValue(memory()));
@ -682,10 +640,7 @@ int HashIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
return insertMulti(trx, revisionId, doc, isRollback);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes an entry from the hash array part of the hash index
////////////////////////////////////////////////////////////////////////////////
int HashIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
VPackSlice const& doc, bool isRollback) {
std::vector<HashIndexElement*> elements;
@ -736,10 +691,7 @@ int HashIndex::unload() {
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief provides a size hint for the hash index
////////////////////////////////////////////////////////////////////////////////
int HashIndex::sizeHint(arangodb::Transaction* trx, size_t size) {
if (_sparse) {
// for sparse indexes, we assume that we will have less index entries
@ -757,10 +709,7 @@ int HashIndex::sizeHint(arangodb::Transaction* trx, size_t size) {
return _multiArray->_hashArray->resize(&context, size);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief locates entries in the hash index given VelocyPack slices
////////////////////////////////////////////////////////////////////////////////
int HashIndex::lookup(arangodb::Transaction* trx,
VPackSlice key,
std::vector<HashIndexElement*>& documents) const {
@ -1017,10 +966,7 @@ int HashIndex::removeMultiElement(arangodb::Transaction* trx,
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether the index supports the condition
////////////////////////////////////////////////////////////////////////////////
bool HashIndex::supportsFilterCondition(
arangodb::aql::AstNode const* node,
arangodb::aql::Variable const* reference, size_t itemsInIndex,
@ -1031,10 +977,7 @@ bool HashIndex::supportsFilterCondition(
estimatedCost);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given Condition
////////////////////////////////////////////////////////////////////////////////
IndexIterator* HashIndex::iteratorForCondition(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -1046,10 +989,7 @@ IndexIterator* HashIndex::iteratorForCondition(
return new HashIndexIterator(_collection, trx, mmdr, this, node, reference);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given VelocyPackSlices
////////////////////////////////////////////////////////////////////////////////
IndexIterator* HashIndex::iteratorForSlice(arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
VPackSlice const searchValues,
@ -1065,10 +1005,7 @@ IndexIterator* HashIndex::iteratorForSlice(arangodb::Transaction* trx,
return new HashIndexIteratorVPack(_collection, trx, mmdr, this, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* HashIndex::specializeCondition(
arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) const {

View File

@ -39,18 +39,12 @@
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
////////////////////////////////////////////////////////////////////////////////
/// @brief hash index query parameter
////////////////////////////////////////////////////////////////////////////////
namespace arangodb {
class HashIndex;
////////////////////////////////////////////////////////////////////////////////
/// @brief Class to build Slice lookups out of AST Conditions
////////////////////////////////////////////////////////////////////////////////
class LookupBuilder {
private:
TransactionBuilderLeaser _builder;
@ -84,10 +78,7 @@ class LookupBuilder {
class HashIndexIterator final : public IndexIterator {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief Construct an HashIndexIterator based on Ast Conditions
////////////////////////////////////////////////////////////////////////////////
HashIndexIterator(LogicalCollection* collection, arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
HashIndex const* index,
@ -114,10 +105,7 @@ class HashIndexIterator final : public IndexIterator {
class HashIndexIteratorVPack final : public IndexIterator {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief Construct an HashIndexIterator based on VelocyPack
////////////////////////////////////////////////////////////////////////////////
HashIndexIteratorVPack(LogicalCollection* collection,
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -196,14 +184,11 @@ class HashIndex final : public PathBasedIndex {
arangodb::aql::Variable const*,
bool) const override;
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given VelocyPackSlices
/// Each slice represents the field at the same position. (order matters)
/// And each slice has to be an object of one of the following types:
/// 1) {"eq": <compareValue>} // The value in index is exactly this
/// 2) {"in": <compareValues>} // The value in index os one of them
////////////////////////////////////////////////////////////////////////////////
IndexIterator* iteratorForSlice(arangodb::Transaction*,
ManagedDocumentResult*,
arangodb::velocypack::Slice const,
@ -237,10 +222,7 @@ class HashIndex final : public PathBasedIndex {
arangodb::aql::Variable const* reference,
std::unordered_set<size_t>& found) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief given an element generates a hash integer
//////////////////////////////////////////////////////////////////////////////
private:
class HashElementFunc {
public:
@ -259,10 +241,7 @@ class HashIndex final : public PathBasedIndex {
}
};
//////////////////////////////////////////////////////////////////////////////
/// @brief determines if a key corresponds to an element
//////////////////////////////////////////////////////////////////////////////
class IsEqualElementElementByKey {
size_t _numFields;
@ -296,10 +275,7 @@ class HashIndex final : public PathBasedIndex {
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief the actual hash index (unique type)
//////////////////////////////////////////////////////////////////////////////
typedef arangodb::basics::AssocUnique<arangodb::velocypack::Slice,
HashIndexElement*> TRI_HashArray_t;
@ -316,10 +292,7 @@ class HashIndex final : public PathBasedIndex {
size_t _numPaths;
};
//////////////////////////////////////////////////////////////////////////////
/// @brief the actual hash index (multi type)
//////////////////////////////////////////////////////////////////////////////
typedef arangodb::basics::AssocMulti<arangodb::velocypack::Slice,
HashIndexElement*, uint32_t,
false> TRI_HashArrayMulti_t;

View File

@ -66,11 +66,8 @@ Index::Index(TRI_idx_iid_t iid, arangodb::LogicalCollection* collection,
setFields(fields, Index::allowExpansion(Index::type(slice.get("type").copyString())));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an index stub with a hard-coded selectivity estimate
/// this is used in the cluster coordinator case
////////////////////////////////////////////////////////////////////////////////
Index::Index(VPackSlice const& slice)
: _iid(arangodb::basics::StringUtils::uint64(
arangodb::basics::VelocyPackHelper::checkAndGetStringValue(slice,
@ -166,10 +163,7 @@ Index::IndexType Index::type(std::string const& type) {
return Index::type(type.c_str());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the name of an index type
////////////////////////////////////////////////////////////////////////////////
char const* Index::typeName(Index::IndexType type) {
switch (type) {
case TRI_IDX_TYPE_PRIMARY_INDEX:
@ -195,10 +189,7 @@ char const* Index::typeName(Index::IndexType type) {
return "";
}
////////////////////////////////////////////////////////////////////////////////
/// @brief validate an index id
////////////////////////////////////////////////////////////////////////////////
bool Index::validateId(char const* key) {
char const* p = key;
@ -217,10 +208,7 @@ bool Index::validateId(char const* key) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief validate an index handle (collection name + / + index id)
////////////////////////////////////////////////////////////////////////////////
bool Index::validateHandle(char const* key, size_t* split) {
char const* p = key;
char c = *p;
@ -261,17 +249,11 @@ bool Index::validateHandle(char const* key, size_t* split) {
return validateId(p);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generate a new index id
////////////////////////////////////////////////////////////////////////////////
TRI_idx_iid_t Index::generateId() { return TRI_NewTickServer(); }
////////////////////////////////////////////////////////////////////////////////
/// @brief index comparator, used by the coordinator to detect if two index
/// contents are the same
////////////////////////////////////////////////////////////////////////////////
bool Index::Compare(VPackSlice const& lhs, VPackSlice const& rhs) {
VPackSlice lhsType = lhs.get("type");
TRI_ASSERT(lhsType.isString());
@ -363,10 +345,7 @@ bool Index::Compare(VPackSlice const& lhs, VPackSlice const& rhs) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a contextual string for logging
////////////////////////////////////////////////////////////////////////////////
std::string Index::context() const {
std::ostringstream result;
@ -386,11 +365,8 @@ std::string Index::context() const {
return result.str();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a VelocyPack representation of the index
/// base functionality (called from derived classes)
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackBuilder> Index::toVelocyPack(bool withFigures) const {
auto builder = std::make_shared<VPackBuilder>();
builder->openObject();
@ -399,12 +375,9 @@ std::shared_ptr<VPackBuilder> Index::toVelocyPack(bool withFigures) const {
return builder;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a VelocyPack representation of the index
/// base functionality (called from derived classes)
/// note: needs an already-opened object as its input!
////////////////////////////////////////////////////////////////////////////////
void Index::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
TRI_ASSERT(builder.isOpenObject());
builder.add("id", VPackValue(std::to_string(_iid)));
@ -430,11 +403,8 @@ void Index::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a VelocyPack representation of the index figures
/// base functionality (called from derived classes)
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackBuilder> Index::toVelocyPackFigures() const {
auto builder = std::make_shared<VPackBuilder>();
builder->openObject();
@ -443,11 +413,8 @@ std::shared_ptr<VPackBuilder> Index::toVelocyPackFigures() const {
return builder;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a VelocyPack representation of the index figures
/// base functionality (called from derived classes)
////////////////////////////////////////////////////////////////////////////////
void Index::toVelocyPackFigures(VPackBuilder& builder) const {
TRI_ASSERT(builder.isOpenObject());
builder.add("memory", VPackValue(memory()));
@ -514,6 +481,13 @@ double Index::selectivityEstimate() const {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
}
/// @brief default implementation for implicitlyUnique
bool Index::implicitlyUnique() const {
// simply return whether the index actually is unique
// in this base class, we cannot do anything else
return _unique;
}
/// @brief default implementation for selectivityEstimate
int Index::batchInsert(arangodb::Transaction*, std::vector<std::pair<TRI_voc_rid_t, VPackSlice>> const&, size_t) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
@ -567,10 +541,7 @@ bool Index::supportsSortCondition(arangodb::aql::SortCondition const*,
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief default iterator factory method. does not create an iterator
////////////////////////////////////////////////////////////////////////////////
IndexIterator* Index::iteratorForCondition(arangodb::Transaction*,
ManagedDocumentResult*,
arangodb::aql::AstNode const*,
@ -581,19 +552,13 @@ IndexIterator* Index::iteratorForCondition(arangodb::Transaction*,
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* Index::specializeCondition(
arangodb::aql::AstNode* node, arangodb::aql::Variable const*) const {
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief perform some base checks for an index condition part
////////////////////////////////////////////////////////////////////////////////
bool Index::canUseConditionPart(arangodb::aql::AstNode const* access,
arangodb::aql::AstNode const* other,
arangodb::aql::AstNode const* op,
@ -716,7 +681,6 @@ bool Index::canUseConditionPart(arangodb::aql::AstNode const* access,
return true;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Transform the list of search slices to search values.
/// Always expects a list of lists as input.
/// Outer list represents the single lookups, inner list represents the
@ -726,8 +690,6 @@ bool Index::canUseConditionPart(arangodb::aql::AstNode const* access,
/// Example: Index on (a, b)
/// Input: [ [{=: 1}, {in: 2,3}], [{=:2}, {=:3}]
/// Result: [ [{=: 1}, {=: 2}],[{=:1}, {=:3}], [{=:2}, {=:3}]]
//////////////////////////////////////////////////////////////////////////////
void Index::expandInSearchValues(VPackSlice const base,
VPackBuilder& result) const {
TRI_ASSERT(base.isArray());
@ -819,19 +781,13 @@ void Index::expandInSearchValues(VPackSlice const base,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief append the index description to an output stream
////////////////////////////////////////////////////////////////////////////////
std::ostream& operator<<(std::ostream& stream, arangodb::Index const* index) {
stream << index->context();
return stream;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief append the index description to an output stream
////////////////////////////////////////////////////////////////////////////////
std::ostream& operator<<(std::ostream& stream, arangodb::Index const& index) {
stream << index.context();
return stream;

View File

@ -72,10 +72,7 @@ class Index {
virtual ~Index();
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief index types
//////////////////////////////////////////////////////////////////////////////
enum IndexType {
TRI_IDX_TYPE_UNKNOWN = 0,
TRI_IDX_TYPE_PRIMARY_INDEX,
@ -98,10 +95,7 @@ class Index {
return _fields;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the index fields names
//////////////////////////////////////////////////////////////////////////////
inline std::vector<std::vector<std::string>> fieldNames() const {
std::vector<std::vector<std::string>> result;
@ -115,10 +109,7 @@ class Index {
return result;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the ith attribute is expanded (somewhere)
//////////////////////////////////////////////////////////////////////////////
inline bool isAttributeExpanded(size_t i) const {
if (i >= _fields.size()) {
return false;
@ -126,10 +117,7 @@ class Index {
return TRI_AttributeNamesHaveExpansion(_fields[i]);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not any attribute is expanded
//////////////////////////////////////////////////////////////////////////////
inline bool isAttributeExpanded(
std::vector<arangodb::basics::AttributeName> const& attribute) const {
for (auto const& it : _fields) {
@ -222,14 +210,21 @@ class Index {
virtual bool matchesDefinition(arangodb::velocypack::Slice const&) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the index is sorted
//////////////////////////////////////////////////////////////////////////////
virtual bool isSorted() const = 0;
/// @brief whether or not the index has a selectivity estimate
virtual bool hasSelectivityEstimate() const = 0;
/// @brief return the selectivity estimate of the index
/// must only be called if hasSelectivityEstimate() returns true
virtual double selectivityEstimate() const;
/// @brief whether or not the index is implicitly unique
/// this can be the case if the index is not declared as unique, but contains a
/// unique attribute such as _key
virtual bool implicitlyUnique() const;
virtual size_t memory() const = 0;
virtual void toVelocyPack(arangodb::velocypack::Builder&, bool) const;
@ -286,12 +281,9 @@ class Index {
std::unordered_set<std::string>& nonNullAttributes,
bool) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief Transform the list of search slices to search values.
/// This will multiply all IN entries and simply return all other
/// entries.
//////////////////////////////////////////////////////////////////////////////
virtual void expandInSearchValues(arangodb::velocypack::Slice const,
arangodb::velocypack::Builder&) const;

View File

@ -43,26 +43,17 @@ IndexIterator::IndexIterator(LogicalCollection* collection,
TRI_ASSERT(_mmdr != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief default destructor. Does not free anything
////////////////////////////////////////////////////////////////////////////////
IndexIterator::~IndexIterator() {
if (_responsible) {
delete _mmdr;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief default implementation for next
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult IndexIterator::next() { return IndexLookupResult(); }
////////////////////////////////////////////////////////////////////////////////
/// @brief default implementation for nextBabies
////////////////////////////////////////////////////////////////////////////////
void IndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t batchSize) {
result.clear();
@ -81,16 +72,10 @@ void IndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t ba
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief default implementation for reset
////////////////////////////////////////////////////////////////////////////////
void IndexIterator::reset() {}
////////////////////////////////////////////////////////////////////////////////
/// @brief default implementation for skip
////////////////////////////////////////////////////////////////////////////////
void IndexIterator::skip(uint64_t count, uint64_t& skipped) {
// Skip the first count-many entries
// TODO: Can be improved
@ -100,12 +85,9 @@ void IndexIterator::skip(uint64_t count, uint64_t& skipped) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element
/// If one iterator is exhausted, the next one is used.
/// A nullptr indicates that all iterators are exhausted
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult MultiIndexIterator::next() {
if (_current == nullptr) {
return IndexLookupResult();
@ -123,12 +105,9 @@ IndexLookupResult MultiIndexIterator::next() {
return next;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next limit many elements
/// If one iterator is exhausted, the next one will be used.
/// An empty result vector indicates that all iterators are exhausted
////////////////////////////////////////////////////////////////////////////////
void MultiIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t limit) {
result.clear();
@ -147,11 +126,8 @@ void MultiIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
/// This will reset ALL internal iterators and start all over again
////////////////////////////////////////////////////////////////////////////////
void MultiIndexIterator::reset() {
_current = _iterators.at(0);
_currentIdx = 0;

View File

@ -36,11 +36,8 @@ class Index;
class LogicalCollection;
class Transaction;
////////////////////////////////////////////////////////////////////////////////
/// @brief a base class to iterate over the index. An iterator is requested
/// at the index itself
////////////////////////////////////////////////////////////////////////////////
class IndexIterator {
public:
IndexIterator(IndexIterator const&) = delete;
@ -72,10 +69,7 @@ class IndexIterator {
bool _responsible;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Special iterator if the condition cannot have any result
////////////////////////////////////////////////////////////////////////////////
class EmptyIndexIterator final : public IndexIterator {
public:
EmptyIndexIterator(LogicalCollection* collection, arangodb::Transaction* trx, ManagedDocumentResult* mmdr, arangodb::Index const* index)
@ -96,14 +90,11 @@ class EmptyIndexIterator final : public IndexIterator {
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief a wrapper class to iterate over several IndexIterators.
/// Each iterator is requested at the index itself.
/// This iterator does NOT check for uniqueness.
/// Will always start with the first iterator in the vector. Reverse them
/// Outside if necessary.
////////////////////////////////////////////////////////////////////////////////
class MultiIndexIterator final : public IndexIterator {
public:
@ -126,27 +117,18 @@ class MultiIndexIterator final : public IndexIterator {
char const* typeName() const override { return "multi-index-iterator"; }
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element
/// If one iterator is exhausted, the next one is used.
/// A nullptr indicates that all iterators are exhausted
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult next() override;
////////////////////////////////////////////////////////////////////////////////
/// @brief Get at most the next limit many elements
/// If one iterator is exhausted, the next one will be used.
/// An empty result vector indicates that all iterators are exhausted
////////////////////////////////////////////////////////////////////////////////
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
/// This will reset ALL internal iterators and start all over again
////////////////////////////////////////////////////////////////////////////////
void reset() override;
private:

View File

@ -31,6 +31,10 @@
using namespace arangodb;
/// @brief the _key attribute, which, when used in an index, will implictly make it unique
static std::vector<arangodb::basics::AttributeName> const KeyAttribute
{arangodb::basics::AttributeName("_key", false)};
arangodb::aql::AstNode const* PathBasedIndex::PermutationState::getValue()
const {
if (type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ) {
@ -46,10 +50,7 @@ arangodb::aql::AstNode const* PathBasedIndex::PermutationState::getValue()
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the index
////////////////////////////////////////////////////////////////////////////////
PathBasedIndex::PathBasedIndex(TRI_idx_iid_t iid,
arangodb::LogicalCollection* collection,
VPackSlice const& info, bool allowPartialIndex)
@ -70,16 +71,36 @@ PathBasedIndex::PathBasedIndex(TRI_idx_iid_t iid,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the index
////////////////////////////////////////////////////////////////////////////////
PathBasedIndex::~PathBasedIndex() {}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to insert a document into any index type
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the index is implicitly unique
/// this can be the case if the index is not declared as unique, but contains a
/// unique attribute such as _key
bool PathBasedIndex::implicitlyUnique() const {
if (_unique) {
// a unique index is always unique
return true;
}
if (_useExpansion) {
// when an expansion such as a[*] is used, the index may not be unique, even
// if it contains attributes that are guaranteed to be unique
return false;
}
for (auto const& it : _fields) {
// if _key is contained in the index fields definition, then the index is
// implicitly unique
if (it == KeyAttribute) {
return true;
}
}
// _key not contained
return false;
}
/// @brief helper function to insert a document into any index type
template<typename T>
int PathBasedIndex::fillElement(std::vector<T*>& elements,
TRI_voc_rid_t revisionId,
@ -162,10 +183,7 @@ int PathBasedIndex::fillElement(std::vector<T*>& elements,
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to create the sole index value insert
////////////////////////////////////////////////////////////////////////////////
std::vector<std::pair<VPackSlice, uint32_t>> PathBasedIndex::buildIndexValue(
VPackSlice const documentSlice) {
size_t const n = _paths.size();
@ -192,10 +210,7 @@ std::vector<std::pair<VPackSlice, uint32_t>> PathBasedIndex::buildIndexValue(
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to create a set of index combinations to insert
////////////////////////////////////////////////////////////////////////////////
void PathBasedIndex::buildIndexValues(
VPackSlice const document, size_t level,
std::vector<std::vector<std::pair<VPackSlice, uint32_t>>>& toInsert,
@ -311,10 +326,7 @@ void PathBasedIndex::buildIndexValues(
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to transform AttributeNames into strings.
////////////////////////////////////////////////////////////////////////////////
void PathBasedIndex::fillPaths(std::vector<std::vector<std::string>>& paths,
std::vector<int>& expanding) {
paths.clear();

View File

@ -73,15 +73,14 @@ class PathBasedIndex : public Index {
return _paths;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the attribute paths, a -1 entry means none is expanding,
/// otherwise the non-negative number is the index of the expanding one.
//////////////////////////////////////////////////////////////////////////////
std::vector<int> const& expanding() const {
return _expanding;
}
bool implicitlyUnique() const override;
protected:
/// @brief helper function to insert a document into any index type
template<typename T>
@ -97,43 +96,25 @@ class PathBasedIndex : public Index {
void fillPaths(std::vector<std::vector<std::string>>& paths,
std::vector<int>& expanding);
//////////////////////////////////////////////////////////////////////////////
/// @brief helper function to create a set of index combinations to insert
//////////////////////////////////////////////////////////////////////////////
std::vector<std::pair<VPackSlice, uint32_t>> buildIndexValue(VPackSlice const documentSlice);
//////////////////////////////////////////////////////////////////////////////
/// @brief helper function to create a set of index combinations to insert
//////////////////////////////////////////////////////////////////////////////
void buildIndexValues(VPackSlice const document, size_t level,
std::vector<std::vector<std::pair<VPackSlice, uint32_t>>>& toInsert,
std::vector<std::pair<VPackSlice, uint32_t>>& sliceStack);
protected:
//////////////////////////////////////////////////////////////////////////////
/// @brief the attribute paths
//////////////////////////////////////////////////////////////////////////////
std::vector<std::vector<std::string>> _paths;
//////////////////////////////////////////////////////////////////////////////
/// @brief ... and which of them expands
//////////////////////////////////////////////////////////////////////////////
std::vector<int> _expanding;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not at least one attribute is expanded
//////////////////////////////////////////////////////////////////////////////
bool _useExpansion;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not partial indexing is allowed
//////////////////////////////////////////////////////////////////////////////
bool _allowPartialIndex;
};
}

View File

@ -56,10 +56,7 @@ static inline uint64_t HashElement(void*, SimpleIndexElement const& element) {
return element.hash();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if a key corresponds to an element
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualKeyElement(void* userData, uint8_t const* key,
uint64_t hash,
SimpleIndexElement const& right) {
@ -75,10 +72,7 @@ static bool IsEqualKeyElement(void* userData, uint8_t const* key,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determines if two elements are equal
////////////////////////////////////////////////////////////////////////////////
static bool IsEqualElementElement(void* userData, SimpleIndexElement const& left,
SimpleIndexElement const& right) {
IndexLookupContext* context = static_cast<IndexLookupContext*>(userData);
@ -216,24 +210,15 @@ PrimaryIndex::~PrimaryIndex() {
delete _primaryIndex;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the number of documents from the index
////////////////////////////////////////////////////////////////////////////////
size_t PrimaryIndex::size() const { return _primaryIndex->size(); }
////////////////////////////////////////////////////////////////////////////////
/// @brief return the memory usage of the index
////////////////////////////////////////////////////////////////////////////////
size_t PrimaryIndex::memory() const {
return _primaryIndex->memoryUsage();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index
////////////////////////////////////////////////////////////////////////////////
void PrimaryIndex::toVelocyPack(VPackBuilder& builder, bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
// hard-coded
@ -312,14 +297,11 @@ SimpleIndexElement* PrimaryIndex::lookupKeyRef(arangodb::Transaction* trx,
return element;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief a method to iterate over all elements in the index in
/// a sequential order.
/// Returns nullptr if all documents have been returned.
/// Convention: position === 0 indicates a new start.
/// DEPRECATED
////////////////////////////////////////////////////////////////////////////////
SimpleIndexElement PrimaryIndex::lookupSequential(
arangodb::Transaction* trx, arangodb::basics::BucketPosition& position,
uint64_t& total) {
@ -328,36 +310,27 @@ SimpleIndexElement PrimaryIndex::lookupSequential(
return _primaryIndex->findSequential(&context, position, total);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief request an iterator over all elements in the index in
/// a sequential order.
//////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::allIterator(arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
bool reverse) const {
return new AllIndexIterator(_collection, trx, mmdr, this, _primaryIndex, reverse);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief request an iterator over all elements in the index in
/// a random order. It is guaranteed that each element is found
/// exactly once unless the collection is modified.
//////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::anyIterator(arangodb::Transaction* trx,
ManagedDocumentResult* mmdr) const {
return new AnyIndexIterator(_collection, trx, mmdr, this, _primaryIndex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief a method to iterate over all elements in the index in
/// reversed sequential order.
/// Returns nullptr if all documents have been returned.
/// Convention: position === UINT64_MAX indicates a new start.
/// DEPRECATED
////////////////////////////////////////////////////////////////////////////////
SimpleIndexElement PrimaryIndex::lookupSequentialReverse(
arangodb::Transaction* trx, arangodb::basics::BucketPosition& position) {
ManagedDocumentResult result(trx);
@ -365,11 +338,8 @@ SimpleIndexElement PrimaryIndex::lookupSequentialReverse(
return _primaryIndex->findSequentialReverse(&context, position);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a key/element to the index
/// returns a status code, and *found will contain a found element (if any)
////////////////////////////////////////////////////////////////////////////////
int PrimaryIndex::insertKey(arangodb::Transaction* trx, TRI_voc_rid_t revisionId, VPackSlice const& doc) {
ManagedDocumentResult result(trx);
IndexLookupContext context(trx, _collection, &result, 1);
@ -385,10 +355,7 @@ int PrimaryIndex::insertKey(arangodb::Transaction* trx, TRI_voc_rid_t revisionId
return _primaryIndex->insert(&context, element);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes an key/element from the index
////////////////////////////////////////////////////////////////////////////////
int PrimaryIndex::removeKey(arangodb::Transaction* trx,
TRI_voc_rid_t revisionId, VPackSlice const& doc) {
ManagedDocumentResult result(trx);
@ -418,10 +385,7 @@ int PrimaryIndex::removeKey(arangodb::Transaction* trx,
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief resizes the index
////////////////////////////////////////////////////////////////////////////////
int PrimaryIndex::resize(arangodb::Transaction* trx, size_t targetSize) {
ManagedDocumentResult result(trx);
IndexLookupContext context(trx, _collection, &result, 1);
@ -438,10 +402,7 @@ void PrimaryIndex::invokeOnAllElementsForRemoval(
_primaryIndex->invokeOnAllElementsForRemoval(work);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether the index supports the condition
////////////////////////////////////////////////////////////////////////////////
bool PrimaryIndex::supportsFilterCondition(
arangodb::aql::AstNode const* node,
arangodb::aql::Variable const* reference, size_t itemsInIndex,
@ -452,10 +413,7 @@ bool PrimaryIndex::supportsFilterCondition(
estimatedCost);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given Condition
////////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::iteratorForCondition(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -494,10 +452,7 @@ IndexIterator* PrimaryIndex::iteratorForCondition(
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IndexIterator for the given slice
////////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::iteratorForSlice(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -513,10 +468,7 @@ IndexIterator* PrimaryIndex::iteratorForSlice(
return new PrimaryIndexIterator(_collection, trx, mmdr, this, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* PrimaryIndex::specializeCondition(
arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) const {
@ -525,10 +477,7 @@ arangodb::aql::AstNode* PrimaryIndex::specializeCondition(
return matcher.specializeOne(this, node, reference);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator, for a single attribute, IN operator
////////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::createInIterator(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -561,10 +510,7 @@ IndexIterator* PrimaryIndex::createInIterator(
return new PrimaryIndexIterator(_collection, trx, mmdr, this, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator, for a single attribute, EQ operator
////////////////////////////////////////////////////////////////////////////////
IndexIterator* PrimaryIndex::createEqIterator(
arangodb::Transaction* trx,
ManagedDocumentResult* mmdr,
@ -588,10 +534,7 @@ IndexIterator* PrimaryIndex::createEqIterator(
return new PrimaryIndexIterator(_collection, trx, mmdr, this, keys);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a single value node to the iterator's keys
////////////////////////////////////////////////////////////////////////////////
void PrimaryIndex::handleValNode(arangodb::Transaction* trx,
VPackBuilder* keys,
arangodb::aql::AstNode const* valNode,

View File

@ -156,41 +156,29 @@ class PrimaryIndex final : public Index {
SimpleIndexElement* lookupKeyRef(arangodb::Transaction*, VPackSlice const&) const;
SimpleIndexElement* lookupKeyRef(arangodb::Transaction*, VPackSlice const&, ManagedDocumentResult&) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief a method to iterate over all elements in the index in
/// a sequential order.
/// Returns nullptr if all documents have been returned.
/// Convention: position === 0 indicates a new start.
/// DEPRECATED
//////////////////////////////////////////////////////////////////////////////
SimpleIndexElement lookupSequential(arangodb::Transaction*,
arangodb::basics::BucketPosition& position,
uint64_t& total);
//////////////////////////////////////////////////////////////////////////////
/// @brief request an iterator over all elements in the index in
/// a sequential order.
//////////////////////////////////////////////////////////////////////////////
IndexIterator* allIterator(arangodb::Transaction*, ManagedDocumentResult*, bool reverse) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief request an iterator over all elements in the index in
/// a random order. It is guaranteed that each element is found
/// exactly once unless the collection is modified.
//////////////////////////////////////////////////////////////////////////////
IndexIterator* anyIterator(arangodb::Transaction*, ManagedDocumentResult*) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief a method to iterate over all elements in the index in
/// reversed sequential order.
/// Returns nullptr if all documents have been returned.
/// Convention: position === UINT64_MAX indicates a new start.
/// DEPRECATED
//////////////////////////////////////////////////////////////////////////////
SimpleIndexElement lookupSequentialReverse(
arangodb::Transaction*, arangodb::basics::BucketPosition& position);
@ -225,30 +213,21 @@ class PrimaryIndex final : public Index {
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator, for a single attribute, IN operator
//////////////////////////////////////////////////////////////////////////////
IndexIterator* createInIterator(
arangodb::Transaction*,
ManagedDocumentResult*,
arangodb::aql::AstNode const*,
arangodb::aql::AstNode const*) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief create the iterator, for a single attribute, EQ operator
//////////////////////////////////////////////////////////////////////////////
IndexIterator* createEqIterator(
arangodb::Transaction*,
ManagedDocumentResult*,
arangodb::aql::AstNode const*,
arangodb::aql::AstNode const*) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief add a single value node to the iterator's keys
////////////////////////////////////////////////////////////////////////////////
void handleValNode(arangodb::Transaction* trx,
VPackBuilder* keys,
arangodb::aql::AstNode const* valNode,

View File

@ -122,10 +122,7 @@ RocksDBIterator::RocksDBIterator(LogicalCollection* collection,
reset();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void RocksDBIterator::reset() {
if (_reverse) {
_probe = true;
@ -138,10 +135,7 @@ void RocksDBIterator::reset() {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the index
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult RocksDBIterator::next() {
auto comparator = RocksDBFeature::instance()->comparator();
@ -208,30 +202,21 @@ IndexLookupResult RocksDBIterator::next() {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the index
////////////////////////////////////////////////////////////////////////////////
RocksDBIndex::RocksDBIndex(TRI_idx_iid_t iid,
arangodb::LogicalCollection* collection,
arangodb::velocypack::Slice const& info)
: PathBasedIndex(iid, collection, info, true),
_db(RocksDBFeature::instance()->db()) {}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the index
////////////////////////////////////////////////////////////////////////////////
RocksDBIndex::~RocksDBIndex() {}
size_t RocksDBIndex::memory() const {
return 0; // TODO
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index
////////////////////////////////////////////////////////////////////////////////
void RocksDBIndex::toVelocyPack(VPackBuilder& builder,
bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
@ -239,19 +224,13 @@ void RocksDBIndex::toVelocyPack(VPackBuilder& builder,
builder.add("sparse", VPackValue(_sparse));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index figures
////////////////////////////////////////////////////////////////////////////////
void RocksDBIndex::toVelocyPackFigures(VPackBuilder& builder) const {
TRI_ASSERT(builder.isOpenObject());
builder.add("memory", VPackValue(memory()));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts a document into the index
////////////////////////////////////////////////////////////////////////////////
int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
VPackSlice const& doc, bool isRollback) {
auto comparator = RocksDBFeature::instance()->comparator();
@ -408,10 +387,7 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a document from the index
////////////////////////////////////////////////////////////////////////////////
int RocksDBIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
VPackSlice const& doc, bool isRollback) {
std::vector<SkiplistIndexElement*> elements;
@ -1070,10 +1046,7 @@ IndexIterator* RocksDBIndex::iteratorForCondition(
return lookup(trx, mmdr, searchSlice, reverse);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* RocksDBIndex::specializeCondition(
arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) const {

View File

@ -53,10 +53,7 @@ class PrimaryIndex;
class RocksDBIndex;
class Transaction;
////////////////////////////////////////////////////////////////////////////////
/// @brief Iterator structure for RocksDB. We require a start and stop node
////////////////////////////////////////////////////////////////////////////////
class RocksDBIterator final : public IndexIterator {
private:
friend class RocksDBIndex;
@ -77,16 +74,10 @@ class RocksDBIterator final : public IndexIterator {
char const* typeName() const override { return "rocksdb-index-iterator"; }
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the index
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult next() override;
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void reset() override;
private:
@ -167,13 +158,10 @@ class RocksDBIndex final : public PathBasedIndex {
int drop() override;
//////////////////////////////////////////////////////////////////////////////
/// @brief attempts to locate an entry in the index
///
/// Warning: who ever calls this function is responsible for destroying
/// the velocypack::Slice and the RocksDBIterator* results
//////////////////////////////////////////////////////////////////////////////
RocksDBIterator* lookup(arangodb::Transaction*,
ManagedDocumentResult* mmdr,
arangodb::velocypack::Slice const,
@ -216,10 +204,7 @@ class RocksDBIndex final : public PathBasedIndex {
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief the RocksDB instance
//////////////////////////////////////////////////////////////////////////////
rocksdb::OptimisticTransactionDB* _db;
};

View File

@ -34,11 +34,8 @@ SimpleAttributeEqualityMatcher::SimpleAttributeEqualityMatcher(
std::vector<std::vector<arangodb::basics::AttributeName>> const& attributes)
: _attributes(attributes), _found() {}
////////////////////////////////////////////////////////////////////////////////
/// @brief match a single of the attributes
/// this is used for the primary index and the edge index
////////////////////////////////////////////////////////////////////////////////
bool SimpleAttributeEqualityMatcher::matchOne(
arangodb::Index const* index, arangodb::aql::AstNode const* node,
arangodb::aql::Variable const* reference, size_t itemsInIndex,
@ -66,7 +63,7 @@ bool SimpleAttributeEqualityMatcher::matchOne(
if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op,
reference, nonNullAttributes, false)) {
// we can use the index
// use slightly different cost calculation for IN that for EQ
// use slightly different cost calculation for IN than for EQ
calculateIndexCosts(index, itemsInIndex, estimatedItems, estimatedCost);
estimatedItems *= op->getMember(1)->numMembers();
estimatedCost *= op->getMember(1)->numMembers();
@ -81,11 +78,8 @@ bool SimpleAttributeEqualityMatcher::matchOne(
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief match all of the attributes, in any order
/// this is used for the hash index
////////////////////////////////////////////////////////////////////////////////
bool SimpleAttributeEqualityMatcher::matchAll(
arangodb::Index const* index, arangodb::aql::AstNode const* node,
arangodb::aql::Variable const* reference, size_t itemsInIndex,
@ -146,12 +140,9 @@ bool SimpleAttributeEqualityMatcher::matchAll(
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specialize the condition for the index
/// this is used for the primary index and the edge index
/// requires that a previous matchOne() returned true
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* SimpleAttributeEqualityMatcher::specializeOne(
arangodb::Index const* index, arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) {
@ -201,12 +192,9 @@ arangodb::aql::AstNode* SimpleAttributeEqualityMatcher::specializeOne(
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specialize the condition for the index
/// this is used for the hash index
/// requires that a previous matchAll() returned true
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* SimpleAttributeEqualityMatcher::specializeAll(
arangodb::Index const* index, arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) {
@ -271,23 +259,20 @@ arangodb::aql::AstNode* SimpleAttributeEqualityMatcher::specializeAll(
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief determine the costs of using this index and the number of items
/// that will return in average
/// cost values have no special meaning, except that multiple cost values are
/// comparable, and lower values mean lower costs
////////////////////////////////////////////////////////////////////////////////
void SimpleAttributeEqualityMatcher::calculateIndexCosts(
arangodb::Index const* index, size_t itemsInIndex, size_t& estimatedItems,
double& estimatedCost) const {
double equalityReductionFactor = 20.0;
if (index->unique()) {
if (index->unique() || index->implicitlyUnique()) {
// index is unique, and the condition covers all attributes
// now use a low value for the costs
estimatedItems = 1;
estimatedCost = 0.95;
estimatedCost = 0.95 - 0.02 * (index->fields().size() - 1);
} else if (index->hasSelectivityEstimate()) {
// use index selectivity estimate
double estimate = index->selectivityEstimate();
@ -320,10 +305,7 @@ void SimpleAttributeEqualityMatcher::calculateIndexCosts(
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the access fits
////////////////////////////////////////////////////////////////////////////////
bool SimpleAttributeEqualityMatcher::accessFitsIndex(
arangodb::Index const* index, arangodb::aql::AstNode const* access,
arangodb::aql::AstNode const* other, arangodb::aql::AstNode const* op,

View File

@ -42,68 +42,47 @@ class SimpleAttributeEqualityMatcher {
std::vector<std::vector<arangodb::basics::AttributeName>> const&);
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief match a single of the attributes
/// this is used for the primary index and the edge index
//////////////////////////////////////////////////////////////////////////////
bool matchOne(arangodb::Index const*, arangodb::aql::AstNode const*,
arangodb::aql::Variable const*, size_t, size_t&, double&);
//////////////////////////////////////////////////////////////////////////////
/// @brief match all of the attributes, in any order
/// this is used for the hash index
//////////////////////////////////////////////////////////////////////////////
bool matchAll(arangodb::Index const*, arangodb::aql::AstNode const*,
arangodb::aql::Variable const*, size_t, size_t&, double&);
//////////////////////////////////////////////////////////////////////////////
/// @brief get the condition parts that the index is responsible for
/// this is used for the primary index and the edge index
/// requires that a previous matchOne() returned true
/// the caller must not free the returned AstNode*, as it belongs to the ast
//////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* getOne(arangodb::aql::Ast*, arangodb::Index const*,
arangodb::aql::AstNode const*,
arangodb::aql::Variable const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief specialize the condition for the index
/// this is used for the primary index and the edge index
/// requires that a previous matchOne() returned true
//////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* specializeOne(arangodb::Index const*,
arangodb::aql::AstNode*,
arangodb::aql::Variable const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief specialize the condition for the index
/// this is used for the hash index
/// requires that a previous matchAll() returned true
//////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* specializeAll(arangodb::Index const*,
arangodb::aql::AstNode*,
arangodb::aql::Variable const*);
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief determine the costs of using this index and the number of items
/// that will return in average
/// cost values have no special meaning, except that multiple cost values are
/// comparable, and lower values mean lower costs
//////////////////////////////////////////////////////////////////////////////
void calculateIndexCosts(arangodb::Index const*, size_t, size_t&,
double&) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the access fits
//////////////////////////////////////////////////////////////////////////////
bool accessFitsIndex(arangodb::Index const*, arangodb::aql::AstNode const*,
arangodb::aql::AstNode const*,
arangodb::aql::AstNode const*,
@ -112,17 +91,11 @@ class SimpleAttributeEqualityMatcher {
bool);
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief array of attributes used for comparisons
//////////////////////////////////////////////////////////////////////////////
std::vector<std::vector<arangodb::basics::AttributeName>> const& _attributes;
//////////////////////////////////////////////////////////////////////////////
/// @brief an internal map to mark which condition parts were useful and
/// covered by the index. Also contains the matching Node
//////////////////////////////////////////////////////////////////////////////
std::unordered_map<size_t, arangodb::aql::AstNode const*> _found;
};
}

View File

@ -74,10 +74,7 @@ static size_t sortWeight(arangodb::aql::AstNode const* node) {
// lists: lexicographically and within each slot according to these rules.
// ...........................................................................
////////////////////////////////////////////////////////////////////////////////
/// @brief compares a key with an element, version with proper types
////////////////////////////////////////////////////////////////////////////////
static int CompareKeyElement(void* userData,
VPackSlice const* left,
SkiplistIndexElement const* right,
@ -89,10 +86,7 @@ static int CompareKeyElement(void* userData,
*left, right->slice(context, rightPosition), true);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief compares elements, version with proper types
////////////////////////////////////////////////////////////////////////////////
static int CompareElementElement(void* userData,
SkiplistIndexElement const* left,
size_t leftPosition,
@ -515,10 +509,7 @@ SkiplistIterator::SkiplistIterator(LogicalCollection* collection, arangodb::Tran
reset(); // Initializes the cursor
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void SkiplistIterator::reset() {
if (_reverse) {
_cursor = _rightEndPoint;
@ -527,10 +518,7 @@ void SkiplistIterator::reset() {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the skiplist
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult SkiplistIterator::next() {
if (_cursor == nullptr) {
// We are exhausted already, sorry
@ -576,11 +564,8 @@ SkiplistIterator2::SkiplistIterator2(LogicalCollection* collection, arangodb::Tr
(!_intervals.empty() && _cursor != nullptr));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the interval is valid. It is declared invalid if
/// one border is nullptr or the right is lower than left.
////////////////////////////////////////////////////////////////////////////////
bool SkiplistIterator2::intervalValid(void* userData, Node* left, Node* right) const {
if (left == nullptr) {
return false;
@ -599,10 +584,7 @@ bool SkiplistIterator2::intervalValid(void* userData, Node* left, Node* right) c
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void SkiplistIterator2::reset() {
// If _intervals is empty at this point
// the cursor does not contain any
@ -618,10 +600,7 @@ void SkiplistIterator2::reset() {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the skiplist
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult SkiplistIterator2::next() {
if (_cursor == nullptr) {
// We are exhausted already, sorry
@ -744,10 +723,7 @@ SkiplistIndex::SkiplistIndex(TRI_idx_iid_t iid,
new TRI_Skiplist(CmpElmElm, CmpKeyElm, [this](SkiplistIndexElement* element) { element->free(); }, _unique, _useExpansion);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the skiplist index
////////////////////////////////////////////////////////////////////////////////
SkiplistIndex::~SkiplistIndex() { delete _skiplistIndex; }
size_t SkiplistIndex::memory() const {
@ -755,10 +731,7 @@ size_t SkiplistIndex::memory() const {
static_cast<size_t>(_skiplistIndex->getNrUsed()) * SkiplistIndexElement::baseMemoryUsage(_paths.size());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index
////////////////////////////////////////////////////////////////////////////////
void SkiplistIndex::toVelocyPack(VPackBuilder& builder,
bool withFigures) const {
Index::toVelocyPack(builder, withFigures);
@ -766,20 +739,14 @@ void SkiplistIndex::toVelocyPack(VPackBuilder& builder,
builder.add("sparse", VPackValue(_sparse));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a VelocyPack representation of the index figures
////////////////////////////////////////////////////////////////////////////////
void SkiplistIndex::toVelocyPackFigures(VPackBuilder& builder) const {
TRI_ASSERT(builder.isOpenObject());
builder.add("memory", VPackValue(memory()));
_skiplistIndex->appendToVelocyPack(builder);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts a document into a skiplist index
////////////////////////////////////////////////////////////////////////////////
int SkiplistIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
VPackSlice const& doc, bool isRollback) {
std::vector<SkiplistIndexElement*> elements;
@ -830,10 +797,7 @@ int SkiplistIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a document from a skiplist index
////////////////////////////////////////////////////////////////////////////////
int SkiplistIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
VPackSlice const& doc, bool isRollback) {
std::vector<SkiplistIndexElement*> elements;
@ -880,11 +844,8 @@ int SkiplistIndex::unload() {
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the interval is valid. It is declared invalid if
/// one border is nullptr or the right is lower than left.
////////////////////////////////////////////////////////////////////////////////
bool SkiplistIndex::intervalValid(void* userData, Node* left, Node* right) const {
if (left == nullptr) {
return false;
@ -903,10 +864,7 @@ bool SkiplistIndex::intervalValid(void* userData, Node* left, Node* right) const
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief compares a key with an element in a skip list, generic callback
////////////////////////////////////////////////////////////////////////////////
int SkiplistIndex::KeyElementComparator::operator()(void* userData,
VPackSlice const* leftKey, SkiplistIndexElement const* rightElement) const {
TRI_ASSERT(nullptr != leftKey);
@ -928,10 +886,7 @@ int SkiplistIndex::KeyElementComparator::operator()(void* userData,
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief compares two elements in a skip list, this is the generic callback
////////////////////////////////////////////////////////////////////////////////
int SkiplistIndex::ElementElementComparator::operator()(
void* userData,
SkiplistIndexElement const* leftElement,
@ -1399,7 +1354,8 @@ bool SkiplistIndex::supportsFilterCondition(
values = 1;
}
if (attributesCoveredByEquality == _fields.size() && unique()) {
if (attributesCoveredByEquality == _fields.size() &&
(unique() || implicitlyUnique())) {
// index is unique and condition covers all attributes by equality
if (estimatedItems >= values) {
// reduce costs due to uniqueness
@ -1464,10 +1420,7 @@ bool SkiplistIndex::supportsSortCondition(
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief specializes the condition for use with the index
////////////////////////////////////////////////////////////////////////////////
arangodb::aql::AstNode* SkiplistIndex::specializeCondition(
arangodb::aql::AstNode* node,
arangodb::aql::Variable const* reference) const {

View File

@ -158,7 +158,6 @@ class SkiplistInLookupBuilder : public BaseSkiplistLookupBuilder {
void buildSearchValues();
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Iterator structure for skip list. We require a start and stop node
///
/// Intervals are open in the sense that both end points are not members
@ -166,8 +165,6 @@ class SkiplistInLookupBuilder : public BaseSkiplistLookupBuilder {
/// on the start node to get the first element and that the stop node
/// can be NULL. Note that it is ensured that all intervals in an iterator
/// are non-empty.
////////////////////////////////////////////////////////////////////////////////
class SkiplistIterator final : public IndexIterator {
private:
friend class SkiplistIndex;
@ -198,20 +195,13 @@ class SkiplistIterator final : public IndexIterator {
public:
char const* typeName() const override { return "skiplist-index-iterator"; }
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the skiplist
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult next() override;
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void reset() override;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Iterator structure for skip list. We require a start and stop node
///
/// Intervals are open in the sense that both end points are not members
@ -219,8 +209,6 @@ class SkiplistIterator final : public IndexIterator {
/// on the start node to get the first element and that the stop node
/// can be NULL. Note that it is ensured that all intervals in an iterator
/// are non-empty.
////////////////////////////////////////////////////////////////////////////////
class SkiplistIterator2 final : public IndexIterator {
private:
// Shorthand for the skiplist node
@ -270,42 +258,27 @@ class SkiplistIterator2 final : public IndexIterator {
char const* typeName() const override { return "skiplist-index-iterator2"; }
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the next element in the skiplist
////////////////////////////////////////////////////////////////////////////////
IndexLookupResult next() override;
////////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
////////////////////////////////////////////////////////////////////////////////
void reset() override;
size_t numPaths() const { return _numPaths; }
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief Initialize left and right endpoints with current lookup
/// value. Also points the _cursor to the border of this interval.
////////////////////////////////////////////////////////////////////////////////
void initNextInterval();
////////////////////////////////////////////////////////////////////////////////
/// @brief Forward the cursor to the next interval. If there was no
/// interval the next one is computed. If the _cursor has
/// nullptr after this call the iterator is exhausted.
////////////////////////////////////////////////////////////////////////////////
void forwardCursor();
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the interval is valid. It is declared invalid if
/// one border is nullptr or the right is lower than left.
////////////////////////////////////////////////////////////////////////////////
bool intervalValid(void*, Node*, Node*) const;
};
@ -416,11 +389,8 @@ class SkiplistIndex final : public PathBasedIndex {
arangodb::aql::AstNode const*, arangodb::aql::Variable const*,
std::vector<std::vector<arangodb::aql::AstNode const*>>&, bool&) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the interval is valid. It is declared invalid if
/// one border is nullptr or the right is lower than left.
////////////////////////////////////////////////////////////////////////////////
// Shorthand for the skiplist node
typedef arangodb::basics::SkipListNode<VPackSlice,
SkiplistIndexElement> Node;
@ -433,10 +403,7 @@ class SkiplistIndex final : public PathBasedIndex {
KeyElementComparator CmpKeyElm;
//////////////////////////////////////////////////////////////////////////////
/// @brief the actual skiplist index
//////////////////////////////////////////////////////////////////////////////
TRI_Skiplist* _skiplistIndex;
};
}