1
0
Fork 0

Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
Jan Steemann 2016-03-01 11:14:55 +01:00
commit 21e5e68ae5
3 changed files with 161 additions and 121 deletions

View File

@ -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() +

View File

@ -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);
} }

View File

@ -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);