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();
|
||||
array->addMember(node);
|
||||
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
|
||||
// result back in index order
|
||||
return ast->createNodeFunctionCall("SORTED_UNIQUE", array);
|
||||
|
|
|
@ -1789,8 +1789,6 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
return true;
|
||||
}
|
||||
|
||||
#warning Reimplement this rule
|
||||
/*
|
||||
auto const& indexes = indexNode->getIndexes();
|
||||
auto cond = indexNode->condition();
|
||||
TRI_ASSERT(cond != nullptr);
|
||||
|
@ -1798,6 +1796,13 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
Variable const* outVariable = indexNode->outVariable();
|
||||
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) {
|
||||
// can only use this index node if it uses exactly one index or multiple
|
||||
// indexes on exactly the same attributes
|
||||
|
@ -1807,17 +1812,13 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<arangodb::basics::AttributeName>> seen;
|
||||
if (!isSparse) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& index : indexes) {
|
||||
if (index->sparse) {
|
||||
// cannot use a sparse index for sorting
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!seen.empty() && arangodb::basics::AttributeName::isIdentical(
|
||||
index->fields, seen, true)) {
|
||||
// different attributes
|
||||
for (auto& idx : indexes) {
|
||||
if (idx != index) {
|
||||
// Can only be sorted iff only one index is used.
|
||||
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
|
||||
// attributes
|
||||
auto index = indexes[0];
|
||||
bool handled = false;
|
||||
|
||||
SortCondition sortCondition(_sorts, cond->getConstAttributes(outVariable, !index->sparse), _variableDefinitions);
|
||||
SortCondition sortCondition(_sorts, cond->getConstAttributes(outVariable, !isSparse), _variableDefinitions);
|
||||
|
||||
bool const isOnlyAttributeAccess =
|
||||
(!sortCondition.isEmpty() && sortCondition.isOnlyAttributeAccess());
|
||||
|
||||
if (isOnlyAttributeAccess && index->isSorted() && !index->sparse &&
|
||||
if (isOnlyAttributeAccess && isSorted && !isSparse &&
|
||||
sortCondition.isUnidirectional() &&
|
||||
sortCondition.isDescending() == indexNode->reverse()) {
|
||||
// we have found a sort condition, which is unidirectional and in the same
|
||||
// order as the IndexNode...
|
||||
// now check if the sort attributes match the ones of the index
|
||||
size_t const numCovered =
|
||||
sortCondition.coveredAttributes(outVariable, index->fields);
|
||||
sortCondition.coveredAttributes(outVariable, fields);
|
||||
|
||||
if (numCovered >= sortCondition.numAttributes()) {
|
||||
// sort condition is fully covered by index... now we can remove the
|
||||
|
@ -1869,12 +1869,11 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
// fields
|
||||
// e.g. FILTER c.value1 == 1 && c.value2 == 42 SORT c.value1, c.value2
|
||||
size_t const numCovered =
|
||||
sortCondition.coveredAttributes(outVariable, index->fields);
|
||||
sortCondition.coveredAttributes(outVariable, fields);
|
||||
|
||||
if (numCovered == sortCondition.numAttributes() &&
|
||||
sortCondition.isUnidirectional() &&
|
||||
(index->isSorted() ||
|
||||
index->fields.size() == sortCondition.numAttributes())) {
|
||||
(isSorted || fields.size() == sortCondition.numAttributes())) {
|
||||
// no need to sort
|
||||
_plan->unlinkNode(_plan->getNodeById(_sortNode->id()));
|
||||
_modified = true;
|
||||
|
@ -1882,7 +1881,6 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return true; // always abort after we found an IndexNode
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "Aql/AstNode.h"
|
||||
#include "Aql/Condition.h"
|
||||
#include "Aql/SortCondition.h"
|
||||
#include "Basics/AttributeNameParser.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
|
@ -2006,6 +2007,28 @@ bool Transaction::supportsFilterCondition(
|
|||
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
|
||||
/// note: the caller must have read-locked the underlying collection when
|
||||
|
@ -2090,26 +2113,13 @@ OperationCursor Transaction::indexScanForCondition(
|
|||
|
||||
return OperationCursor(transactionContext()->orderCustomTypeHandler(),
|
||||
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(
|
||||
std::string const& collectionName, std::string const& indexHandle) {
|
||||
TRI_voc_cid_t cid = resolver()->getCollectionIdLocal(collectionName);
|
||||
|
|
|
@ -37,6 +37,11 @@
|
|||
#define TRI_DEFAULT_BATCH_SIZE 1000
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
namespace basics {
|
||||
class AttributeName;
|
||||
}
|
||||
|
||||
class Index;
|
||||
|
||||
namespace aql {
|
||||
|
@ -400,6 +405,15 @@ class Transaction {
|
|||
arangodb::aql::Variable const*, size_t, size_t&,
|
||||
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
|
||||
/// note: the caller must have read-locked the underlying collection when
|
||||
|
@ -424,14 +438,6 @@ class Transaction {
|
|||
arangodb::aql::Variable const*,
|
||||
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
|
||||
/// note: the caller must have read-locked the underlying collection when
|
||||
|
|
Loading…
Reference in New Issue