mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk
This commit is contained in:
commit
b7d576bce2
|
@ -68,7 +68,10 @@ arangodb::aql::AstNode* IndexBlock::makeUnique(
|
||||||
auto array = ast->createNodeArray();
|
auto array = ast->createNodeArray();
|
||||||
array->addMember(node);
|
array->addMember(node);
|
||||||
auto trx = ast->query()->trx();
|
auto trx = ast->query()->trx();
|
||||||
if (trx->isIndexSorted(_collection->getName(), _indexes[_currentIndex])) {
|
bool isSorted = false;
|
||||||
|
bool isSparse = false;
|
||||||
|
auto unused = trx->getIndexFeatures(_collection->getName(), _indexes[_currentIndex], isSorted, isSparse);
|
||||||
|
if (isSparse) {
|
||||||
// the index is sorted. we need to use SORTED_UNIQUE to get the
|
// the index is sorted. we need to use SORTED_UNIQUE to get the
|
||||||
// result back in index order
|
// result back in index order
|
||||||
return ast->createNodeFunctionCall("SORTED_UNIQUE", array);
|
return ast->createNodeFunctionCall("SORTED_UNIQUE", array);
|
||||||
|
|
|
@ -1789,8 +1789,6 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning Reimplement this rule
|
|
||||||
/*
|
|
||||||
auto const& indexes = indexNode->getIndexes();
|
auto const& indexes = indexNode->getIndexes();
|
||||||
auto cond = indexNode->condition();
|
auto cond = indexNode->condition();
|
||||||
TRI_ASSERT(cond != nullptr);
|
TRI_ASSERT(cond != nullptr);
|
||||||
|
@ -1798,6 +1796,13 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
Variable const* outVariable = indexNode->outVariable();
|
Variable const* outVariable = indexNode->outVariable();
|
||||||
TRI_ASSERT(outVariable != nullptr);
|
TRI_ASSERT(outVariable != nullptr);
|
||||||
|
|
||||||
|
auto index = indexes[0];
|
||||||
|
std::string collectionName = indexNode->collection()->getName();
|
||||||
|
arangodb::Transaction* trx = indexNode->trx();
|
||||||
|
bool isSorted = false;
|
||||||
|
bool isSparse = false;
|
||||||
|
std::vector<std::vector<arangodb::basics::AttributeName>> fields = fields =
|
||||||
|
trx->getIndexFeatures(collectionName, index, isSorted, isSparse);
|
||||||
if (indexes.size() != 1) {
|
if (indexes.size() != 1) {
|
||||||
// can only use this index node if it uses exactly one index or multiple
|
// can only use this index node if it uses exactly one index or multiple
|
||||||
// indexes on exactly the same attributes
|
// indexes on exactly the same attributes
|
||||||
|
@ -1807,17 +1812,13 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<arangodb::basics::AttributeName>> seen;
|
if (!isSparse) {
|
||||||
|
|
||||||
for (auto& index : indexes) {
|
|
||||||
if (index->sparse) {
|
|
||||||
// cannot use a sparse index for sorting
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!seen.empty() && arangodb::basics::AttributeName::isIdentical(
|
for (auto& idx : indexes) {
|
||||||
index->fields, seen, true)) {
|
if (idx != index) {
|
||||||
// different attributes
|
// Can only be sorted iff only one index is used.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1828,22 +1829,21 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
|
|
||||||
// if we get here, we either have one index or multiple indexes on the same
|
// if we get here, we either have one index or multiple indexes on the same
|
||||||
// attributes
|
// attributes
|
||||||
auto index = indexes[0];
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
SortCondition sortCondition(_sorts, cond->getConstAttributes(outVariable, !index->sparse), _variableDefinitions);
|
SortCondition sortCondition(_sorts, cond->getConstAttributes(outVariable, !isSparse), _variableDefinitions);
|
||||||
|
|
||||||
bool const isOnlyAttributeAccess =
|
bool const isOnlyAttributeAccess =
|
||||||
(!sortCondition.isEmpty() && sortCondition.isOnlyAttributeAccess());
|
(!sortCondition.isEmpty() && sortCondition.isOnlyAttributeAccess());
|
||||||
|
|
||||||
if (isOnlyAttributeAccess && index->isSorted() && !index->sparse &&
|
if (isOnlyAttributeAccess && isSorted && !isSparse &&
|
||||||
sortCondition.isUnidirectional() &&
|
sortCondition.isUnidirectional() &&
|
||||||
sortCondition.isDescending() == indexNode->reverse()) {
|
sortCondition.isDescending() == indexNode->reverse()) {
|
||||||
// we have found a sort condition, which is unidirectional and in the same
|
// we have found a sort condition, which is unidirectional and in the same
|
||||||
// order as the IndexNode...
|
// order as the IndexNode...
|
||||||
// now check if the sort attributes match the ones of the index
|
// now check if the sort attributes match the ones of the index
|
||||||
size_t const numCovered =
|
size_t const numCovered =
|
||||||
sortCondition.coveredAttributes(outVariable, index->fields);
|
sortCondition.coveredAttributes(outVariable, fields);
|
||||||
|
|
||||||
if (numCovered >= sortCondition.numAttributes()) {
|
if (numCovered >= sortCondition.numAttributes()) {
|
||||||
// sort condition is fully covered by index... now we can remove the
|
// sort condition is fully covered by index... now we can remove the
|
||||||
|
@ -1869,12 +1869,11 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
// fields
|
// fields
|
||||||
// e.g. FILTER c.value1 == 1 && c.value2 == 42 SORT c.value1, c.value2
|
// e.g. FILTER c.value1 == 1 && c.value2 == 42 SORT c.value1, c.value2
|
||||||
size_t const numCovered =
|
size_t const numCovered =
|
||||||
sortCondition.coveredAttributes(outVariable, index->fields);
|
sortCondition.coveredAttributes(outVariable, fields);
|
||||||
|
|
||||||
if (numCovered == sortCondition.numAttributes() &&
|
if (numCovered == sortCondition.numAttributes() &&
|
||||||
sortCondition.isUnidirectional() &&
|
sortCondition.isUnidirectional() &&
|
||||||
(index->isSorted() ||
|
(isSorted || fields.size() == sortCondition.numAttributes())) {
|
||||||
index->fields.size() == sortCondition.numAttributes())) {
|
|
||||||
// no need to sort
|
// no need to sort
|
||||||
_plan->unlinkNode(_plan->getNodeById(_sortNode->id()));
|
_plan->unlinkNode(_plan->getNodeById(_sortNode->id()));
|
||||||
_modified = true;
|
_modified = true;
|
||||||
|
@ -1882,7 +1881,6 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
return true; // always abort after we found an IndexNode
|
return true; // always abort after we found an IndexNode
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Aql/AstNode.h"
|
#include "Aql/AstNode.h"
|
||||||
#include "Aql/Condition.h"
|
#include "Aql/Condition.h"
|
||||||
#include "Aql/SortCondition.h"
|
#include "Aql/SortCondition.h"
|
||||||
|
#include "Basics/AttributeNameParser.h"
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/StringUtils.h"
|
#include "Basics/StringUtils.h"
|
||||||
#include "Basics/VelocyPackHelper.h"
|
#include "Basics/VelocyPackHelper.h"
|
||||||
|
@ -2006,6 +2007,28 @@ bool Transaction::supportsFilterCondition(
|
||||||
estimatedItems, estimatedCost);
|
estimatedItems, estimatedCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Get the index features:
|
||||||
|
/// Returns the covered attributes, and sets the first bool value
|
||||||
|
/// to isSorted and the second bool value to isSparse
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<std::vector<arangodb::basics::AttributeName>>
|
||||||
|
Transaction::getIndexFeatures(std::string const& collectionName,
|
||||||
|
std::string const& indexHandle, bool& isSorted,
|
||||||
|
bool& isSparse) {
|
||||||
|
|
||||||
|
if (ServerState::instance()->isCoordinator()) {
|
||||||
|
// The index is sorted check is only available on DBServers and Single Server.
|
||||||
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_ONLY_ON_DBSERVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
arangodb::Index* idx = getIndexByIdentifier(collectionName, indexHandle);
|
||||||
|
isSorted = idx->isSorted();
|
||||||
|
isSparse = idx->sparse();
|
||||||
|
return idx->fields();
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Gets the best fitting index for an AQL sort condition
|
/// @brief Gets the best fitting index for an AQL sort condition
|
||||||
/// note: the caller must have read-locked the underlying collection when
|
/// note: the caller must have read-locked the underlying collection when
|
||||||
|
@ -2090,26 +2113,13 @@ OperationCursor Transaction::indexScanForCondition(
|
||||||
|
|
||||||
return OperationCursor(transactionContext()->orderCustomTypeHandler(),
|
return OperationCursor(transactionContext()->orderCustomTypeHandler(),
|
||||||
iterator.release(), limit, batchSize);
|
iterator.release(), limit, batchSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief check if index is sorted
|
/// @brief get the index by it's identifier. Will either throw or
|
||||||
|
/// return a valid index. nullptr is impossible.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool Transaction::isIndexSorted(std::string const& collectionName,
|
|
||||||
std::string const& indexId) {
|
|
||||||
if (ServerState::instance()->isCoordinator()) {
|
|
||||||
// The index is sorted check is only available on DBServers and Single Server.
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_ONLY_ON_DBSERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::Index* idx = getIndexByIdentifier(collectionName, indexId);
|
|
||||||
TRI_ASSERT(idx != nullptr);
|
|
||||||
return idx->isSorted();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::Index* Transaction::getIndexByIdentifier(
|
arangodb::Index* Transaction::getIndexByIdentifier(
|
||||||
std::string const& collectionName, std::string const& indexHandle) {
|
std::string const& collectionName, std::string const& indexHandle) {
|
||||||
TRI_voc_cid_t cid = resolver()->getCollectionIdLocal(collectionName);
|
TRI_voc_cid_t cid = resolver()->getCollectionIdLocal(collectionName);
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
#define TRI_DEFAULT_BATCH_SIZE 1000
|
#define TRI_DEFAULT_BATCH_SIZE 1000
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
|
||||||
|
namespace basics {
|
||||||
|
class AttributeName;
|
||||||
|
}
|
||||||
|
|
||||||
class Index;
|
class Index;
|
||||||
|
|
||||||
namespace aql {
|
namespace aql {
|
||||||
|
@ -400,6 +405,15 @@ class Transaction {
|
||||||
arangodb::aql::Variable const*, size_t, size_t&,
|
arangodb::aql::Variable const*, size_t, size_t&,
|
||||||
double&);
|
double&);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Get the index features:
|
||||||
|
/// Returns the covered attributes, and sets the first bool value
|
||||||
|
/// to isSorted and the second bool value to isSparse
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<std::vector<arangodb::basics::AttributeName>> getIndexFeatures(
|
||||||
|
std::string const&, std::string const&, bool&, bool&);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Gets the best fitting index for an AQL sort condition
|
/// @brief Gets the best fitting index for an AQL sort condition
|
||||||
/// note: the caller must have read-locked the underlying collection when
|
/// note: the caller must have read-locked the underlying collection when
|
||||||
|
@ -424,14 +438,6 @@ class Transaction {
|
||||||
arangodb::aql::Variable const*,
|
arangodb::aql::Variable const*,
|
||||||
uint64_t, uint64_t, bool);
|
uint64_t, uint64_t, bool);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief check if index is sorted
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool isIndexSorted(std::string const& collectionName,
|
|
||||||
std::string const& indexId);
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief factory for OperationCursor objects
|
/// @brief factory for OperationCursor objects
|
||||||
/// note: the caller must have read-locked the underlying collection when
|
/// note: the caller must have read-locked the underlying collection when
|
||||||
|
|
Loading…
Reference in New Issue