1
0
Fork 0

further work on RemoveNode

This commit is contained in:
Jan Steemann 2014-08-15 12:20:17 +02:00
parent 655d7759bf
commit 773c29cecf
13 changed files with 585 additions and 132 deletions

View File

@ -34,6 +34,7 @@
using namespace triagens::aql;
using Json = triagens::basics::Json;
using JsonHelper = triagens::basics::JsonHelper;
////////////////////////////////////////////////////////////////////////////////
/// @brief a quick method to decide whether a value is true
@ -156,6 +157,106 @@ bool AqlValue::isString () const {
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the AqlValue contains a list value
////////////////////////////////////////////////////////////////////////////////
bool AqlValue::isList () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
return TRI_IsListJson(json);
}
case SHAPED: {
return false;
}
case DOCVEC:
case RANGE: {
return true;
}
case EMPTY: {
return false;
}
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the AqlValue contains an array value
////////////////////////////////////////////////////////////////////////////////
bool AqlValue::isArray () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
return TRI_IsArrayJson(json);
}
case SHAPED: {
return true;
}
case DOCVEC:
case RANGE:
case EMPTY: {
return false;
}
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
////////////////////////////////////////////////////////////////////////////////
std::string AqlValue::toString () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
TRI_ASSERT(TRI_IsStringJson(json));
return std::string(json->_value._string.data, json->_value._string.length - 1);
}
case SHAPED:
case DOCVEC:
case RANGE:
case EMPTY: {
// cannot convert these types
}
}
return std::string("");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
////////////////////////////////////////////////////////////////////////////////
char const* AqlValue::toChar () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
TRI_ASSERT(TRI_IsStringJson(json));
return json->_value._string.data;
}
case SHAPED:
case DOCVEC:
case RANGE:
case EMPTY: {
// cannot convert these types
}
}
return "";
}
////////////////////////////////////////////////////////////////////////////////
/// @brief construct a V8 value as input for the expression execution in V8
////////////////////////////////////////////////////////////////////////////////
@ -327,6 +428,96 @@ Json AqlValue::toJson (AQL_TRANSACTION_V8* trx,
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extract an attribute value from the AqlValue
/// this will fail if the value is not an array
////////////////////////////////////////////////////////////////////////////////
Json AqlValue::extractArrayMember (AQL_TRANSACTION_V8* trx,
TRI_document_collection_t const* document,
char const* name) const {
switch (_type) {
case JSON: {
TRI_ASSERT(_json != nullptr);
TRI_json_t const* json = _json->json();
if (TRI_IsArrayJson(json)) {
TRI_json_t const* found = TRI_LookupArrayJson(json, name);
if (found != nullptr) {
return Json(TRI_UNKNOWN_MEM_ZONE, TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, found));
}
}
// attribute does not exist or something went wrong - fall-through to returning null below
return Json(Json::Null);
}
case SHAPED: {
TRI_ASSERT(document != nullptr);
TRI_ASSERT(_marker != nullptr);
auto shaper = document->getShaper();
// look for the attribute name in the shape
if (*name == '_') {
if (strcmp(name, "_key") == 0) {
// _key value is copied into JSON
return Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(_marker));
}
else if (strcmp(name, "_id") == 0) {
std::string id(trx->resolver()->getCollectionName(document->_info._cid));
id.push_back('/');
id.append(TRI_EXTRACT_MARKER_KEY(_marker));
return Json(TRI_UNKNOWN_MEM_ZONE, id);
}
else if (strcmp(name, "_rev") == 0) {
TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_marker);
return Json(TRI_UNKNOWN_MEM_ZONE, JsonHelper::uint64String(TRI_UNKNOWN_MEM_ZONE, rid));
}
else if (strcmp(name, "_from") == 0) {
std::string from(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_FROM_CID(_marker)));
from.push_back('/');
from.append(TRI_EXTRACT_MARKER_FROM_KEY(_marker));
return Json(TRI_UNKNOWN_MEM_ZONE, from);
}
else if (strcmp(name, "_to") == 0) {
std::string to(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_TO_CID(_marker)));
to.push_back('/');
to.append(TRI_EXTRACT_MARKER_TO_KEY(_marker));
return Json(TRI_UNKNOWN_MEM_ZONE, to);
}
}
TRI_shape_pid_t pid = shaper->lookupAttributePathByName(shaper, name);
if (pid != 0) {
// attribute exists
TRI_shaped_json_t document;
TRI_EXTRACT_SHAPED_JSON_MARKER(document, _marker);
TRI_shaped_json_t json;
TRI_shape_t const* shape;
bool ok = TRI_ExtractShapedJsonVocShaper(shaper, &document, 0, pid, &json, &shape);
if (ok && shape != nullptr) {
return Json(TRI_UNKNOWN_MEM_ZONE, TRI_JsonShapedJson(shaper, &json));
}
}
// attribute does not exist or something went wrong - fall-through to returning null
break;
}
case DOCVEC:
case RANGE:
case EMPTY: {
break;
}
}
return Json(Json::Null);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AqlValue from a vector of AqlItemBlock*s
////////////////////////////////////////////////////////////////////////////////

View File

@ -156,6 +156,32 @@ namespace triagens {
bool isString () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the AqlValue contains a list value
////////////////////////////////////////////////////////////////////////////////
bool isList () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the AqlValue contains an array value
////////////////////////////////////////////////////////////////////////////////
bool isArray () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
/// this will fail if the value is not a string
////////////////////////////////////////////////////////////////////////////////
std::string toString () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
/// this will fail if the value is not a string
////////////////////////////////////////////////////////////////////////////////
char const* toChar () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief construct a V8 value as input for the expression execution in V8
////////////////////////////////////////////////////////////////////////////////
@ -170,6 +196,15 @@ namespace triagens {
triagens::basics::Json toJson (AQL_TRANSACTION_V8*,
TRI_document_collection_t const*) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief extract an attribute value from the AqlValue
/// this will fail if the value is not an array
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json extractArrayMember (AQL_TRANSACTION_V8*,
TRI_document_collection_t const*,
char const*) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AqlValue from a vector of AqlItemBlock*s
////////////////////////////////////////////////////////////////////////////////

View File

@ -36,7 +36,17 @@
#include "VocBase/collection.h"
using namespace triagens::aql;
// -----------------------------------------------------------------------------
// --SECTION-- static initialization
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief initialize a singleton NOP node instance
////////////////////////////////////////////////////////////////////////////////
AstNode const Ast::NopNode = { NODE_TYPE_NOP };
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
@ -181,12 +191,18 @@ AstNode* Ast::createNodeReturn (AstNode const* expression) {
AstNode* Ast::createNodeRemove (AstNode const* expression,
AstNode const* collection,
AstNode* options) {
AstNode const* options) {
AstNode* node = createNode(NODE_TYPE_REMOVE);
if (options == nullptr) {
// no options given. now use default options
options = &NopNode;
}
node->addMember(options);
node->addMember(collection);
node->addMember(expression);
// TODO: handle options
return node;
}
@ -714,9 +730,7 @@ AstNode* Ast::createNodeRange (AstNode const* start,
////////////////////////////////////////////////////////////////////////////////
AstNode* Ast::createNodeNop () {
AstNode* node = createNode(NODE_TYPE_NOP);
return node;
return const_cast<AstNode*>(&NopNode);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -253,7 +253,7 @@ namespace triagens {
AstNode* createNodeRemove (AstNode const*,
AstNode const*,
AstNode*);
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST insert node
@ -679,6 +679,12 @@ namespace triagens {
AstNode const* _writeOptions;
////////////////////////////////////////////////////////////////////////////////
/// @brief a singleton NOP node instance
////////////////////////////////////////////////////////////////////////////////
static AstNode const NopNode;
};
}

View File

@ -236,6 +236,35 @@ void AstNode::toJson (TRI_json_t* json,
TRI_PushBack3ListJson(zone, json, node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the node's value to a boolean value
////////////////////////////////////////////////////////////////////////////////
bool AstNode::toBoolean () const {
if (type == NODE_TYPE_VALUE) {
switch (value.type) {
case VALUE_TYPE_BOOL: {
return value.value._bool;
}
case VALUE_TYPE_INT: {
return (value.value._int != 0);
}
case VALUE_TYPE_DOUBLE: {
return value.value._double != 0.0;
}
case VALUE_TYPE_STRING: {
return (*value.value._string != '\0');
}
case VALUE_TYPE_NULL:
case VALUE_TYPE_FAIL: {
return false;
}
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not a node is simple enough to be used in a simple
/// expression

View File

@ -181,6 +181,12 @@ namespace triagens {
void toJson (TRI_json_t*,
TRI_memory_zone_t*) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the node's value to a boolean value
////////////////////////////////////////////////////////////////////////////////
bool toBoolean () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not a value node is of numeric type
////////////////////////////////////////////////////////////////////////////////
@ -421,13 +427,31 @@ namespace triagens {
// -----------------------------------------------------------------------------
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief the node type
////////////////////////////////////////////////////////////////////////////////
AstNodeType const type;
////////////////////////////////////////////////////////////////////////////////
/// @brief the node value
////////////////////////////////////////////////////////////////////////////////
AstNodeValue value;
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief the node's sub nodes
////////////////////////////////////////////////////////////////////////////////
TRI_vector_pointer_t members;
};
}

View File

@ -1888,65 +1888,114 @@ RemoveBlock::RemoveBlock (AQL_TRANSACTION_V8* trx,
RemoveBlock::~RemoveBlock () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get some - this accumulates all input and calls the remove() method
////////////////////////////////////////////////////////////////////////////////
AqlItemBlock* RemoveBlock::getSome (size_t atLeast,
size_t atMost) {
std::vector<AqlItemBlock*> blocks;
// loop over input until it is exhausted
try {
while (true) {
auto res = ExecutionBlock::getSome(atLeast, atMost);
if (res == nullptr) {
break;
}
blocks.push_back(res);
}
remove(blocks);
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
delete (*it);
}
return nullptr;
}
catch (...) {
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
delete (*it);
}
throw;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the actual work horse for removing data
////////////////////////////////////////////////////////////////////////////////
void RemoveBlock::remove (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());
RegisterId const registerId = it->second.registerId;
auto trxCollection = _trx->trxCollection(_collection->cid());
if (ep->_outVariable == nullptr) {
// don't return anything
// loop over input until it is exhausted
while (true) {
auto res = ExecutionBlock::getSome(atLeast, atMost);
if (res == nullptr) {
return nullptr;
}
// loop over all blocks
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
auto res = (*it);
auto document = res->getDocumentCollection(registerId);
try {
size_t const n = res->size();
size_t const n = res->size();
for (size_t i = 0; i < n; i++) {
AqlValue a = res->getValue(i, registerId);
// loop over the complete block
for (size_t i = 0; i < n; i++) {
AqlValue a = res->getValue(i, registerId);
if (a.isEmpty()) {
// no value for _key. TODO: should we fail with an error in this case?
char const* key = nullptr;
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* json = member.json();
if (TRI_IsStringJson(json)) {
key = json->_value._string.data;
}
else {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_KEY_MISSING;
}
}
else if (a.isString()) {
// value is a string
key = a.toChar();
}
else {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
}
if (errorCode != TRI_ERROR_NO_ERROR) {
if (ep->_options.ignoreErrors) {
continue;
}
if (a.isString()) {
std::cout << "VALUE IS A STRING\n";
}
std::cout << JsonHelper::toString(a.toJson(_trx, document)) << "\n";
std::string key = "gig";
int removed = TRI_RemoveShapedJsonDocumentCollection(trxCollection, (TRI_voc_key_t) key.c_str(), 0, nullptr, nullptr, false, false);
std::cout << "REMOVE RESULT: " << removed << "\n";
THROW_ARANGO_EXCEPTION(errorCode);
}
else {
// no error. we expect to have a key
TRI_ASSERT(key != nullptr);
errorCode = TRI_RemoveShapedJsonDocumentCollection(trxCollection,
(TRI_voc_key_t) key,
0,
nullptr,
nullptr,
false,
ep->_options.waitForSync);
}
delete res;
}
catch (...) {
delete res;
throw;
}
(*it) = nullptr;
delete res;
}
// will never get here
}
// NOT YET IMPLEMENTED
TRI_ASSERT(false);
return nullptr;
}
// -----------------------------------------------------------------------------

View File

@ -1058,6 +1058,18 @@ namespace triagens {
virtual AqlItemBlock* getSome (size_t atLeast,
size_t atMost);
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief the actual work horse for removing data
////////////////////////////////////////////////////////////////////////////////
void remove (std::vector<AqlItemBlock*>&);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------

View File

@ -36,6 +36,7 @@
#include "Aql/Collection.h"
#include "Aql/Expression.h"
#include "Aql/ModificationOptions.h"
#include "Aql/Variable.h"
#include "Aql/Types.h"
#include "Aql/WalkerWorker.h"
@ -1087,6 +1088,63 @@ namespace triagens {
};
// -----------------------------------------------------------------------------
// --SECTION-- class ModificationNode
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief abstract base class for modification operations
////////////////////////////////////////////////////////////////////////////////
class ModificationNode : public ExecutionNode {
friend class ExecutionBlock;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor with a vocbase and a collection and options
////////////////////////////////////////////////////////////////////////////////
protected:
ModificationNode (TRI_vocbase_t* vocbase,
Collection* collection,
ModificationOptions const& options)
: ExecutionNode(),
_vocbase(vocbase),
_collection(collection),
_options(options) {
TRI_ASSERT(_vocbase != nullptr);
TRI_ASSERT(_collection != nullptr);
}
// -----------------------------------------------------------------------------
// --SECTION-- protected variables
// -----------------------------------------------------------------------------
protected:
////////////////////////////////////////////////////////////////////////////////
/// @brief _vocbase, the database
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief collection
////////////////////////////////////////////////////////////////////////////////
Collection* _collection;
////////////////////////////////////////////////////////////////////////////////
/// @brief modification operation options
////////////////////////////////////////////////////////////////////////////////
ModificationOptions _options;
};
// -----------------------------------------------------------------------------
// --SECTION-- class RemoveNode
// -----------------------------------------------------------------------------
@ -1095,7 +1153,7 @@ namespace triagens {
/// @brief class RemoveNode
////////////////////////////////////////////////////////////////////////////////
class RemoveNode : public ExecutionNode {
class RemoveNode : public ModificationNode {
friend class ExecutionBlock;
friend class RemoveBlock;
@ -1108,16 +1166,13 @@ namespace triagens {
RemoveNode (TRI_vocbase_t* vocbase,
Collection* collection,
ModificationOptions const& options,
Variable const* inVariable,
Variable const* outVariable)
: ExecutionNode(),
_vocbase(vocbase),
_collection(collection),
: ModificationNode(vocbase, collection, options),
_inVariable(inVariable),
_outVariable(outVariable) {
TRI_ASSERT(_vocbase != nullptr);
TRI_ASSERT(_collection != nullptr);
TRI_ASSERT(_inVariable != nullptr);
// _outVariable might be a nullptr
}
@ -1143,7 +1198,7 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
virtual ExecutionNode* clone () const {
auto c = new RemoveNode(_vocbase, _collection, _inVariable, _outVariable);
auto c = new RemoveNode(_vocbase, _collection, _options, _inVariable, _outVariable);
cloneDependencies(c);
return static_cast<ExecutionNode*>(c);
}
@ -1164,18 +1219,6 @@ namespace triagens {
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief _vocbase, the database
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief collection
////////////////////////////////////////////////////////////////////////////////
Collection* _collection;
////////////////////////////////////////////////////////////////////////////////
/// @brief input variable
////////////////////////////////////////////////////////////////////////////////

View File

@ -99,6 +99,37 @@ ExecutionPlan* ExecutionPlan::instanciateFromAst (Ast const* ast) {
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create modification options from an AST node
////////////////////////////////////////////////////////////////////////////////
ModificationOptions ExecutionPlan::createOptions (AstNode const* node) {
ModificationOptions options;
// parse the modification options we got
if (node != nullptr && node->type == NODE_TYPE_ARRAY) {
size_t n = node->numMembers();
for (size_t i = 0; i < n; ++i) {
auto member = node->getMember(i);
if (member != nullptr && member->type == NODE_TYPE_ARRAY_ELEMENT) {
auto name = member->getStringValue();
auto value = member->getMember(0);
TRI_ASSERT(value->isConstant());
if (strcmp(name, "waitForSync") == 0) {
options.waitForSync = value->toBoolean();
}
else if (strcmp(name, "ignoreErrors") == 0) {
options.ignoreErrors = value->toBoolean();
}
}
}
}
return options;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a node to the plan, will delete node if addition fails
////////////////////////////////////////////////////////////////////////////////
@ -487,9 +518,10 @@ ExecutionNode* ExecutionPlan::fromNodeRemove (Ast const* ast,
ExecutionNode* previous,
AstNode const* node) {
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REMOVE);
TRI_ASSERT(node->numMembers() == 2);
TRI_ASSERT(node->numMembers() == 3);
char const* collectionName = node->getMember(0)->getStringValue();
auto options = createOptions(node->getMember(0));
char const* collectionName = node->getMember(1)->getStringValue();
auto collections = ast->query()->collections();
auto collection = collections->get(collectionName);
@ -497,20 +529,20 @@ ExecutionNode* ExecutionPlan::fromNodeRemove (Ast const* ast,
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
auto expression = node->getMember(1);
auto expression = node->getMember(2);
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 RemoveNode(ast->query()->vocbase(), collection, v, nullptr));
en = addNode(new RemoveNode(ast->query()->vocbase(), collection, options, v, nullptr));
}
else {
// operand is some misc expression
auto calc = createTemporaryCalculation(ast, expression);
calc->addDependency(previous);
en = addNode(new RemoveNode(ast->query()->vocbase(), collection, calc->outVariable(), nullptr));
en = addNode(new RemoveNode(ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
previous = calc;
}

View File

@ -32,6 +32,7 @@
#include "Basics/Common.h"
#include "arangod/Aql/ExecutionNode.h"
#include "arangod/Aql/ModificationOptions.h"
namespace triagens {
namespace aql {
@ -109,6 +110,12 @@ namespace triagens {
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief create modification options from an AST node
////////////////////////////////////////////////////////////////////////////////
ModificationOptions createOptions (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a node to the plan, will delete node if addition fails
////////////////////////////////////////////////////////////////////////////////

View File

@ -162,8 +162,6 @@ void Expression::analyzeExpression () {
_type = V8;
_canThrow = _node->canThrow();
}
std::cout << "CAN THROW: " << _canThrow << "\n";
}
////////////////////////////////////////////////////////////////////////////////
@ -191,70 +189,10 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
if (result._type == AqlValue::SHAPED) {
TRI_ASSERT(myCollection != nullptr);
auto shaper = myCollection->getShaper();
// look for the attribute name in the shape
if (*name == '_') {
if (strcmp(name, "_key") == 0) {
// _key value is copied into JSON
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(result._marker)));
}
else if (strcmp(name, "_id") == 0) {
std::string id(trx->resolver()->getCollectionName(myCollection->_info._cid));
id.push_back('/');
id.append(TRI_EXTRACT_MARKER_KEY(result._marker));
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, id));
}
else if (strcmp(name, "_rev") == 0) {
TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(result._marker);
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, JsonHelper::uint64String(TRI_UNKNOWN_MEM_ZONE, rid)));
}
else if (strcmp(name, "_from") == 0) {
std::string from(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_FROM_CID(result._marker)));
from.push_back('/');
from.append(TRI_EXTRACT_MARKER_FROM_KEY(result._marker));
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, from));
}
else if (strcmp(name, "_to") == 0) {
std::string to(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_TO_CID(result._marker)));
to.push_back('/');
to.append(TRI_EXTRACT_MARKER_TO_KEY(result._marker));
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, to));
}
}
TRI_shape_pid_t pid = shaper->lookupAttributePathByName(shaper, name);
if (pid != 0) {
// attribute exists
TRI_shaped_json_t document;
TRI_EXTRACT_SHAPED_JSON_MARKER(document, result._marker);
TRI_shaped_json_t json;
TRI_shape_t const* shape;
bool ok = TRI_ExtractShapedJsonVocShaper(shaper, &document, 0, pid, &json, &shape);
if (ok && shape != nullptr) {
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_JsonShapedJson(shaper, &json)));
}
}
// attribute does not exist or something went wrong - fall-through to returning null below
auto j = result.extractArrayMember(trx, myCollection, name);
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, j.steal()));
}
else if (result._type == AqlValue::JSON) {
TRI_json_t const* json = result._json->json();
if (TRI_IsArrayJson(json)) {
TRI_json_t const* found = TRI_LookupArrayJson(json, name);
if (found != nullptr) {
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, found)));
}
}
// attribute does not exist or something went wrong - fall-through to returning null below
}
return AqlValue(new Json(Json::Null));
}

View File

@ -0,0 +1,73 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief AQL, data-modification query options
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Max Neunhoeffer
/// @author Copyright 2014, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_AQL_MODIFICATION_OPTIONS_H
#define ARANGODB_AQL_MODIFICATION_OPTIONS_H 1
#include "Basics/Common.h"
namespace triagens {
namespace aql {
////////////////////////////////////////////////////////////////////////////////
/// @brief ModificationOptions
////////////////////////////////////////////////////////////////////////////////
struct ModificationOptions {
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor, using default values
////////////////////////////////////////////////////////////////////////////////
ModificationOptions ()
: ignoreErrors(false),
waitForSync(false) {
}
// -----------------------------------------------------------------------------
// --SECTION-- public variables
// -----------------------------------------------------------------------------
bool ignoreErrors;
bool waitForSync;
};
} // namespace triagens::aql
} // namespace triagens
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End: