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) {
|
||||
|
||||
VPackSlice slice = result.slice();
|
||||
TRI_ASSERT(slice.isObject());
|
||||
TRI_ASSERT(slice.isObject() || slice.isArray());
|
||||
_response->setContentType("application/json; charset=utf-8");
|
||||
_response->setHeader("etag", 4, "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
||||
|
||||
std::string escapedHandle(DocumentHelper::assembleDocumentId(
|
||||
collectionName, slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString(), true));
|
||||
if (_request->compatibility() < 10400L) {
|
||||
// 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 (slice.isObject()) {
|
||||
_response->setHeader("etag", 4, "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
||||
// pre 1.4 location headers withdrawn for >= 3.0
|
||||
std::string escapedHandle(DocumentHelper::assembleDocumentId(
|
||||
collectionName, slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString(), true));
|
||||
if (type == TRI_COL_TYPE_EDGE) {
|
||||
_response->setHeader("location", 8,
|
||||
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);
|
||||
}
|
||||
|
||||
if (value.isArray()) {
|
||||
// multi-document variant is not yet implemented
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
// Validate Edges
|
||||
if (isEdgeCollection(collectionName)) {
|
||||
// Check _from
|
||||
size_t split;
|
||||
VPackSlice from = value.get(TRI_VOC_ATTRIBUTE_FROM);
|
||||
if (!from.isString()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||
}
|
||||
std::string docId = from.copyString();
|
||||
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)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||
}
|
||||
auto checkFrom = [&](VPackSlice const value) -> void {
|
||||
size_t split;
|
||||
VPackSlice from = value.get(TRI_VOC_ATTRIBUTE_FROM);
|
||||
if (!from.isString()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||
}
|
||||
std::string docId = from.copyString();
|
||||
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)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
// Check _to
|
||||
VPackSlice to = value.get(TRI_VOC_ATTRIBUTE_TO);
|
||||
if (!to.isString()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||
}
|
||||
docId = to.copyString();
|
||||
if (!TRI_ValidateDocumentIdKeyGenerator(docId.c_str(), &split)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||
}
|
||||
cName = docId.substr(0, split);
|
||||
if (TRI_COL_TYPE_UNKNOWN == resolver()->getCollectionType(cName)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||
auto checkTo = [&](VPackSlice const value) -> void {
|
||||
size_t split;
|
||||
VPackSlice to = value.get(TRI_VOC_ATTRIBUTE_TO);
|
||||
if (!to.isString()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE);
|
||||
}
|
||||
std::string docId = to.copyString();
|
||||
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)) {
|
||||
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,
|
||||
VPackSlice const& value,
|
||||
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;
|
||||
arangodb::rest::HttpResponse::HttpResponseCode responseCode;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1886,7 +1886,7 @@ static void JS_InsertVocbaseVPack(
|
|||
options.waitForSync = ExtractWaitForSync(args, optsIdx + 1);
|
||||
}
|
||||
|
||||
if (!args[docIdx]->IsObject() || args[docIdx]->IsArray()) {
|
||||
if (!args[docIdx]->IsObject()) {
|
||||
// invalid value type. must be a document
|
||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
|
||||
}
|
||||
|
@ -1895,37 +1895,53 @@ static void JS_InsertVocbaseVPack(
|
|||
VPackOptions vpackOptions = VPackOptions::Defaults;
|
||||
vpackOptions.attributeExcludeHandler = basics::VelocyPackHelper::getExcludeHandler();
|
||||
VPackBuilder builder(&vpackOptions);
|
||||
v8::Handle<v8::Value> payload = args[0];
|
||||
|
||||
int res = TRI_V8ToVPack(isolate, builder, args[docIdx]->ToObject(), true);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
if (isEdgeCollection) {
|
||||
// Just insert from and to. Check is done later.
|
||||
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
|
||||
auto transactionContext = std::make_shared<V8TransactionContext>(collection->_vocbase, true);
|
||||
|
||||
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) {
|
||||
TRI_V8_THROW_EXCEPTION(res);
|
||||
|
|
Loading…
Reference in New Issue