1
0
Fork 0

Modified interna of LookupInfo used in traverser. It should now properly name the attribute that has to be adjusted with new _from / _to values. However this is a bug somewhere still. This commit crashes.

This commit is contained in:
Michael Hackstein 2016-09-07 13:37:57 +02:00
parent 8826f7ef08
commit 9cd3b7a4f5
5 changed files with 79 additions and 10 deletions

View File

@ -898,16 +898,19 @@ void TraversalNode::prepareOptions() {
_options->_baseLookupInfos.reserve(numEdgeColls);
// Compute Edge Indexes. First default indexes:
for (size_t i = 0; i < numEdgeColls; ++i) {
std::string usedField;
auto dir = _directions[i];
// TODO we can optimize here. indexCondition and Expression could be
// made non-overlapping.
traverser::TraverserOptions::LookupInfo info;
switch (dir) {
case TRI_EDGE_IN:
usedField = StaticStrings::ToString;
info.indexCondition =
globalEdgeConditionBuilder.getInboundCondition()->clone(ast);
break;
case TRI_EDGE_OUT:
usedField = StaticStrings::FromString;
info.indexCondition =
globalEdgeConditionBuilder.getOutboundCondition()->clone(ast);
break;
@ -921,6 +924,22 @@ void TraversalNode::prepareOptions() {
info.idxHandles[0]);
TRI_ASSERT(res); // Right now we have an enforced edge index which will
// always fit.
// We now have to check if we need _from / _to inside the index lookup and which position
// it is used in. Such that the traverser can update the respective string value
// in-place
// TODO This place can be optimized.
std::vector<std::vector<std::string>> fieldNames =
info.idxHandles[0].fieldNames();
for (size_t i = 0; i < fieldNames.size(); ++i) {
auto f = fieldNames[i];
if (f.size() == 1 && f[0] == usedField) {
// we only work for _from and _to not _from.foo which would be null anyways...
info.conditionNeedUpdate = true;
info.conditionMemberToUpdate = i;
break;
}
}
_options->_baseLookupInfos.emplace_back(std::move(info));
}
@ -937,15 +956,18 @@ void TraversalNode::prepareOptions() {
auto& builder = it.second;
for (size_t i = 0; i < numEdgeColls; ++i) {
std::string usedField;
auto dir = _directions[i];
// TODO we can optimize here. indexCondition and Expression could be
// made non-overlapping.
traverser::TraverserOptions::LookupInfo info;
switch (dir) {
case TRI_EDGE_IN:
usedField = StaticStrings::ToString;
info.indexCondition = builder->getInboundCondition()->clone(ast);
break;
case TRI_EDGE_OUT:
usedField = StaticStrings::FromString;
info.indexCondition = builder->getOutboundCondition()->clone(ast);
break;
case TRI_EDGE_ANY:
@ -959,6 +981,22 @@ void TraversalNode::prepareOptions() {
info.idxHandles[0]);
TRI_ASSERT(res); // Right now we have an enforced edge index which will
// always fit.
// We now have to check if we need _from / _to inside the index lookup and which position
// it is used in. Such that the traverser can update the respective string value
// in-place
// TODO This place can be optimized.
std::vector<std::vector<std::string>> fieldNames =
info.idxHandles[0].fieldNames();
for (size_t i = 0; i < fieldNames.size(); ++i) {
auto f = fieldNames[i];
if (f.size() == 1 && f[0] == usedField) {
// we only work for _from and _to not _from.foo which would be null anyways...
info.conditionNeedUpdate = true;
info.conditionMemberToUpdate = i;
break;
}
}
infos.emplace_back(std::move(info));
}
}

View File

@ -67,6 +67,14 @@
using namespace arangodb;
//////////////////////////////////////////////////////////////////////////////
/// @brief Get the field names of the used index
//////////////////////////////////////////////////////////////////////////////
std::vector<std::vector<std::string>> Transaction::IndexHandle::fieldNames() const {
return _index->fieldNames();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief IndexHandle getter method
//////////////////////////////////////////////////////////////////////////////

View File

@ -97,6 +97,7 @@ class Transaction {
}
explicit IndexHandle(std::shared_ptr<arangodb::Index> idx) : _index(idx) {
}
std::vector<std::vector<std::string>> fieldNames() const;
private:
std::shared_ptr<arangodb::Index> getIndex() const;
};

View File

@ -36,7 +36,10 @@
using VPackHelper = arangodb::basics::VelocyPackHelper;
arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo()
: expression(nullptr), indexCondition(nullptr) {
: expression(nullptr),
indexCondition(nullptr),
conditionNeedUpdate(false),
conditionMemberToUpdate(0) {
// NOTE: We need exactly one in this case for the optimizer to update
idxHandles.resize(1);
};
@ -52,6 +55,12 @@ arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo(
TRI_ASSERT(shards.isArray());
idxHandles.reserve(shards.length());
conditionNeedUpdate = arangodb::basics::VelocyPackHelper::getBooleanValue(
info, "condNeedUpdate", false);
conditionMemberToUpdate =
arangodb::basics::VelocyPackHelper::getNumericValue<size_t>(
info, "condMemberToUpdate", 0);
VPackSlice read = info.get("handle");
if (!read.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(
@ -84,6 +93,7 @@ arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo(
"Each lookup requires expression to be an object");
}
expression = new aql::Expression(query->ast(), read);
read = info.get("condition");
@ -95,10 +105,13 @@ arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo(
indexCondition = new aql::AstNode(query->ast(), read);
}
arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo(LookupInfo const& other)
arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo(
LookupInfo const& other)
: idxHandles(other.idxHandles),
expression(nullptr),
indexCondition(other.indexCondition) {
indexCondition(other.indexCondition),
conditionNeedUpdate(other.conditionNeedUpdate),
conditionMemberToUpdate(other.conditionMemberToUpdate) {
expression = other.expression->clone();
}
@ -118,6 +131,8 @@ void arangodb::traverser::TraverserOptions::LookupInfo::buildEngineInfo(
result.close();
result.add(VPackValue("condition"));
indexCondition->toVelocyPack(result, true);
result.add("condNeedUpdate", VPackValue(conditionNeedUpdate));
result.add("condMemberToUpdate", VPackValue(conditionMemberToUpdate));
result.close();
}
@ -560,14 +575,17 @@ arangodb::traverser::TraverserOptions::nextCursorLocal(
for (auto& info : list) {
auto& node = info.indexCondition;
TRI_ASSERT(node->numMembers() > 0);
auto dirCmp = node->getMemberUnchecked(node->numMembers() - 1);
TRI_ASSERT(dirCmp->type == aql::NODE_TYPE_OPERATOR_BINARY_EQ);
TRI_ASSERT(dirCmp->numMembers() == 2);
if (info.conditionNeedUpdate) {
// We have to inject _from/_to iff the condition needs it
auto dirCmp = node->getMemberUnchecked(info.conditionMemberToUpdate);
TRI_ASSERT(dirCmp->type == aql::NODE_TYPE_OPERATOR_BINARY_EQ);
TRI_ASSERT(dirCmp->numMembers() == 2);
auto idNode = dirCmp->getMemberUnchecked(1);
TRI_ASSERT(idNode->type == aql::NODE_TYPE_VALUE);
TRI_ASSERT(idNode->isValueType(aql::VALUE_TYPE_STRING));
idNode->setStringValue(vid, vidLength);
auto idNode = dirCmp->getMemberUnchecked(1);
TRI_ASSERT(idNode->type == aql::NODE_TYPE_VALUE);
TRI_ASSERT(idNode->isValueType(aql::VALUE_TYPE_STRING));
idNode->setStringValue(vid, vidLength);
}
std::vector<OperationCursor*> csrs;
csrs.reserve(info.idxHandles.size());
for (auto const& it : info.idxHandles) {

View File

@ -75,6 +75,10 @@ struct TraverserOptions {
std::vector<arangodb::Transaction::IndexHandle> idxHandles;
aql::Expression* expression;
aql::AstNode* indexCondition;
// Flag if we have to update _from / _to in the index search condition
bool conditionNeedUpdate;
// Position of _from / _to in the index search condition
size_t conditionMemberToUpdate;
LookupInfo();
~LookupInfo();