1
0
Fork 0

implemented local insert method

This commit is contained in:
Jan Steemann 2016-02-16 18:32:50 +01:00
parent a75814264c
commit 0511a944ad
4 changed files with 144 additions and 14 deletions

View File

@ -26,14 +26,16 @@
#include "Basics/Common.h"
#include <velocypack/Builder.h>
#include <velocypack/Buffer.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
namespace arangodb {
struct OperationResult {
OperationResult() : builder(), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {}
OperationResult() : buffer(), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {}
explicit OperationResult(int code) : buffer(), code(code), wasSynchronous(false) {}
OperationResult(int code, std::shared_ptr<VPackBuffer<uint8_t>> buffer) : buffer(buffer), code(code), wasSynchronous(false) {}
bool successful() const {
return code == TRI_ERROR_NO_ERROR;
@ -44,11 +46,11 @@ struct OperationResult {
}
VPackSlice slice() const {
TRI_ASSERT(builder != nullptr);
return builder->slice();
TRI_ASSERT(buffer != nullptr);
return VPackSlice(buffer->data());
}
std::shared_ptr<VPackBuilder> builder;
std::shared_ptr<VPackBuffer<uint8_t>> buffer;
int code;
bool wasSynchronous;
};

View File

@ -23,6 +23,13 @@
#include "Utils/transactions.h"
#include "Indexes/PrimaryIndex.h"
#include "Storage/Marker.h"
#include "VocBase/KeyGenerator.h"
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
@ -406,3 +413,122 @@ int Transaction::readSlice(TRI_transaction_collection_t* trxCollection,
return TRI_ERROR_NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief create one or multiple documents in a collection
/// the single-document variant of this operation will either succeed or,
/// if it fails, clean up after itself
//////////////////////////////////////////////////////////////////////////////
OperationResult Transaction::insert(std::string const& collectionName,
VPackSlice const& value,
OperationOptions const& options) {
TRI_ASSERT(getStatus() == TRI_TRANSACTION_RUNNING);
if (!value.isObject() && !value.isArray()) {
// must provide a document object or an array of documents
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);
}
if (ServerState::instance()->isCoordinator()) {
return insertCoordinator(collectionName, value, options);
}
return insertLocal(collectionName, value, options);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief create one or multiple documents in a collection, coordinator
/// the single-document variant of this operation will either succeed or,
/// if it fails, clean up after itself
/// TODO: implement this
//////////////////////////////////////////////////////////////////////////////
OperationResult Transaction::insertCoordinator(std::string const& collectionName,
VPackSlice const& value,
OperationOptions const& options) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief create one or multiple documents in a collection, local
/// the single-document variant of this operation will either succeed or,
/// if it fails, clean up after itself
//////////////////////////////////////////////////////////////////////////////
OperationResult Transaction::insertLocal(std::string const& collectionName,
VPackSlice const& value,
OperationOptions const& options) {
TRI_voc_cid_t cid = resolver()->getCollectionId(collectionName);
if (cid == 0) {
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
// TODO: clean this up
TRI_document_collection_t* document = documentCollection(trxCollection(cid));
// add missing attributes for document (_id, _rev, _key)
VPackBuilder merge;
merge.openObject();
// generate a new tick value
TRI_voc_tick_t const tick = TRI_NewTickServer();
auto key = value.get(TRI_VOC_ATTRIBUTE_KEY);
if (key.isNone()) {
// "_key" attribute not present in object
merge.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(document->_keyGenerator->generate(tick)));
} else if (!key.isString()) {
// "_key" present but wrong type
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
} else {
int res = document->_keyGenerator->validate(key.copyString(), 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(tick)));
// 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_copy_t mptr;
int res = document->insert(this, &insertSlice, &mptr, !isLocked(document, TRI_TRANSACTION_WRITE), options.waitForSync);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
}
TRI_ASSERT(mptr.getDataPtr() != nullptr);
VPackSlice vpack(mptr.vpack());
std::string resultKey = VPackSlice(mptr.vpack()).get(TRI_VOC_ATTRIBUTE_KEY).copyString();
VPackBuilder builder;
builder.openObject();
builder.add(TRI_VOC_ATTRIBUTE_ID, VPackValue(std::string(collectionName + "/" + resultKey)));
builder.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(vpack.get(TRI_VOC_ATTRIBUTE_REV).copyString()));
builder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(resultKey));
builder.close();
return OperationResult(TRI_ERROR_NO_ERROR, builder.steal());
}

View File

@ -425,7 +425,6 @@ class Transaction {
/// @brief create one or multiple documents in a collection
/// the single-document variant of this operation will either succeed or,
/// if it fails, clean up after itself
/// TODO: implement this
//////////////////////////////////////////////////////////////////////////////
OperationResult insert(std::string const& collectionName,
@ -738,6 +737,16 @@ class Transaction {
int setupState() { return _setupState; }
private:
OperationResult insertCoordinator(std::string const& collectionName,
VPackSlice const& value,
OperationOptions const& options);
OperationResult insertLocal(std::string const& collectionName,
VPackSlice const& value,
OperationOptions const& options);
protected:
//////////////////////////////////////////////////////////////////////////////
/// @brief return the collection

View File

@ -3270,13 +3270,6 @@ static void JS_InsertVocbaseVPack(
options.waitForSync = ExtractWaitForSync(args, 2);
}
// requirements for insert:
// - must check input value type
//res = document->insert(&trx, &slice, &mptr,
// !trx.isLocked(document, TRI_TRANSACTION_WRITE),
// options.waitForSync);
// res = trx.finish(res);
if (!args[0]->IsObject() || args[0]->IsArray()) {
// invalid value type. must be a document
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
@ -3285,7 +3278,7 @@ static void JS_InsertVocbaseVPack(
VPackOptions const* vpackOptions = StorageOptions::getInsertOptions();
VPackBuilder builder(vpackOptions);
int res = TRI_V8ToVPack(isolate, builder, args[0]->ToObject(), true);
int res = TRI_V8ToVPack(isolate, builder, args[0]->ToObject(), false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);