1
0
Fork 0

Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
jsteemann 2016-03-15 12:29:11 +01:00
commit b7d576bce2
4 changed files with 61 additions and 44 deletions

View File

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

View File

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

View File

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

View File

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