mirror of https://gitee.com/bigwinds/arangodb
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:
parent
8826f7ef08
commit
9cd3b7a4f5
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue