mirror of https://gitee.com/bigwinds/arangodb
specialized attribute accessor for AQL
This commit is contained in:
parent
0ffac810d4
commit
d20c104d0c
|
@ -831,36 +831,40 @@ Json AqlValue::extractObjectMember (triagens::arango::AqlTransaction* trx,
|
|||
TRI_ASSERT(_marker != nullptr);
|
||||
|
||||
// look for the attribute name in the shape
|
||||
if (*name == '_') {
|
||||
if (strcmp(name, TRI_VOC_ATTRIBUTE_KEY) == 0) {
|
||||
if (*name == '_' && name[1] != '\0') {
|
||||
if (name[1] == 'k' && strcmp(name, TRI_VOC_ATTRIBUTE_KEY) == 0) {
|
||||
// _key value is copied into JSON
|
||||
return Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(_marker));
|
||||
}
|
||||
else if (strcmp(name, TRI_VOC_ATTRIBUTE_ID) == 0) {
|
||||
if (name[1] == 'i' && strcmp(name, TRI_VOC_ATTRIBUTE_ID) == 0) {
|
||||
// _id
|
||||
buffer.reset();
|
||||
trx->resolver()->getCollectionName(document->_info._cid, buffer);
|
||||
buffer.appendChar('/');
|
||||
buffer.appendText(TRI_EXTRACT_MARKER_KEY(_marker));
|
||||
return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
|
||||
}
|
||||
else if (strcmp(name, TRI_VOC_ATTRIBUTE_REV) == 0) {
|
||||
if (name[1] == 'r' && strcmp(name, TRI_VOC_ATTRIBUTE_REV) == 0) {
|
||||
// _rev
|
||||
TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_marker);
|
||||
buffer.reset();
|
||||
buffer.appendInteger(rid);
|
||||
return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
|
||||
}
|
||||
else if (strcmp(name, TRI_VOC_ATTRIBUTE_FROM) == 0 &&
|
||||
(_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
|
||||
_marker->_type == TRI_WAL_MARKER_EDGE)) {
|
||||
if (name[1] == 'f' &&
|
||||
strcmp(name, TRI_VOC_ATTRIBUTE_FROM) == 0 &&
|
||||
(_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
|
||||
_marker->_type == TRI_WAL_MARKER_EDGE)) {
|
||||
buffer.reset();
|
||||
trx->resolver()->getCollectionNameCluster(TRI_EXTRACT_MARKER_FROM_CID(_marker), buffer);
|
||||
buffer.appendChar('/');
|
||||
buffer.appendText(TRI_EXTRACT_MARKER_FROM_KEY(_marker));
|
||||
return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
|
||||
}
|
||||
else if (strcmp(name, TRI_VOC_ATTRIBUTE_TO) == 0 &&
|
||||
(_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
|
||||
_marker->_type == TRI_WAL_MARKER_EDGE)) {
|
||||
if (name[1] == 't' &&
|
||||
strcmp(name, TRI_VOC_ATTRIBUTE_TO) == 0 &&
|
||||
(_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
|
||||
_marker->_type == TRI_WAL_MARKER_EDGE)) {
|
||||
buffer.reset();
|
||||
trx->resolver()->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(_marker), buffer);
|
||||
buffer.appendChar('/');
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AQL, specialized attribute accessor for expressions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-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 ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "AttributeAccessor.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "Basics/json.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
using Json = triagens::basics::Json;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the accessor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttributeAccessor::AttributeAccessor (char const* name,
|
||||
Variable const* variable)
|
||||
: _name(name),
|
||||
_variable(variable),
|
||||
_buffer(TRI_UNKNOWN_MEM_ZONE) {
|
||||
|
||||
TRI_ASSERT(_name != nullptr);
|
||||
TRI_ASSERT(_variable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the accessor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttributeAccessor::~AttributeAccessor () {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute the accessor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue AttributeAccessor::get (triagens::arango::AqlTransaction* trx,
|
||||
std::vector<TRI_document_collection_t const*>& docColls,
|
||||
std::vector<AqlValue>& argv,
|
||||
size_t startPos,
|
||||
std::vector<Variable*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
|
||||
size_t i = 0;
|
||||
for (auto it = vars.begin(); it != vars.end(); ++it, ++i) {
|
||||
if ((*it)->id == _variable->id) {
|
||||
|
||||
// save the collection info
|
||||
TRI_document_collection_t const* collection = docColls[regs[i]];
|
||||
|
||||
// get the AQL value
|
||||
auto& result = argv[startPos + regs[i]];
|
||||
|
||||
// extract the attribute
|
||||
auto j = result.extractObjectMember(trx, collection, _name, true, _buffer);
|
||||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, j.steal()));
|
||||
}
|
||||
// fall-through intentional
|
||||
}
|
||||
|
||||
return AqlValue(new Json(Json::Null));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -0,0 +1,117 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AQL, specialized attribute accessor for expressions
|
||||
///
|
||||
/// @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_ATTRIBUTE_ACCESSOR_H
|
||||
#define ARANGODB_AQL_ATTRIBUTE_ACCESSOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/AqlValue.h"
|
||||
#include "Aql/types.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "Utils/AqlTransaction.h"
|
||||
|
||||
struct TRI_document_collection_t;
|
||||
|
||||
namespace triagens {
|
||||
namespace aql {
|
||||
class Variable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AttributeAccessor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AttributeAccessor {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttributeAccessor (char const*,
|
||||
Variable const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~AttributeAccessor ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute the accessor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue get (triagens::arango::AqlTransaction* trx,
|
||||
std::vector<TRI_document_collection_t const*>&,
|
||||
std::vector<AqlValue>&,
|
||||
size_t,
|
||||
std::vector<Variable*> const&,
|
||||
std::vector<RegisterId> const&);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the attribute name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char const* _name;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the accessed variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable const* _variable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief buffer for temporary strings
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::basics::StringBuffer _buffer;
|
||||
|
||||
};
|
||||
|
||||
} // namespace triagens::aql
|
||||
} // namespace triagens
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -30,15 +30,16 @@
|
|||
#include "Aql/Expression.h"
|
||||
#include "Aql/AqlValue.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/AttributeAccessor.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/V8Expression.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "Basics/json.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
using Json = triagens::basics::Json;
|
||||
|
@ -112,15 +113,28 @@ Expression::Expression (Ast* ast,
|
|||
|
||||
Expression::~Expression () {
|
||||
if (_built) {
|
||||
if (_type == V8) {
|
||||
delete _func;
|
||||
_func = nullptr;
|
||||
}
|
||||
else if (_type == JSON) {
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
||||
_data = nullptr;
|
||||
// _json is freed automatically by AqlItemBlock
|
||||
switch (_type) {
|
||||
case JSON:
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
||||
break;
|
||||
|
||||
case ATTRIBUTE: {
|
||||
TRI_ASSERT(_accessor != nullptr);
|
||||
delete _accessor;
|
||||
break;
|
||||
}
|
||||
|
||||
case V8:
|
||||
delete _func;
|
||||
break;
|
||||
|
||||
case SIMPLE:
|
||||
case UNPROCESSED: {
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +177,15 @@ AqlValue Expression::execute (triagens::arango::AqlTransaction* trx,
|
|||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, _data, Json::NOFREE));
|
||||
}
|
||||
|
||||
case SIMPLE: {
|
||||
return executeSimpleExpression(_node, collection, trx, docColls, argv, startPos, vars, regs);
|
||||
}
|
||||
|
||||
case ATTRIBUTE: {
|
||||
TRI_ASSERT(_accessor != nullptr);
|
||||
return _accessor->get(trx, docColls, argv, startPos, vars, regs);
|
||||
}
|
||||
|
||||
case V8: {
|
||||
TRI_ASSERT(_func != nullptr);
|
||||
try {
|
||||
|
@ -184,10 +207,6 @@ AqlValue Expression::execute (triagens::arango::AqlTransaction* trx,
|
|||
}
|
||||
}
|
||||
|
||||
case SIMPLE: {
|
||||
return executeSimpleExpression(_node, collection, trx, docColls, argv, startPos, vars, regs);
|
||||
}
|
||||
|
||||
case UNPROCESSED: {
|
||||
// fall-through to exception
|
||||
}
|
||||
|
@ -323,6 +342,20 @@ void Expression::analyzeExpression () {
|
|||
_canThrow = _node->canThrow();
|
||||
_canRunOnDBServer = _node->canRunOnDBServer();
|
||||
_isDeterministic = _node->isDeterministic();
|
||||
|
||||
if (_node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
TRI_ASSERT_EXPENSIVE(_node->numMembers() == 1);
|
||||
auto member = _node->getMemberUnchecked(0);
|
||||
|
||||
if (member->type == NODE_TYPE_REFERENCE) {
|
||||
auto name = static_cast<char const*>(_node->getData());
|
||||
auto v = static_cast<Variable const*>(member->getData());
|
||||
|
||||
// specialize the simple expression into an attribute accessor
|
||||
_accessor = new AttributeAccessor(name, v);
|
||||
_type = ATTRIBUTE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// expression is a V8 expression
|
||||
|
@ -772,13 +805,13 @@ bool Expression::isConstant () const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief this gives you ("variable.access", "Reference")
|
||||
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||
/// call isAttributeAccess in advance to ensure no exceptions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::pair<std::string, std::string> Expression::getMultipleAttributes() {
|
||||
if (! isSimple()) {
|
||||
if (_type != SIMPLE && _type != ATTRIBUTE) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||
"getAccessNRef works only on simple expressions!");
|
||||
"getMultipleAttributes works only on simple expressions or attribute accesses!");
|
||||
}
|
||||
|
||||
auto expNode = _node;
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace triagens {
|
|||
class AqlItemBlock;
|
||||
struct AqlValue;
|
||||
class Ast;
|
||||
class AttributeAccessor;
|
||||
class Executor;
|
||||
struct V8Expression;
|
||||
|
||||
|
@ -63,7 +64,8 @@ namespace triagens {
|
|||
UNPROCESSED,
|
||||
JSON,
|
||||
V8,
|
||||
SIMPLE
|
||||
SIMPLE,
|
||||
ATTRIBUTE
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -164,22 +166,12 @@ namespace triagens {
|
|||
|
||||
AqlValue execute (triagens::arango::AqlTransaction* trx,
|
||||
std::vector<TRI_document_collection_t const*>&,
|
||||
std::vector<AqlValue>&, size_t,
|
||||
std::vector<AqlValue>&,
|
||||
size_t,
|
||||
std::vector<Variable*> const&,
|
||||
std::vector<RegisterId> const&,
|
||||
TRI_document_collection_t const**);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is a simple expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isSimple () {
|
||||
if (_type == UNPROCESSED) {
|
||||
analyzeExpression();
|
||||
}
|
||||
return _type == SIMPLE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether this is a JSON expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -210,11 +202,14 @@ namespace triagens {
|
|||
if (_type == UNPROCESSED) {
|
||||
analyzeExpression();
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case JSON:
|
||||
return "json";
|
||||
case SIMPLE:
|
||||
return "simple";
|
||||
case ATTRIBUTE:
|
||||
return "attribute";
|
||||
case V8:
|
||||
return "v8";
|
||||
case UNPROCESSED: {
|
||||
|
@ -245,7 +240,7 @@ namespace triagens {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief this gives you ("variable.access", "Reference")
|
||||
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||
/// call isAttributeAccess in advance to ensure no exceptions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::pair<std::string, std::string> getMultipleAttributes();
|
||||
|
@ -348,6 +343,8 @@ namespace triagens {
|
|||
V8Expression* _func;
|
||||
|
||||
struct TRI_json_t* _data;
|
||||
|
||||
AttributeAccessor* _accessor;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -46,6 +46,7 @@ add_executable(
|
|||
Aql/AqlValue.cpp
|
||||
Aql/Ast.cpp
|
||||
Aql/AstNode.cpp
|
||||
Aql/AttributeAccessor.cpp
|
||||
Aql/BindParameters.cpp
|
||||
Aql/Collection.cpp
|
||||
Aql/CollectionScanner.cpp
|
||||
|
|
|
@ -19,6 +19,7 @@ arangod_libarangod_a_SOURCES = \
|
|||
arangod/Aql/AqlValue.cpp \
|
||||
arangod/Aql/Ast.cpp \
|
||||
arangod/Aql/AstNode.cpp \
|
||||
arangod/Aql/AttributeAccessor.cpp \
|
||||
arangod/Aql/BindParameters.cpp \
|
||||
arangod/Aql/Collection.cpp \
|
||||
arangod/Aql/CollectionScanner.cpp \
|
||||
|
|
Loading…
Reference in New Issue