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
-----
* 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
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
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)
-------------------

View File

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