mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk
This commit is contained in:
commit
21e5e68ae5
|
@ -262,18 +262,13 @@ void RestVocbaseBaseHandler::generate20x(
|
||||||
TRI_col_type_e type) {
|
TRI_col_type_e type) {
|
||||||
|
|
||||||
VPackSlice slice = result.slice();
|
VPackSlice slice = result.slice();
|
||||||
TRI_ASSERT(slice.isObject());
|
TRI_ASSERT(slice.isObject() || slice.isArray());
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
_response->setContentType("application/json; charset=utf-8");
|
||||||
_response->setHeader("etag", 4, "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
if (slice.isObject()) {
|
||||||
|
_response->setHeader("etag", 4, "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
||||||
std::string escapedHandle(DocumentHelper::assembleDocumentId(
|
// pre 1.4 location headers withdrawn for >= 3.0
|
||||||
collectionName, slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString(), true));
|
std::string escapedHandle(DocumentHelper::assembleDocumentId(
|
||||||
if (_request->compatibility() < 10400L) {
|
collectionName, slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString(), true));
|
||||||
// pre-1.4 location header (e.g. /_api/document/xyz)
|
|
||||||
_response->setHeader("location", 8,
|
|
||||||
std::string(DOCUMENT_PATH + "/" + escapedHandle));
|
|
||||||
} else {
|
|
||||||
// 1.4+ location header (e.g. /_db/_system/_api/document/xyz)
|
|
||||||
if (type == TRI_COL_TYPE_EDGE) {
|
if (type == TRI_COL_TYPE_EDGE) {
|
||||||
_response->setHeader("location", 8,
|
_response->setHeader("location", 8,
|
||||||
std::string("/_db/" + _request->databaseName() +
|
std::string("/_db/" + _request->databaseName() +
|
||||||
|
|
|
@ -737,40 +737,50 @@ OperationResult Transaction::insert(std::string const& collectionName,
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.isArray()) {
|
|
||||||
// multi-document variant is not yet implemented
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Edges
|
// Validate Edges
|
||||||
if (isEdgeCollection(collectionName)) {
|
if (isEdgeCollection(collectionName)) {
|
||||||
// Check _from
|
// Check _from
|
||||||
size_t split;
|
auto checkFrom = [&](VPackSlice const value) -> void {
|
||||||
VPackSlice from = value.get(TRI_VOC_ATTRIBUTE_FROM);
|
size_t split;
|
||||||
if (!from.isString()) {
|
VPackSlice from = value.get(TRI_VOC_ATTRIBUTE_FROM);
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
if (!from.isString()) {
|
||||||
}
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||||
std::string docId = from.copyString();
|
}
|
||||||
if (!TRI_ValidateDocumentIdKeyGenerator(docId.c_str(), &split)) {
|
std::string docId = from.copyString();
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
if (!TRI_ValidateDocumentIdKeyGenerator(docId.c_str(), &split)) {
|
||||||
}
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||||
std::string cName = docId.substr(0, split);
|
}
|
||||||
if (TRI_COL_TYPE_UNKNOWN == resolver()->getCollectionType(cName)) {
|
std::string cName = docId.substr(0, split);
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
if (TRI_COL_TYPE_UNKNOWN == resolver()->getCollectionType(cName)) {
|
||||||
}
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Check _to
|
// Check _to
|
||||||
VPackSlice to = value.get(TRI_VOC_ATTRIBUTE_TO);
|
auto checkTo = [&](VPackSlice const value) -> void {
|
||||||
if (!to.isString()) {
|
size_t split;
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
VPackSlice to = value.get(TRI_VOC_ATTRIBUTE_TO);
|
||||||
}
|
if (!to.isString()) {
|
||||||
docId = to.copyString();
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||||
if (!TRI_ValidateDocumentIdKeyGenerator(docId.c_str(), &split)) {
|
}
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
std::string docId = to.copyString();
|
||||||
}
|
if (!TRI_ValidateDocumentIdKeyGenerator(docId.c_str(), &split)) {
|
||||||
cName = docId.substr(0, split);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||||
if (TRI_COL_TYPE_UNKNOWN == resolver()->getCollectionType(cName)) {
|
}
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
std::string cName = docId.substr(0, split);
|
||||||
|
if (TRI_COL_TYPE_UNKNOWN == resolver()->getCollectionType(cName)) {
|
||||||
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (value.isArray()) {
|
||||||
|
for (auto s : VPackArrayIterator(value)) {
|
||||||
|
checkFrom(s);
|
||||||
|
checkTo(s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkFrom(value);
|
||||||
|
checkTo(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,6 +802,12 @@ OperationResult Transaction::insert(std::string const& collectionName,
|
||||||
OperationResult Transaction::insertCoordinator(std::string const& collectionName,
|
OperationResult Transaction::insertCoordinator(std::string const& collectionName,
|
||||||
VPackSlice const& value,
|
VPackSlice const& value,
|
||||||
OperationOptions& options) {
|
OperationOptions& options) {
|
||||||
|
|
||||||
|
if (value.isArray()) {
|
||||||
|
// must provide a document object
|
||||||
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
arangodb::rest::HttpResponse::HttpResponseCode responseCode;
|
arangodb::rest::HttpResponse::HttpResponseCode responseCode;
|
||||||
std::map<std::string, std::string> resultHeaders;
|
std::map<std::string, std::string> resultHeaders;
|
||||||
|
@ -847,70 +863,83 @@ OperationResult Transaction::insertLocal(std::string const& collectionName,
|
||||||
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add missing attributes for document (_id, _rev, _key)
|
|
||||||
VPackBuilder merge;
|
|
||||||
merge.openObject();
|
|
||||||
|
|
||||||
// generate a new tick value
|
|
||||||
TRI_voc_tick_t const revisionId = TRI_NewTickServer();
|
|
||||||
std::string keyString;
|
|
||||||
// TODO: clean this up
|
|
||||||
TRI_document_collection_t* document = documentCollection(trxCollection(cid));
|
TRI_document_collection_t* document = documentCollection(trxCollection(cid));
|
||||||
|
|
||||||
auto key = value.get(TRI_VOC_ATTRIBUTE_KEY);
|
|
||||||
|
|
||||||
if (key.isNone()) {
|
|
||||||
// "_key" attribute not present in object
|
|
||||||
keyString = document->_keyGenerator->generate(revisionId);
|
|
||||||
merge.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(keyString));
|
|
||||||
} else if (!key.isString()) {
|
|
||||||
// "_key" present but wrong type
|
|
||||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
|
||||||
} else {
|
|
||||||
keyString = key.copyString();
|
|
||||||
int res = document->_keyGenerator->validate(keyString, false);
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
// invalid key value
|
|
||||||
return OperationResult(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add _rev attribute
|
|
||||||
merge.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(std::to_string(revisionId)));
|
|
||||||
|
|
||||||
// add _id attribute
|
|
||||||
uint8_t* p = merge.add(TRI_VOC_ATTRIBUTE_ID, VPackValuePair(9ULL, VPackValueType::Custom));
|
|
||||||
*p++ = 0xf3; // custom type for _id
|
|
||||||
MarkerHelper::storeNumber<uint64_t>(p, cid, sizeof(uint64_t));
|
|
||||||
|
|
||||||
merge.close();
|
|
||||||
|
|
||||||
VPackBuilder toInsert = VPackCollection::merge(value, merge.slice(), false, false);
|
|
||||||
VPackSlice insertSlice = toInsert.slice();
|
|
||||||
|
|
||||||
if (orderDitch(trxCollection(cid)) == nullptr) {
|
|
||||||
return OperationResult(TRI_ERROR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_doc_mptr_t mptr;
|
|
||||||
int res = document->insert(this, &insertSlice, &mptr, options, !isLocked(document, TRI_TRANSACTION_WRITE));
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
return OperationResult(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.silent) {
|
|
||||||
// no need to construct the result object
|
|
||||||
return OperationResult(TRI_ERROR_NO_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_ASSERT(mptr.getDataPtr() != nullptr);
|
|
||||||
|
|
||||||
VPackBuilder resultBuilder;
|
VPackBuilder resultBuilder;
|
||||||
buildDocumentIdentity(resultBuilder, cid, keyString, mptr._rid, "");
|
|
||||||
|
|
||||||
return OperationResult(resultBuilder.steal(), nullptr, "", TRI_ERROR_NO_ERROR,
|
auto workForOneDocument = [&](VPackSlice const value) -> int {
|
||||||
|
// add missing attributes for document (_id, _rev, _key)
|
||||||
|
VPackBuilder merge;
|
||||||
|
merge.openObject();
|
||||||
|
|
||||||
|
// generate a new tick value
|
||||||
|
TRI_voc_tick_t const revisionId = TRI_NewTickServer();
|
||||||
|
std::string keyString;
|
||||||
|
auto key = value.get(TRI_VOC_ATTRIBUTE_KEY);
|
||||||
|
|
||||||
|
if (key.isNone()) {
|
||||||
|
// "_key" attribute not present in object
|
||||||
|
keyString = document->_keyGenerator->generate(revisionId);
|
||||||
|
merge.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(keyString));
|
||||||
|
} else if (!key.isString()) {
|
||||||
|
// "_key" present but wrong type
|
||||||
|
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
|
||||||
|
} else {
|
||||||
|
keyString = key.copyString();
|
||||||
|
int res = document->_keyGenerator->validate(keyString, false);
|
||||||
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
// invalid key value
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add _rev attribute
|
||||||
|
merge.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(std::to_string(revisionId)));
|
||||||
|
|
||||||
|
// add _id attribute
|
||||||
|
uint8_t* p = merge.add(TRI_VOC_ATTRIBUTE_ID, VPackValuePair(9ULL, VPackValueType::Custom));
|
||||||
|
*p++ = 0xf3; // custom type for _id
|
||||||
|
MarkerHelper::storeNumber<uint64_t>(p, cid, sizeof(uint64_t));
|
||||||
|
|
||||||
|
merge.close();
|
||||||
|
|
||||||
|
VPackBuilder toInsert = VPackCollection::merge(value, merge.slice(), false, false);
|
||||||
|
VPackSlice insertSlice = toInsert.slice();
|
||||||
|
|
||||||
|
TRI_doc_mptr_t mptr;
|
||||||
|
int res = document->insert(this, &insertSlice, &mptr, options,
|
||||||
|
!isLocked(document, TRI_TRANSACTION_WRITE));
|
||||||
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.silent) {
|
||||||
|
// no need to construct the result object
|
||||||
|
return TRI_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(mptr.getDataPtr() != nullptr);
|
||||||
|
|
||||||
|
buildDocumentIdentity(resultBuilder, cid, keyString, mptr._rid, "");
|
||||||
|
return TRI_ERROR_NO_ERROR;
|
||||||
|
};
|
||||||
|
|
||||||
|
int res;
|
||||||
|
if (value.isArray()) {
|
||||||
|
VPackArrayBuilder b(&resultBuilder);
|
||||||
|
for (auto const s : VPackArrayIterator(value)) {
|
||||||
|
res = workForOneDocument(s);
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = workForOneDocument(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OperationResult(resultBuilder.steal(), nullptr, "", res,
|
||||||
options.waitForSync);
|
options.waitForSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1886,7 +1886,7 @@ static void JS_InsertVocbaseVPack(
|
||||||
options.waitForSync = ExtractWaitForSync(args, optsIdx + 1);
|
options.waitForSync = ExtractWaitForSync(args, optsIdx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args[docIdx]->IsObject() || args[docIdx]->IsArray()) {
|
if (!args[docIdx]->IsObject()) {
|
||||||
// invalid value type. must be a document
|
// invalid value type. must be a document
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
@ -1895,37 +1895,53 @@ static void JS_InsertVocbaseVPack(
|
||||||
VPackOptions vpackOptions = VPackOptions::Defaults;
|
VPackOptions vpackOptions = VPackOptions::Defaults;
|
||||||
vpackOptions.attributeExcludeHandler = basics::VelocyPackHelper::getExcludeHandler();
|
vpackOptions.attributeExcludeHandler = basics::VelocyPackHelper::getExcludeHandler();
|
||||||
VPackBuilder builder(&vpackOptions);
|
VPackBuilder builder(&vpackOptions);
|
||||||
|
v8::Handle<v8::Value> payload = args[0];
|
||||||
|
|
||||||
int res = TRI_V8ToVPack(isolate, builder, args[docIdx]->ToObject(), true);
|
auto doOneDocument = [&](v8::Handle<v8::Value> obj) -> void {
|
||||||
|
int res = TRI_V8ToVPack(isolate, builder, obj, true);
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
}
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
|
||||||
if (isEdgeCollection) {
|
|
||||||
// Just insert from and to. Check is done later.
|
|
||||||
std::string tmpId = ExtractIdString(isolate, args[0]);
|
|
||||||
if (tmpId.empty()) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
|
||||||
}
|
}
|
||||||
builder.add(TRI_VOC_ATTRIBUTE_FROM, VPackValue(tmpId));
|
|
||||||
|
|
||||||
tmpId = ExtractIdString(isolate, args[1]);
|
if (isEdgeCollection) {
|
||||||
if (tmpId.empty()) {
|
// Just insert from and to. Check is done later.
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
std::string tmpId = ExtractIdString(isolate, obj);
|
||||||
|
if (tmpId.empty()) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||||
|
}
|
||||||
|
builder.add(TRI_VOC_ATTRIBUTE_FROM, VPackValue(tmpId));
|
||||||
|
|
||||||
|
tmpId = ExtractIdString(isolate, args[1]);
|
||||||
|
if (tmpId.empty()) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||||
|
}
|
||||||
|
builder.add(TRI_VOC_ATTRIBUTE_TO, VPackValue(tmpId));
|
||||||
}
|
}
|
||||||
builder.add(TRI_VOC_ATTRIBUTE_TO, VPackValue(tmpId));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.close();
|
builder.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (payload->IsArray()) {
|
||||||
|
VPackArrayBuilder b(&builder);
|
||||||
|
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(payload);
|
||||||
|
uint32_t const n = array->Length();
|
||||||
|
for (uint32_t i = 0; i < n; ++i) {
|
||||||
|
doOneDocument(array->Get(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
doOneDocument(payload);
|
||||||
|
}
|
||||||
|
|
||||||
// load collection
|
// load collection
|
||||||
auto transactionContext = std::make_shared<V8TransactionContext>(collection->_vocbase, true);
|
auto transactionContext = std::make_shared<V8TransactionContext>(collection->_vocbase, true);
|
||||||
|
|
||||||
SingleCollectionTransaction trx(transactionContext, collection->_cid, TRI_TRANSACTION_WRITE);
|
SingleCollectionTransaction trx(transactionContext, collection->_cid, TRI_TRANSACTION_WRITE);
|
||||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
if (! payload->IsArray()) {
|
||||||
|
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||||
|
}
|
||||||
|
|
||||||
res = trx.begin();
|
int res = trx.begin();
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
|
Loading…
Reference in New Issue