1
0
Fork 0

show which unique constraint was violated in an AQL query (#3330)

this addresses https://stackoverflow.com/questions/46427126/arangodb-3-2-unique-constraint-violation-id-or-key
This commit is contained in:
Jan 2017-10-13 12:13:44 +02:00 committed by Frank Celler
parent 9a2385b941
commit 1579eb9dfd
2 changed files with 54 additions and 12 deletions

View File

@ -1,6 +1,12 @@
devel devel
----- -----
* make AQL return a proper error message in case of a unique key constraint
violation. previously it only returned the generic "unique constraint violated"
error message but omitted the details about which index caused the problem.
This addresses https://stackoverflow.com/questions/46427126/arangodb-3-2-unique-constraint-violation-id-or-key
* fix potential overflow in CRC marker check when a corrupted CRC marker * fix potential overflow in CRC marker check when a corrupted CRC marker
is found at the very beginning of an MMFiles datafile is found at the very beginning of an MMFiles datafile
@ -33,6 +39,13 @@ devel
eight times as high as the previous recommended value. Increasing the eight times as high as the previous recommended value. Increasing the
values helps to prevent an ArangoDB server from running out of memory mappings. values helps to prevent an ArangoDB server from running out of memory mappings.
The raised minimum recommended value may lead to ArangoDB showing some startup
warnings as follows:
WARNING {memory} maximum number of memory mappings per process is 65530, which seems too low. it is recommended to set it to at least 512000
WARNING {memory} execute 'sudo sysctl -w "vm.max_map_count=512000"'
v3.2.4 (2017-XX-XX) v3.2.4 (2017-XX-XX)
------------------- -------------------

View File

@ -327,7 +327,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
keyBuilder.close(); keyBuilder.close();
} else { } else {
// We have an error, handle it // We have an error, handle it
handleResult(errorCode, ep->_options.ignoreErrors); handleResult(errorCode, ep->_options.ignoreErrors, nullptr);
} }
} }
} }
@ -370,7 +370,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) { if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) {
result->emplaceValue(dstRow, _outRegOld, it.get("old")); result->emplaceValue(dstRow, _outRegOld, it.get("old"));
} }
handleResult(errorCode, ep->_options.ignoreErrors); handleResult(errorCode, ep->_options.ignoreErrors, nullptr);
++iter; ++iter;
} }
++dstRow; ++dstRow;
@ -392,7 +392,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) { if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) {
result->emplaceValue(dstRow, _outRegOld, opRes.slice().get("old")); result->emplaceValue(dstRow, _outRegOld, opRes.slice().get("old"));
} }
handleResult(errorCode, ep->_options.ignoreErrors); handleResult(errorCode, ep->_options.ignoreErrors, nullptr);
++dstRow; ++dstRow;
} }
} else { } else {
@ -426,6 +426,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end()); TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const registerId = it->second.registerId; RegisterId const registerId = it->second.registerId;
std::string errorMessage;
bool const producesOutput = (ep->_outVariableNew != nullptr); bool const producesOutput = (ep->_outVariableNew != nullptr);
result.reset(requestBlock(count, getPlanNode()->getRegisterPlan()->nrRegs[getPlanNode()->getDepth()])); result.reset(requestBlock(count, getPlanNode()->getRegisterPlan()->nrRegs[getPlanNode()->getDepth()]));
@ -454,6 +455,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
// only copy 1st row of registers inherited from previous frame(s) // only copy 1st row of registers inherited from previous frame(s)
inheritRegisters(res, result.get(), i, dstRow); inheritRegisters(res, result.get(), i, dstRow);
errorMessage.clear();
int errorCode = TRI_ERROR_NO_ERROR; int errorCode = TRI_ERROR_NO_ERROR;
if (!a.isObject()) { if (!a.isObject()) {
@ -468,13 +470,16 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) { if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) {
// return $NEW // return $NEW
result->emplaceValue(dstRow, _outRegNew, opRes.slice().get("new")); result->emplaceValue(dstRow, _outRegNew, opRes.slice().get("new"));
} }
if (errorCode != TRI_ERROR_NO_ERROR) {
errorMessage.assign(opRes.errorMessage);
}
} else { } else {
errorCode = TRI_ERROR_NO_ERROR; errorCode = TRI_ERROR_NO_ERROR;
} }
} }
handleResult(errorCode, ep->_options.ignoreErrors); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
++dstRow; ++dstRow;
} }
// done with a block // done with a block
@ -605,6 +610,7 @@ AqlItemBlock* UpdateBlock::work(std::vector<AqlItemBlock*>& blocks) {
AqlValue const& a = res->getValueReference(i, docRegisterId); AqlValue const& a = res->getValueReference(i, docRegisterId);
errorMessage.clear();
int errorCode = TRI_ERROR_NO_ERROR; int errorCode = TRI_ERROR_NO_ERROR;
if (a.isObject()) { if (a.isObject()) {
@ -619,9 +625,9 @@ AqlItemBlock* UpdateBlock::work(std::vector<AqlItemBlock*>& blocks) {
} }
} else { } else {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID; errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
errorMessage += std::string("expecting 'Object', got: ") + errorMessage = std::string("expecting 'Object', got: ") +
a.slice().typeName() + std::string(" while handling: ") + a.slice().typeName() + std::string(" while handling: ") +
_exeNode->getTypeString(); _exeNode->getTypeString();
} }
if (errorCode == TRI_ERROR_NO_ERROR) { if (errorCode == TRI_ERROR_NO_ERROR) {
@ -688,6 +694,12 @@ AqlItemBlock* UpdateBlock::work(std::vector<AqlItemBlock*>& blocks) {
// Ignore document not found on the DBserver: // Ignore document not found on the DBserver:
errorCode = TRI_ERROR_NO_ERROR; errorCode = TRI_ERROR_NO_ERROR;
} }
if (errorCode != TRI_ERROR_NO_ERROR) {
errorMessage.assign(opRes.errorMessage);
} else {
errorMessage.clear();
}
handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
++dstRow; ++dstRow;
@ -813,6 +825,7 @@ AqlItemBlock* UpsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
// only copy 1st row of registers inherited from previous frame(s) // only copy 1st row of registers inherited from previous frame(s)
inheritRegisters(res, result.get(), i, dstRow); inheritRegisters(res, result.get(), i, dstRow);
errorMessage.clear();
errorCode = TRI_ERROR_NO_ERROR; errorCode = TRI_ERROR_NO_ERROR;
bool tookThis = false; bool tookThis = false;
@ -842,7 +855,6 @@ AqlItemBlock* UpsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
} else { } else {
updateBuilder = VPackCollection::merge(toUpdate, keyBuilder.slice(), false, false); updateBuilder = VPackCollection::merge(toUpdate, keyBuilder.slice(), false, false);
} }
} else { } else {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID; errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
} }
@ -913,6 +925,11 @@ AqlItemBlock* UpsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) { if (producesOutput && errorCode == TRI_ERROR_NO_ERROR) {
result->emplaceValue(dstRow - 1, _outRegNew, opRes.slice().get("new")); result->emplaceValue(dstRow - 1, _outRegNew, opRes.slice().get("new"));
} }
if (errorCode != TRI_ERROR_NO_ERROR) {
errorMessage.assign(opRes.errorMessage);
} else {
errorMessage.clear();
}
handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
} }
} }
@ -963,6 +980,11 @@ AqlItemBlock* UpsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
// store $NEW // store $NEW
result->emplaceValue(dstRow - 1, _outRegNew, opRes.slice().get("new")); result->emplaceValue(dstRow - 1, _outRegNew, opRes.slice().get("new"));
} }
if (errorCode != TRI_ERROR_NO_ERROR) {
errorMessage.assign(opRes.errorMessage);
} else {
errorMessage.clear();
}
handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
} }
} }
@ -1044,6 +1066,7 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
AqlValue const& a = res->getValueReference(i, docRegisterId); AqlValue const& a = res->getValueReference(i, docRegisterId);
errorMessage.clear();
int errorCode = TRI_ERROR_NO_ERROR; int errorCode = TRI_ERROR_NO_ERROR;
if (a.isObject()) { if (a.isObject()) {
@ -1058,9 +1081,9 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
} }
} else { } else {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID; errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
errorMessage += std::string("expecting 'Object', got: ") + errorMessage = std::string("expecting 'Object', got: ") +
a.slice().typeName() + std::string(" while handling: ") + a.slice().typeName() + std::string(" while handling: ") +
_exeNode->getTypeString(); _exeNode->getTypeString();
} }
if (errorCode == TRI_ERROR_NO_ERROR) { if (errorCode == TRI_ERROR_NO_ERROR) {
@ -1124,6 +1147,12 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
// Ignore document not found on the DBserver: // Ignore document not found on the DBserver:
errorCode = TRI_ERROR_NO_ERROR; errorCode = TRI_ERROR_NO_ERROR;
} }
if (errorCode != TRI_ERROR_NO_ERROR) {
errorMessage.assign(opRes.errorMessage);
} else {
errorMessage.clear();
}
handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage);
++dstRow; ++dstRow;
} else { } else {