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); _options->_baseLookupInfos.reserve(numEdgeColls);
// Compute Edge Indexes. First default indexes: // Compute Edge Indexes. First default indexes:
for (size_t i = 0; i < numEdgeColls; ++i) { for (size_t i = 0; i < numEdgeColls; ++i) {
std::string usedField;
auto dir = _directions[i]; auto dir = _directions[i];
// TODO we can optimize here. indexCondition and Expression could be // TODO we can optimize here. indexCondition and Expression could be
// made non-overlapping. // made non-overlapping.
traverser::TraverserOptions::LookupInfo info; traverser::TraverserOptions::LookupInfo info;
switch (dir) { switch (dir) {
case TRI_EDGE_IN: case TRI_EDGE_IN:
usedField = StaticStrings::ToString;
info.indexCondition = info.indexCondition =
globalEdgeConditionBuilder.getInboundCondition()->clone(ast); globalEdgeConditionBuilder.getInboundCondition()->clone(ast);
break; break;
case TRI_EDGE_OUT: case TRI_EDGE_OUT:
usedField = StaticStrings::FromString;
info.indexCondition = info.indexCondition =
globalEdgeConditionBuilder.getOutboundCondition()->clone(ast); globalEdgeConditionBuilder.getOutboundCondition()->clone(ast);
break; break;
@ -921,6 +924,22 @@ void TraversalNode::prepareOptions() {
info.idxHandles[0]); info.idxHandles[0]);
TRI_ASSERT(res); // Right now we have an enforced edge index which will TRI_ASSERT(res); // Right now we have an enforced edge index which will
// always fit. // 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)); _options->_baseLookupInfos.emplace_back(std::move(info));
} }
@ -937,15 +956,18 @@ void TraversalNode::prepareOptions() {
auto& builder = it.second; auto& builder = it.second;
for (size_t i = 0; i < numEdgeColls; ++i) { for (size_t i = 0; i < numEdgeColls; ++i) {
std::string usedField;
auto dir = _directions[i]; auto dir = _directions[i];
// TODO we can optimize here. indexCondition and Expression could be // TODO we can optimize here. indexCondition and Expression could be
// made non-overlapping. // made non-overlapping.
traverser::TraverserOptions::LookupInfo info; traverser::TraverserOptions::LookupInfo info;
switch (dir) { switch (dir) {
case TRI_EDGE_IN: case TRI_EDGE_IN:
usedField = StaticStrings::ToString;
info.indexCondition = builder->getInboundCondition()->clone(ast); info.indexCondition = builder->getInboundCondition()->clone(ast);
break; break;
case TRI_EDGE_OUT: case TRI_EDGE_OUT:
usedField = StaticStrings::FromString;
info.indexCondition = builder->getOutboundCondition()->clone(ast); info.indexCondition = builder->getOutboundCondition()->clone(ast);
break; break;
case TRI_EDGE_ANY: case TRI_EDGE_ANY:
@ -959,6 +981,22 @@ void TraversalNode::prepareOptions() {
info.idxHandles[0]); info.idxHandles[0]);
TRI_ASSERT(res); // Right now we have an enforced edge index which will TRI_ASSERT(res); // Right now we have an enforced edge index which will
// always fit. // 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)); infos.emplace_back(std::move(info));
} }
} }

View File

@ -67,6 +67,14 @@
using namespace arangodb; 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 /// @brief IndexHandle getter method
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

View File

@ -75,6 +75,10 @@ struct TraverserOptions {
std::vector<arangodb::Transaction::IndexHandle> idxHandles; std::vector<arangodb::Transaction::IndexHandle> idxHandles;
aql::Expression* expression; aql::Expression* expression;
aql::AstNode* indexCondition; 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();
~LookupInfo(); ~LookupInfo();