mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
fb1d69bbae
|
@ -234,15 +234,21 @@ AstNode* Ast::createNodeInsert (AstNode const* expression,
|
|||
AstNode* Ast::createNodeUpdate (AstNode const* keyExpression,
|
||||
AstNode const* docExpression,
|
||||
AstNode const* collection,
|
||||
AstNode* options) {
|
||||
AstNode const* options) {
|
||||
AstNode* node = createNode(NODE_TYPE_UPDATE);
|
||||
|
||||
if (options == nullptr) {
|
||||
// no options given. now use default options
|
||||
options = &NopNode;
|
||||
}
|
||||
|
||||
node->addMember(options);
|
||||
node->addMember(collection);
|
||||
node->addMember(docExpression);
|
||||
|
||||
if (keyExpression != nullptr) {
|
||||
node->addMember(keyExpression);
|
||||
}
|
||||
// TODO: handle options
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -254,15 +260,21 @@ AstNode* Ast::createNodeUpdate (AstNode const* keyExpression,
|
|||
AstNode* Ast::createNodeReplace (AstNode const* keyExpression,
|
||||
AstNode const* docExpression,
|
||||
AstNode const* collection,
|
||||
AstNode* options) {
|
||||
AstNode const* options) {
|
||||
AstNode* node = createNode(NODE_TYPE_REPLACE);
|
||||
|
||||
if (options == nullptr) {
|
||||
// no options given. now use default options
|
||||
options = &NopNode;
|
||||
}
|
||||
|
||||
node->addMember(options);
|
||||
node->addMember(collection);
|
||||
node->addMember(docExpression);
|
||||
|
||||
if (keyExpression != nullptr) {
|
||||
node->addMember(keyExpression);
|
||||
}
|
||||
// TODO: handle options
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ namespace triagens {
|
|||
AstNode* createNodeUpdate (AstNode const*,
|
||||
AstNode const*,
|
||||
AstNode const*,
|
||||
AstNode*);
|
||||
AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST replace node
|
||||
|
@ -271,7 +271,7 @@ namespace triagens {
|
|||
AstNode* createNodeReplace (AstNode const*,
|
||||
AstNode const*,
|
||||
AstNode const*,
|
||||
AstNode*);
|
||||
AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST collect node
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/json-utilities.h"
|
||||
#include "Utils/Exception.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
|
@ -1877,25 +1878,25 @@ AqlItemBlock* ReturnBlock::getSome (size_t atLeast,
|
|||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class RemoveBlock
|
||||
// --SECTION-- class ModificationBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
RemoveBlock::RemoveBlock (AQL_TRANSACTION_V8* trx,
|
||||
RemoveNode const* ep)
|
||||
ModificationBlock::ModificationBlock (AQL_TRANSACTION_V8* trx,
|
||||
ModificationNode const* ep)
|
||||
: ExecutionBlock(trx, ep),
|
||||
_collection(ep->_collection) {
|
||||
}
|
||||
|
||||
|
||||
RemoveBlock::~RemoveBlock () {
|
||||
ModificationBlock::~ModificationBlock () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get some - this accumulates all input and calls the remove() method
|
||||
/// @brief get some - this accumulates all input and calls the work() method
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlItemBlock* RemoveBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
AqlItemBlock* ModificationBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
|
||||
std::vector<AqlItemBlock*> blocks;
|
||||
|
||||
|
@ -1919,7 +1920,7 @@ AqlItemBlock* RemoveBlock::getSome (size_t atLeast,
|
|||
blocks.push_back(res);
|
||||
}
|
||||
|
||||
remove(blocks);
|
||||
work(blocks);
|
||||
freeBlocks(blocks);
|
||||
|
||||
return nullptr;
|
||||
|
@ -1930,11 +1931,73 @@ AqlItemBlock* RemoveBlock::getSome (size_t atLeast,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resolve a collection name and return cid and document key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int ModificationBlock::resolve (char const* handle,
|
||||
TRI_voc_cid_t& cid,
|
||||
std::string& key) const {
|
||||
char const* p = strchr(handle, TRI_DOCUMENT_HANDLE_SEPARATOR_CHR);
|
||||
if (p == nullptr || *p == '\0') {
|
||||
return TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD;
|
||||
}
|
||||
|
||||
if (*handle >= '0' && *handle <= '9') {
|
||||
cid = triagens::basics::StringUtils::uint64(handle, p - handle);
|
||||
}
|
||||
else {
|
||||
std::string const name(handle, p - handle);
|
||||
cid = _trx->resolver()->getCollectionIdCluster(name);
|
||||
}
|
||||
|
||||
if (cid == 0) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
key = std::string(p + 1);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract a key from the AqlValue passed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int ModificationBlock::extractKey (AqlValue const& value,
|
||||
TRI_document_collection_t const* document,
|
||||
std::string& key) const {
|
||||
Json member(value.extractArrayMember(_trx, document, TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
// TODO: allow _id, too
|
||||
|
||||
TRI_json_t const* json = member.json();
|
||||
if (TRI_IsStringJson(json)) {
|
||||
key = std::string(json->_value._string.data, json->_value._string.length - 1);
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
return TRI_ERROR_ARANGO_DOCUMENT_KEY_MISSING;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class RemoveBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
RemoveBlock::RemoveBlock (AQL_TRANSACTION_V8* trx,
|
||||
RemoveNode const* ep)
|
||||
: ModificationBlock(trx, ep) {
|
||||
}
|
||||
|
||||
|
||||
RemoveBlock::~RemoveBlock () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for removing data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RemoveBlock::remove (std::vector<AqlItemBlock*>& blocks) {
|
||||
void RemoveBlock::work (std::vector<AqlItemBlock*>& blocks) {
|
||||
auto ep = static_cast<RemoveNode const*>(getPlanNode());
|
||||
auto it = _varOverview->varInfo.find(ep->_inVariable->id);
|
||||
TRI_ASSERT(it != _varOverview->varInfo.end());
|
||||
|
@ -1949,27 +2012,19 @@ void RemoveBlock::remove (std::vector<AqlItemBlock*>& blocks) {
|
|||
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
auto res = (*it);
|
||||
auto document = res->getDocumentCollection(registerId);
|
||||
|
||||
|
||||
size_t const n = res->size();
|
||||
|
||||
// loop over the complete block
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue a = res->getValue(i, registerId);
|
||||
|
||||
char const* key = nullptr;
|
||||
std::string key;
|
||||
int errorCode = TRI_ERROR_NO_ERROR;
|
||||
|
||||
if (a.isArray()) {
|
||||
// value is an array. now extract the _key attribute
|
||||
Json member(a.extractArrayMember(_trx, document, "_key"));
|
||||
|
||||
TRI_json_t const* json = member.json();
|
||||
if (TRI_IsStringJson(json)) {
|
||||
key = json->_value._string.data;
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_ARANGO_DOCUMENT_KEY_MISSING;
|
||||
}
|
||||
errorCode = extractKey(a, document, key);
|
||||
}
|
||||
else if (a.isString()) {
|
||||
// value is a string
|
||||
|
@ -1981,10 +2036,10 @@ void RemoveBlock::remove (std::vector<AqlItemBlock*>& blocks) {
|
|||
|
||||
if (errorCode == TRI_ERROR_NO_ERROR) {
|
||||
// no error. we expect to have a key
|
||||
TRI_ASSERT(key != nullptr);
|
||||
|
||||
|
||||
// all exceptions are caught in _trx->remove()
|
||||
errorCode = _trx->remove(trxCollection,
|
||||
std::string(key),
|
||||
key,
|
||||
0,
|
||||
TRI_DOC_UPDATE_LAST_WRITE,
|
||||
0,
|
||||
|
@ -2013,59 +2068,17 @@ void RemoveBlock::remove (std::vector<AqlItemBlock*>& blocks) {
|
|||
|
||||
InsertBlock::InsertBlock (AQL_TRANSACTION_V8* trx,
|
||||
InsertNode const* ep)
|
||||
: ExecutionBlock(trx, ep),
|
||||
_collection(ep->_collection) {
|
||||
: ModificationBlock(trx, ep) {
|
||||
}
|
||||
|
||||
|
||||
InsertBlock::~InsertBlock () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get some - this accumulates all input and calls the insert() method
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlItemBlock* InsertBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
|
||||
std::vector<AqlItemBlock*> blocks;
|
||||
|
||||
auto freeBlocks = [](std::vector<AqlItemBlock*>& blocks) {
|
||||
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
if ((*it) != nullptr) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// loop over input until it is exhausted
|
||||
try {
|
||||
while (true) {
|
||||
auto res = ExecutionBlock::getSome(atLeast, atMost);
|
||||
|
||||
if (res == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
blocks.push_back(res);
|
||||
}
|
||||
|
||||
insert(blocks);
|
||||
freeBlocks(blocks);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
catch (...) {
|
||||
freeBlocks(blocks);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for inserting data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
||||
void InsertBlock::work (std::vector<AqlItemBlock*>& blocks) {
|
||||
auto ep = static_cast<InsertNode const*>(getPlanNode());
|
||||
auto it = _varOverview->varInfo.find(ep->_inVariable->id);
|
||||
TRI_ASSERT(it != _varOverview->varInfo.end());
|
||||
|
@ -2075,30 +2088,6 @@ void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
|||
|
||||
bool const isEdgeCollection = _collection->isEdgeCollection();
|
||||
|
||||
auto resolve = [&](char const* handle, TRI_voc_cid_t& cid, std::string& key) -> int {
|
||||
char const* p = strchr(handle, TRI_DOCUMENT_HANDLE_SEPARATOR_CHR);
|
||||
if (p == nullptr || *p == '\0') {
|
||||
return TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD;
|
||||
}
|
||||
|
||||
if (*handle >= '0' && *handle <= '9') {
|
||||
cid = triagens::basics::StringUtils::uint64(handle, p - handle);
|
||||
}
|
||||
else {
|
||||
std::string const name(handle, p - handle);
|
||||
cid = _trx->resolver()->getCollectionIdCluster(name);
|
||||
}
|
||||
|
||||
if (cid == 0) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
key = std::string(p + 1);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
};
|
||||
|
||||
|
||||
if (ep->_outVariable == nullptr) {
|
||||
// don't return anything
|
||||
|
||||
|
@ -2116,7 +2105,7 @@ void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
|||
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
auto res = (*it);
|
||||
auto document = res->getDocumentCollection(registerId);
|
||||
|
||||
|
||||
size_t const n = res->size();
|
||||
|
||||
// loop over the complete block
|
||||
|
@ -2129,10 +2118,10 @@ void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
|||
// value is an array
|
||||
|
||||
if (isEdgeCollection) {
|
||||
// array must have "_from" and "_to"
|
||||
// array must have _from and _to attributes
|
||||
TRI_json_t const* json;
|
||||
|
||||
Json member(a.extractArrayMember(_trx, document, "_from"));
|
||||
Json member(a.extractArrayMember(_trx, document, TRI_VOC_ATTRIBUTE_FROM));
|
||||
json = member.json();
|
||||
|
||||
if (TRI_IsStringJson(json)) {
|
||||
|
@ -2143,7 +2132,7 @@ void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
|||
}
|
||||
|
||||
if (errorCode == TRI_ERROR_NO_ERROR) {
|
||||
Json member(a.extractArrayMember(_trx, document, "_to"));
|
||||
Json member(a.extractArrayMember(_trx, document, TRI_VOC_ATTRIBUTE_TO));
|
||||
json = member.json();
|
||||
if (TRI_IsStringJson(json)) {
|
||||
errorCode = resolve(json->_value._string.data, edge._toCid, to);
|
||||
|
@ -2188,6 +2177,177 @@ void InsertBlock::insert (std::vector<AqlItemBlock*>& blocks) {
|
|||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class UpdateBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
UpdateBlock::UpdateBlock (AQL_TRANSACTION_V8* trx,
|
||||
UpdateNode const* ep)
|
||||
: ModificationBlock(trx, ep) {
|
||||
}
|
||||
|
||||
UpdateBlock::~UpdateBlock () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for inserting data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UpdateBlock::work (std::vector<AqlItemBlock*>& blocks) {
|
||||
auto ep = static_cast<UpdateNode const*>(getPlanNode());
|
||||
auto it = _varOverview->varInfo.find(ep->_inVariable->id);
|
||||
TRI_ASSERT(it != _varOverview->varInfo.end());
|
||||
RegisterId const registerId = it->second.registerId;
|
||||
|
||||
auto trxCollection = _trx->trxCollection(_collection->cid());
|
||||
|
||||
if (ep->_outVariable == nullptr) {
|
||||
// don't return anything
|
||||
|
||||
// loop over all blocks
|
||||
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
auto res = (*it);
|
||||
auto document = res->getDocumentCollection(registerId);
|
||||
|
||||
size_t const n = res->size();
|
||||
|
||||
// loop over the complete block
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue a = res->getValue(i, registerId);
|
||||
|
||||
int errorCode = TRI_ERROR_NO_ERROR;
|
||||
std::string key;
|
||||
|
||||
if (a.isArray()) {
|
||||
// value is an array. now extract the _key attribute
|
||||
errorCode = extractKey(a, document, key);
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
if (errorCode == TRI_ERROR_NO_ERROR) {
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
auto json = a.toJson(_trx, document);
|
||||
|
||||
// read old document
|
||||
TRI_doc_mptr_copy_t oldDocument;
|
||||
errorCode = _trx->readSingle(trxCollection, &oldDocument, key);
|
||||
|
||||
if (errorCode == TRI_ERROR_NO_ERROR) {
|
||||
if (oldDocument.getDataPtr() != nullptr) {
|
||||
TRI_shaped_json_t shapedJson;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, oldDocument.getDataPtr()); // PROTECTED by trx here
|
||||
TRI_json_t* old = TRI_JsonShapedJson(_collection->documentCollection()->getShaper(), &shapedJson);
|
||||
|
||||
if (old != nullptr) {
|
||||
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json.json(), ep->_options.nullMeansRemove);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, old);
|
||||
|
||||
if (patchedJson != nullptr) {
|
||||
// all exceptions are caught in _trx->update()
|
||||
errorCode = _trx->update(trxCollection, key, 0, &mptr, patchedJson, TRI_DOC_UPDATE_LAST_WRITE, 0, nullptr, ep->_options.waitForSync);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, patchedJson);
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errorCode != TRI_ERROR_NO_ERROR &&
|
||||
! ep->_options.ignoreErrors) {
|
||||
THROW_ARANGO_EXCEPTION(errorCode);
|
||||
}
|
||||
}
|
||||
// done with a block
|
||||
|
||||
// now free it already
|
||||
(*it) = nullptr;
|
||||
delete res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ReplaceBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ReplaceBlock::ReplaceBlock (AQL_TRANSACTION_V8* trx,
|
||||
ReplaceNode const* ep)
|
||||
: ModificationBlock(trx, ep) {
|
||||
}
|
||||
|
||||
ReplaceBlock::~ReplaceBlock () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for replacing data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ReplaceBlock::work (std::vector<AqlItemBlock*>& blocks) {
|
||||
auto ep = static_cast<ReplaceNode const*>(getPlanNode());
|
||||
auto it = _varOverview->varInfo.find(ep->_inVariable->id);
|
||||
TRI_ASSERT(it != _varOverview->varInfo.end());
|
||||
RegisterId const registerId = it->second.registerId;
|
||||
|
||||
auto trxCollection = _trx->trxCollection(_collection->cid());
|
||||
|
||||
if (ep->_outVariable == nullptr) {
|
||||
// don't return anything
|
||||
|
||||
// loop over all blocks
|
||||
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
auto res = (*it);
|
||||
auto document = res->getDocumentCollection(registerId);
|
||||
|
||||
size_t const n = res->size();
|
||||
|
||||
// loop over the complete block
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue a = res->getValue(i, registerId);
|
||||
|
||||
int errorCode = TRI_ERROR_NO_ERROR;
|
||||
std::string key;
|
||||
|
||||
if (a.isArray()) {
|
||||
// value is an array. now extract the _key attribute
|
||||
errorCode = extractKey(a, document, key);
|
||||
}
|
||||
else {
|
||||
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
if (errorCode == TRI_ERROR_NO_ERROR) {
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
auto json = a.toJson(_trx, document);
|
||||
|
||||
// all exceptions are caught in _trx->update()
|
||||
errorCode = _trx->update(trxCollection, key, 0, &mptr, json.json(), TRI_DOC_UPDATE_LAST_WRITE, 0, nullptr, ep->_options.waitForSync);
|
||||
}
|
||||
|
||||
if (errorCode != TRI_ERROR_NO_ERROR &&
|
||||
! ep->_options.ignoreErrors) {
|
||||
THROW_ARANGO_EXCEPTION(errorCode);
|
||||
}
|
||||
}
|
||||
// done with a block
|
||||
|
||||
// now free it already
|
||||
(*it) = nullptr;
|
||||
delete res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct ExecutionBlock::VarOverview
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -1031,11 +1031,81 @@ namespace triagens {
|
|||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ModificationBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class ModificationBlock : public ExecutionBlock {
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ModificationBlock (AQL_TRANSACTION_V8*, ModificationNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ~ModificationBlock ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSome
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual AqlItemBlock* getSome (size_t atLeast,
|
||||
size_t atMost);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void work (std::vector<AqlItemBlock*>&) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resolve a collection name and return cid and document key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int resolve (char const*,
|
||||
TRI_voc_cid_t&,
|
||||
std::string&) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract a key from the AqlValue passed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int extractKey (AqlValue const&,
|
||||
TRI_document_collection_t const*,
|
||||
std::string&) const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Collection* _collection;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- RemoveBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class RemoveBlock : public ExecutionBlock {
|
||||
class RemoveBlock : public ModificationBlock {
|
||||
|
||||
public:
|
||||
|
||||
|
@ -1051,36 +1121,17 @@ namespace triagens {
|
|||
|
||||
~RemoveBlock ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSome
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual AqlItemBlock* getSome (size_t atLeast,
|
||||
size_t atMost);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for removing data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void remove (std::vector<AqlItemBlock*>&);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Collection* _collection;
|
||||
void work (std::vector<AqlItemBlock*>&);
|
||||
|
||||
};
|
||||
|
||||
|
@ -1088,7 +1139,7 @@ namespace triagens {
|
|||
// --SECTION-- InsertBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class InsertBlock : public ExecutionBlock {
|
||||
class InsertBlock : public ModificationBlock {
|
||||
|
||||
public:
|
||||
|
||||
|
@ -1104,36 +1155,85 @@ namespace triagens {
|
|||
|
||||
~InsertBlock ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSome
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual AqlItemBlock* getSome (size_t atLeast,
|
||||
size_t atMost);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for inserting data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void insert (std::vector<AqlItemBlock*>&);
|
||||
void work (std::vector<AqlItemBlock*>&);
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// --SECTION-- UpdateBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
class UpdateBlock : public ModificationBlock {
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Collection* _collection;
|
||||
UpdateBlock (AQL_TRANSACTION_V8* trx, UpdateNode const* ep);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~UpdateBlock ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for updating data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void work (std::vector<AqlItemBlock*>&);
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ReplaceBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class ReplaceBlock : public ModificationBlock {
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ReplaceBlock (AQL_TRANSACTION_V8* trx, ReplaceNode const* ep);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~ReplaceBlock ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual work horse for replacing data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void work (std::vector<AqlItemBlock*>&);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -159,6 +159,20 @@ struct Instanciator : public WalkerWorker<ExecutionNode> {
|
|||
root = eb;
|
||||
break;
|
||||
}
|
||||
case ExecutionNode::UPDATE: {
|
||||
eb = new UpdateBlock(engine->getTransaction(),
|
||||
static_cast<UpdateNode const*>(en));
|
||||
|
||||
root = eb;
|
||||
break;
|
||||
}
|
||||
case ExecutionNode::REPLACE: {
|
||||
eb = new ReplaceBlock(engine->getTransaction(),
|
||||
static_cast<ReplaceNode const*>(en));
|
||||
|
||||
root = eb;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
|
|
|
@ -294,7 +294,7 @@ void IndexRangeNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
|
||||
// put together the range info . . .
|
||||
Json ranges(Json::List);
|
||||
|
||||
/*
|
||||
for (auto x : *_ranges) {
|
||||
Json item(Json::Array);
|
||||
item("name", Json(x._name))
|
||||
|
@ -304,7 +304,7 @@ void IndexRangeNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
("highOpen", Json(x._highOpen));
|
||||
ranges(item);
|
||||
}
|
||||
|
||||
*/
|
||||
// Now put info about vocbase and cid in there
|
||||
json("database", Json(_vocbase->_name))
|
||||
("collection", Json(_collection->name))
|
||||
|
@ -594,8 +594,13 @@ void UpdateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
|
||||
// Now put info about vocbase and cid in there
|
||||
json("database", Json(_vocbase->_name))
|
||||
("collection", Json(_collname))
|
||||
("outVariable", _outVariable->toJson());
|
||||
("collection", Json(_collection->name))
|
||||
("inVariable", _inVariable->toJson());
|
||||
|
||||
// output variable might be empty
|
||||
if (_outVariable != nullptr) {
|
||||
json("outVariable", _outVariable->toJson());
|
||||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -622,8 +627,13 @@ void ReplaceNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
|
||||
// Now put info about vocbase and cid in there
|
||||
json("database", Json(_vocbase->_name))
|
||||
("collection", Json(_collname))
|
||||
("outVariable", _outVariable->toJson());
|
||||
("collection", Json(_collection->name))
|
||||
("inVariable", _inVariable->toJson());
|
||||
|
||||
// output variable might be empty
|
||||
if (_outVariable != nullptr) {
|
||||
json("outVariable", _outVariable->toJson());
|
||||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
|
|
@ -1455,6 +1455,7 @@ namespace triagens {
|
|||
class ModificationNode : public ExecutionNode {
|
||||
|
||||
friend class ExecutionBlock;
|
||||
friend class ModificationBlock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor with a vocbase and a collection and options
|
||||
|
@ -1728,7 +1729,7 @@ namespace triagens {
|
|||
/// @brief class UpdateNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class UpdateNode : public ExecutionNode {
|
||||
class UpdateNode : public ModificationNode {
|
||||
|
||||
friend class ExecutionBlock;
|
||||
friend class UpdateBlock;
|
||||
|
@ -1740,13 +1741,16 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
UpdateNode (TRI_vocbase_t* vocbase,
|
||||
std::string collname,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ExecutionNode(), _vocbase(vocbase), _collname(collname),
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
_inVariable(inVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1770,7 +1774,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new UpdateNode(_vocbase, _collname, _outVariable);
|
||||
auto c = new UpdateNode(_vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1784,6 +1788,28 @@ namespace triagens {
|
|||
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1791,16 +1817,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _vocbase, the database
|
||||
/// @brief input variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_t* _vocbase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _collname, the collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _collname;
|
||||
Variable const* _inVariable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief output variable
|
||||
|
@ -1818,7 +1838,7 @@ namespace triagens {
|
|||
/// @brief class ReplaceNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ReplaceNode : public ExecutionNode {
|
||||
class ReplaceNode : public ModificationNode {
|
||||
|
||||
friend class ExecutionBlock;
|
||||
friend class ReplaceBlock;
|
||||
|
@ -1830,13 +1850,16 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
ReplaceNode (TRI_vocbase_t* vocbase,
|
||||
std::string collname,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ExecutionNode(), _vocbase(vocbase), _collname(collname),
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
_inVariable(inVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1860,7 +1883,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new UpdateNode(_vocbase, _collname, _outVariable);
|
||||
auto c = new ReplaceNode(_vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1874,6 +1897,28 @@ namespace triagens {
|
|||
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1881,16 +1926,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _vocbase, the database
|
||||
/// @brief input variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_t* _vocbase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _collname, the collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _collname;
|
||||
Variable const* _inVariable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief output variable
|
||||
|
|
|
@ -120,7 +120,6 @@ ModificationOptions ExecutionPlan::createOptions (AstNode const* node) {
|
|||
auto name = member->getStringValue();
|
||||
auto value = member->getMember(0);
|
||||
|
||||
std::cout << "VALUE: " << value->typeString() << "\n";
|
||||
TRI_ASSERT(value->isConstant());
|
||||
|
||||
if (strcmp(name, "waitForSync") == 0) {
|
||||
|
@ -129,6 +128,10 @@ std::cout << "VALUE: " << value->typeString() << "\n";
|
|||
else if (strcmp(name, "ignoreErrors") == 0) {
|
||||
options.ignoreErrors = value->toBoolean();
|
||||
}
|
||||
else if (strcmp(name, "keepNull") == 0) {
|
||||
// nullMeansRemove is the opposite of keepNull
|
||||
options.nullMeansRemove = (! value->toBoolean());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -597,26 +600,27 @@ ExecutionNode* ExecutionPlan::fromNodeUpdate (Ast const* ast,
|
|||
ExecutionNode* previous,
|
||||
AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_UPDATE);
|
||||
TRI_ASSERT(node->numMembers() >= 2);
|
||||
TRI_ASSERT(node->numMembers() >= 3);
|
||||
|
||||
auto collection = node->getMember(0);
|
||||
auto expression = node->getMember(1);
|
||||
|
||||
// collection, expression
|
||||
char const* collectionName = collection->getStringValue();
|
||||
auto options = createOptions(node->getMember(0));
|
||||
char const* collectionName = node->getMember(1)->getStringValue();
|
||||
auto collections = ast->query()->collections();
|
||||
auto collection = collections->get(collectionName);
|
||||
auto expression = node->getMember(2);
|
||||
// auto keyExpression = node->getMember(3);
|
||||
ExecutionNode* en = nullptr;
|
||||
|
||||
if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), std::string(collectionName), v));
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable()));
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -631,26 +635,27 @@ ExecutionNode* ExecutionPlan::fromNodeReplace (Ast const* ast,
|
|||
ExecutionNode* previous,
|
||||
AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REPLACE);
|
||||
TRI_ASSERT(node->numMembers() >= 2);
|
||||
TRI_ASSERT(node->numMembers() >= 3);
|
||||
|
||||
auto collection = node->getMember(0);
|
||||
auto expression = node->getMember(1);
|
||||
|
||||
// collection, expression
|
||||
char const* collectionName = collection->getStringValue();
|
||||
auto options = createOptions(node->getMember(0));
|
||||
char const* collectionName = node->getMember(1)->getStringValue();
|
||||
auto collections = ast->query()->collections();
|
||||
auto collection = collections->get(collectionName);
|
||||
auto expression = node->getMember(2);
|
||||
// auto keyExpression = node->getMember(3);
|
||||
ExecutionNode* en = nullptr;
|
||||
|
||||
|
||||
if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), std::string(collectionName), v));
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), std::string(collectionName), calc->outVariable()));
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -723,13 +728,11 @@ ExecutionNode* ExecutionPlan::fromNode (Ast const* ast,
|
|||
}
|
||||
|
||||
case NODE_TYPE_UPDATE: {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
en = fromNodeUpdate(ast, en, member);
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_TYPE_REPLACE: {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
en = fromNodeReplace(ast, en, member);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ namespace triagens {
|
|||
|
||||
ModificationOptions ()
|
||||
: ignoreErrors(false),
|
||||
waitForSync(false) {
|
||||
waitForSync(false),
|
||||
nullMeansRemove(false) {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -58,6 +59,7 @@ namespace triagens {
|
|||
|
||||
bool ignoreErrors;
|
||||
bool waitForSync;
|
||||
bool nullMeansRemove;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -637,8 +637,8 @@ namespace triagens {
|
|||
|
||||
#define YY_INPUT(resultBuffer, resultState, maxBytesToRead) { \
|
||||
size_t length = yyextra->remainingLength(); \
|
||||
if (length > maxBytesToRead) { \
|
||||
length = maxBytesToRead; \
|
||||
if (length > static_cast<size_t>(maxBytesToRead)) { \
|
||||
length = static_cast<size_t>(maxBytesToRead); \
|
||||
} \
|
||||
if (length > 0) { \
|
||||
yyextra->fillBuffer(resultBuffer, length); \
|
||||
|
|
|
@ -38,8 +38,8 @@ namespace triagens {
|
|||
|
||||
#define YY_INPUT(resultBuffer, resultState, maxBytesToRead) { \
|
||||
size_t length = yyextra->remainingLength(); \
|
||||
if (length > maxBytesToRead) { \
|
||||
length = maxBytesToRead; \
|
||||
if (length > static_cast<size_t>(maxBytesToRead)) { \
|
||||
length = static_cast<size_t>(maxBytesToRead); \
|
||||
} \
|
||||
if (length > 0) { \
|
||||
yyextra->fillBuffer(resultBuffer, length); \
|
||||
|
|
|
@ -495,6 +495,74 @@ namespace triagens {
|
|||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update a single document, using JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int update (TRI_transaction_collection_t* trxCollection,
|
||||
std::string const& key,
|
||||
TRI_voc_rid_t rid,
|
||||
TRI_doc_mptr_copy_t* mptr,
|
||||
TRI_json_t* const json,
|
||||
TRI_doc_update_policy_e policy,
|
||||
TRI_voc_rid_t expectedRevision,
|
||||
TRI_voc_rid_t* actualRevision,
|
||||
bool forceSync) {
|
||||
|
||||
TRI_shaper_t* shaper = this->shaper(trxCollection);
|
||||
TRI_memory_zone_t* zone = shaper->_memoryZone;
|
||||
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json, true, isLocked(trxCollection, TRI_TRANSACTION_WRITE));
|
||||
|
||||
if (shaped == nullptr) {
|
||||
return TRI_ERROR_ARANGO_SHAPER_FAILED;
|
||||
}
|
||||
|
||||
if (orderBarrier(trxCollection) == nullptr) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int res = update(trxCollection,
|
||||
key,
|
||||
rid,
|
||||
mptr,
|
||||
shaped,
|
||||
policy,
|
||||
expectedRevision,
|
||||
actualRevision,
|
||||
forceSync);
|
||||
|
||||
TRI_FreeShapedJson(zone, shaped);
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read a single document, identified by key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int readSingle (TRI_transaction_collection_t* trxCollection,
|
||||
TRI_doc_mptr_copy_t* mptr,
|
||||
std::string const& key) {
|
||||
|
||||
TRI_ASSERT(mptr != nullptr);
|
||||
|
||||
if (orderBarrier(trxCollection) == nullptr) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
try {
|
||||
return TRI_ReadShapedJsonDocumentCollection(trxCollection,
|
||||
(TRI_voc_key_t) key.c_str(),
|
||||
mptr,
|
||||
! isLocked(trxCollection, TRI_TRANSACTION_READ));
|
||||
}
|
||||
catch (triagens::arango::Exception const& ex) {
|
||||
return ex.code();
|
||||
}
|
||||
catch (...) {
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -696,34 +764,6 @@ namespace triagens {
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read a single document, identified by key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int readSingle (TRI_transaction_collection_t* trxCollection,
|
||||
TRI_doc_mptr_copy_t* mptr,
|
||||
std::string const& key) {
|
||||
|
||||
TRI_ASSERT(mptr != nullptr);
|
||||
|
||||
if (orderBarrier(trxCollection) == nullptr) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
try {
|
||||
return TRI_ReadShapedJsonDocumentCollection(trxCollection,
|
||||
(TRI_voc_key_t) key.c_str(),
|
||||
mptr,
|
||||
! isLocked(trxCollection, TRI_TRANSACTION_READ));
|
||||
}
|
||||
catch (triagens::arango::Exception const& ex) {
|
||||
return ex.code();
|
||||
}
|
||||
catch (...) {
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read all documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -997,46 +1037,6 @@ namespace triagens {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update a single document, using JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int update (TRI_transaction_collection_t* trxCollection,
|
||||
std::string const& key,
|
||||
TRI_voc_rid_t rid,
|
||||
TRI_doc_mptr_copy_t* mptr,
|
||||
TRI_json_t* const json,
|
||||
TRI_doc_update_policy_e policy,
|
||||
TRI_voc_rid_t expectedRevision,
|
||||
TRI_voc_rid_t* actualRevision,
|
||||
bool forceSync) {
|
||||
|
||||
TRI_shaper_t* shaper = this->shaper(trxCollection);
|
||||
TRI_memory_zone_t* zone = shaper->_memoryZone;
|
||||
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json, true, isLocked(trxCollection, TRI_TRANSACTION_WRITE));
|
||||
|
||||
if (shaped == nullptr) {
|
||||
return TRI_ERROR_ARANGO_SHAPER_FAILED;
|
||||
}
|
||||
|
||||
if (orderBarrier(trxCollection) == nullptr) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int res = update(trxCollection,
|
||||
key,
|
||||
rid,
|
||||
mptr,
|
||||
shaped,
|
||||
policy,
|
||||
expectedRevision,
|
||||
actualRevision,
|
||||
forceSync);
|
||||
|
||||
TRI_FreeShapedJson(zone, shaped);
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update a single document, using shaped json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue