mirror of https://gitee.com/bigwinds/arangodb
implemented local insert method
This commit is contained in:
parent
a75814264c
commit
0511a944ad
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue