mirror of https://gitee.com/bigwinds/arangodb
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:
parent
9a2385b941
commit
1579eb9dfd
13
CHANGELOG
13
CHANGELOG
|
@ -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)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue