1
0
Fork 0

Fix AQL REPLACE for smart edges.

This commit is contained in:
Max Neunhoeffer 2016-10-13 10:58:59 +02:00
parent b993de3c42
commit a3b5e993f7
3 changed files with 51 additions and 32 deletions

View File

@ -291,7 +291,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
errorCode = TRI_ERROR_NO_ERROR; errorCode = TRI_ERROR_NO_ERROR;
if (!ep->_options.consultAqlWriteFilter || if (!ep->_options.consultAqlWriteFilter ||
!_collection->getCollection()->skipForAqlWrite(a.slice())) { !_collection->getCollection()->skipForAqlWrite(a.slice(), "")) {
if (a.isObject()) { if (a.isObject()) {
// value is an object. now extract the _key attribute // value is an object. now extract the _key attribute
key.clear(); key.clear();
@ -335,7 +335,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
AqlValue const& a = res->getValueReference(i, registerId); AqlValue const& a = res->getValueReference(i, registerId);
if (!ep->_options.consultAqlWriteFilter || if (!ep->_options.consultAqlWriteFilter ||
!_collection->getCollection()->skipForAqlWrite(a.slice())) { !_collection->getCollection()->skipForAqlWrite(a.slice(), "")) {
TRI_ASSERT(iter.valid()); TRI_ASSERT(iter.valid());
auto it = iter.value(); auto it = iter.value();
bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue( bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue(
@ -446,7 +446,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID; errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
} else { } else {
if (!ep->_options.consultAqlWriteFilter || if (!ep->_options.consultAqlWriteFilter ||
!_collection->getCollection()->skipForAqlWrite(a.slice())) { !_collection->getCollection()->skipForAqlWrite(a.slice(), "")) {
OperationResult opRes = _trx->insert(_collection->name, a.slice(), options); OperationResult opRes = _trx->insert(_collection->name, a.slice(), options);
errorCode = opRes.code; errorCode = opRes.code;
@ -473,7 +473,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
inheritRegisters(res, result.get(), i, dstRow); inheritRegisters(res, result.get(), i, dstRow);
// TODO This may be optimized with externals // TODO This may be optimized with externals
if (!ep->_options.consultAqlWriteFilter || if (!ep->_options.consultAqlWriteFilter ||
!_collection->getCollection()->skipForAqlWrite(a.slice())) { !_collection->getCollection()->skipForAqlWrite(a.slice(), "")) {
babyBuilder.add(a.slice()); babyBuilder.add(a.slice());
} }
++dstRow; ++dstRow;
@ -493,7 +493,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
AqlValue a = res->getValue(i, registerId); AqlValue a = res->getValue(i, registerId);
if (!ep->_options.consultAqlWriteFilter || if (!ep->_options.consultAqlWriteFilter ||
!_collection->getCollection()->skipForAqlWrite(a.slice())) { !_collection->getCollection()->skipForAqlWrite(a.slice(), "")) {
TRI_ASSERT(iter.valid()); TRI_ASSERT(iter.valid());
auto elm = iter.value(); auto elm = iter.value();
bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue( bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue(
@ -1007,6 +1007,8 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
std::string key; std::string key;
// loop over the complete block // loop over the complete block
std::vector<bool> wasTaken;
wasTaken.reserve(n);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
inheritRegisters(res, result.get(), i, dstRow + i); inheritRegisters(res, result.get(), i, dstRow + i);
@ -1018,7 +1020,7 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
// value is an object // value is an object
key.clear(); key.clear();
if (hasKeyVariable) { if (hasKeyVariable) {
// seperate key specification // separate key specification
AqlValue const& k = res->getValueReference(i, keyRegisterId); AqlValue const& k = res->getValueReference(i, keyRegisterId);
errorCode = extractKey(k, key); errorCode = extractKey(k, key);
} else { } else {
@ -1032,24 +1034,31 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
} }
if (errorCode == TRI_ERROR_NO_ERROR) { if (errorCode == TRI_ERROR_NO_ERROR) {
if (hasKeyVariable) { if (!ep->_options.consultAqlWriteFilter ||
keyBuilder.clear(); !_collection->getCollection()->skipForAqlWrite(a.slice(), key)) {
keyBuilder.openObject(); wasTaken.push_back(true);
keyBuilder.add(StaticStrings::KeyString, VPackValue(key)); if (hasKeyVariable) {
keyBuilder.close(); keyBuilder.clear();
VPackBuilder tmp = VPackCollection::merge( keyBuilder.openObject();
a.slice(), keyBuilder.slice(), false, false); keyBuilder.add(StaticStrings::KeyString, VPackValue(key));
if (isMultiple) { keyBuilder.close();
object.add(tmp.slice()); VPackBuilder tmp = VPackCollection::merge(
a.slice(), keyBuilder.slice(), false, false);
if (isMultiple) {
object.add(tmp.slice());
} else {
object = tmp;
}
} else { } else {
object = tmp; // Use the original slice for updating
object.add(a.slice());
} }
} else { } else {
// Use the original slice for updateing wasTaken.push_back(false);
object.add(a.slice());
} }
} else { } else {
handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
wasTaken.push_back(false);
} }
} }
@ -1059,7 +1068,9 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
VPackSlice toUpdate = object.slice(); VPackSlice toUpdate = object.slice();
if (toUpdate.isNone()) { if (toUpdate.isNone() ||
(toUpdate.isArray() && toUpdate.length() == 0)) {
dstRow += n;
continue; continue;
} }
// fetch old revision // fetch old revision
@ -1091,22 +1102,28 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
if (producesOutput) { if (producesOutput) {
VPackSlice resultList = opRes.slice(); VPackSlice resultList = opRes.slice();
TRI_ASSERT(resultList.isArray()); TRI_ASSERT(resultList.isArray());
for (auto const& elm : VPackArrayIterator(resultList)) { auto iter = VPackArrayIterator(resultList);
bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue(elm, "error", false); for (size_t i = 0; i < n; ++i) {
if (!wasError) { if (wasTaken[i]) {
if (ep->_outVariableOld != nullptr) { TRI_ASSERT(iter.valid());
// store $OLD auto elm = iter.value();
result->setValue(dstRow, _outRegOld, AqlValue(elm.get("old"))); bool wasError = arangodb::basics::VelocyPackHelper::getBooleanValue(elm, "error", false);
} if (!wasError) {
if (ep->_outVariableNew != nullptr) { if (ep->_outVariableOld != nullptr) {
// store $NEW // store $OLD
result->setValue(dstRow, _outRegNew, AqlValue(elm.get("new"))); result->setValue(dstRow, _outRegOld, AqlValue(elm.get("old")));
}
if (ep->_outVariableNew != nullptr) {
// store $NEW
result->setValue(dstRow, _outRegNew, AqlValue(elm.get("new")));
}
} }
++iter;
} }
dstRow++; dstRow++;
} }
} else { } else {
dstRow += static_cast<size_t>(toUpdate.length()); dstRow += n;
} }
handleBabyResult(opRes.countErrorCodes, static_cast<size_t>(toUpdate.length()), handleBabyResult(opRes.countErrorCodes, static_cast<size_t>(toUpdate.length()),
ep->_options.ignoreErrors); ep->_options.ignoreErrors);

View File

@ -3406,7 +3406,8 @@ void LogicalCollection::newObjectForRemove(
/// @brief a method to skip certain documents in AQL write operations, /// @brief a method to skip certain documents in AQL write operations,
/// this is only used in the enterprise edition for smart graphs /// this is only used in the enterprise edition for smart graphs
#ifndef USE_ENTERPRISE #ifndef USE_ENTERPRISE
bool LogicalCollection::skipForAqlWrite(arangodb::velocypack::Slice document) const { bool LogicalCollection::skipForAqlWrite(arangodb::velocypack::Slice document,
std::string const& key) const {
return false; return false;
} }
#endif #endif

View File

@ -238,7 +238,8 @@ class LogicalCollection {
/// @brief a method to skip certain documents in AQL write operations, /// @brief a method to skip certain documents in AQL write operations,
/// this is only used in the enterprise edition for smart graphs /// this is only used in the enterprise edition for smart graphs
virtual bool skipForAqlWrite(arangodb::velocypack::Slice document) const; virtual bool skipForAqlWrite(arangodb::velocypack::Slice document,
std::string const& key) const;
// SECTION: Modification Functions // SECTION: Modification Functions
int rename(std::string const&); int rename(std::string const&);