mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of ssh://github.com/ArangoDB/ArangoDB into spdvpk
This commit is contained in:
commit
bd7ccc1444
|
@ -327,10 +327,39 @@ class Slice {
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// look for the specified attribute path inside an Object
|
||||||
|
// returns a Slice(ValueType::None) if not found
|
||||||
|
Slice get(std::vector<char const*> const& attributes) const {
|
||||||
|
size_t const n = attributes.size();
|
||||||
|
if (n == 0) {
|
||||||
|
throw Exception(Exception::InvalidAttributePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use ourselves as the starting point
|
||||||
|
Slice last = Slice(start());
|
||||||
|
for (size_t i = 0; i < attributes.size(); ++i) {
|
||||||
|
// fetch subattribute
|
||||||
|
last = last.get(attributes[i]);
|
||||||
|
|
||||||
|
// abort as early as possible
|
||||||
|
if (last.isNone() || (i + 1 < n && !last.isObject())) {
|
||||||
|
return Slice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
// look for the specified attribute inside an Object
|
// look for the specified attribute inside an Object
|
||||||
// returns a Slice(ValueType::None) if not found
|
// returns a Slice(ValueType::None) if not found
|
||||||
Slice get(std::string const& attribute) const;
|
Slice get(std::string const& attribute) const;
|
||||||
|
|
||||||
|
// look for the specified attribute inside an Object
|
||||||
|
// returns a Slice(ValueType::None) if not found
|
||||||
|
Slice get(char const* attribute) const {
|
||||||
|
return get(std::string(attribute));
|
||||||
|
}
|
||||||
|
|
||||||
Slice operator[](std::string const& attribute) const {
|
Slice operator[](std::string const& attribute) const {
|
||||||
return get(attribute);
|
return get(attribute);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,15 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "AttributeAccessor.h"
|
#include "AttributeAccessor.h"
|
||||||
|
#include "Basics/JsonHelper.h"
|
||||||
#include "Aql/AqlItemBlock.h"
|
#include "Aql/AqlItemBlock.h"
|
||||||
#include "Aql/Variable.h"
|
#include "Aql/Variable.h"
|
||||||
#include "Basics/StringBuffer.h"
|
#include "Utils/AqlTransaction.h"
|
||||||
#include "Basics/json.h"
|
|
||||||
#include "VocBase/document-collection.h"
|
#include <velocypack/Slice.h>
|
||||||
#include "VocBase/shaped-json.h"
|
#include <velocypack/velocypack-aliases.h>
|
||||||
#include "VocBase/VocShaper.h"
|
|
||||||
|
|
||||||
using namespace arangodb::aql;
|
using namespace arangodb::aql;
|
||||||
using Json = arangodb::basics::Json;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create the accessor
|
/// @brief create the accessor
|
||||||
|
@ -41,38 +40,8 @@ AttributeAccessor::AttributeAccessor(
|
||||||
std::vector<char const*> const& attributeParts, Variable const* variable)
|
std::vector<char const*> const& attributeParts, Variable const* variable)
|
||||||
: _attributeParts(attributeParts),
|
: _attributeParts(attributeParts),
|
||||||
_combinedName(),
|
_combinedName(),
|
||||||
_variable(variable),
|
_variable(variable) {
|
||||||
_buffer(TRI_UNKNOWN_MEM_ZONE),
|
|
||||||
_shaper(nullptr),
|
|
||||||
_pid(0),
|
|
||||||
_nameCache({"", 0}),
|
|
||||||
_attributeType(ATTRIBUTE_TYPE_REGULAR) {
|
|
||||||
TRI_ASSERT(_variable != nullptr);
|
TRI_ASSERT(_variable != nullptr);
|
||||||
|
|
||||||
if (_attributeParts.size() == 1) {
|
|
||||||
char const* n = _attributeParts[0];
|
|
||||||
|
|
||||||
if (strcmp(n, TRI_VOC_ATTRIBUTE_KEY) == 0) {
|
|
||||||
_attributeType = ATTRIBUTE_TYPE_KEY;
|
|
||||||
} else if (strcmp(n, TRI_VOC_ATTRIBUTE_REV) == 0) {
|
|
||||||
_attributeType = ATTRIBUTE_TYPE_REV;
|
|
||||||
} else if (strcmp(n, TRI_VOC_ATTRIBUTE_ID) == 0) {
|
|
||||||
_attributeType = ATTRIBUTE_TYPE_ID;
|
|
||||||
} else if (strcmp(n, TRI_VOC_ATTRIBUTE_FROM) == 0) {
|
|
||||||
_attributeType = ATTRIBUTE_TYPE_FROM;
|
|
||||||
} else if (strcmp(n, TRI_VOC_ATTRIBUTE_TO) == 0) {
|
|
||||||
_attributeType = ATTRIBUTE_TYPE_TO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_attributeType == ATTRIBUTE_TYPE_REGULAR) {
|
|
||||||
for (auto const& it : _attributeParts) {
|
|
||||||
if (!_combinedName.empty()) {
|
|
||||||
_combinedName.push_back('.');
|
|
||||||
}
|
|
||||||
_combinedName.append(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -96,206 +65,15 @@ AqlValue AttributeAccessor::get(arangodb::AqlTransaction* trx,
|
||||||
auto& result = argv->getValueReference(startPos, regs[i]);
|
auto& result = argv->getValueReference(startPos, regs[i]);
|
||||||
|
|
||||||
// extract the attribute
|
// extract the attribute
|
||||||
if (result.isShaped()) {
|
VPackSlice const slice;
|
||||||
switch (_attributeType) {
|
#warning TODO: fill slice from AqlValue (result)
|
||||||
case ATTRIBUTE_TYPE_KEY: {
|
VPackSlice extracted = slice.get(_attributeParts);
|
||||||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE,
|
#warning TODO: build result from extracted
|
||||||
TRI_EXTRACT_MARKER_KEY(result._marker)));
|
return AqlValue(new arangodb::basics::Json(arangodb::basics::Json::Null));
|
||||||
}
|
|
||||||
|
|
||||||
case ATTRIBUTE_TYPE_REV: {
|
|
||||||
return extractRev(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
case ATTRIBUTE_TYPE_ID: {
|
|
||||||
TRI_document_collection_t const* collection =
|
|
||||||
argv->getDocumentCollection(regs[i]);
|
|
||||||
return extractId(result, trx, collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
case ATTRIBUTE_TYPE_FROM: {
|
|
||||||
return extractFrom(result, trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case ATTRIBUTE_TYPE_TO: {
|
|
||||||
return extractTo(result, trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case ATTRIBUTE_TYPE_REGULAR:
|
|
||||||
default: {
|
|
||||||
TRI_document_collection_t const* collection =
|
|
||||||
argv->getDocumentCollection(regs[i]);
|
|
||||||
return extractRegular(result, trx, collection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (result.isJson()) {
|
|
||||||
TRI_json_t const* json = result._json->json();
|
|
||||||
size_t const n = _attributeParts.size();
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
while (TRI_IsObjectJson(json)) {
|
|
||||||
TRI_ASSERT(i < n);
|
|
||||||
|
|
||||||
json = TRI_LookupObjectJson(json, _attributeParts[i]);
|
|
||||||
|
|
||||||
if (json == nullptr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
|
|
||||||
if (i == n) {
|
|
||||||
// reached the end
|
|
||||||
std::unique_ptr<TRI_json_t> copy(
|
|
||||||
TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, json));
|
|
||||||
|
|
||||||
if (copy == nullptr) {
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = new Json(TRI_UNKNOWN_MEM_ZONE, copy.get());
|
|
||||||
copy.release();
|
|
||||||
return AqlValue(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fall-through intentional
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// fall-through intentional
|
// fall-through intentional
|
||||||
}
|
}
|
||||||
|
|
||||||
return AqlValue(new Json(Json::Null));
|
return AqlValue(new arangodb::basics::Json(arangodb::basics::Json::Null));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _rev attribute from a ShapedJson marker
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue AttributeAccessor::extractRev(AqlValue const& src) {
|
|
||||||
_buffer.reset();
|
|
||||||
_buffer.appendInteger(TRI_EXTRACT_MARKER_RID(src._marker));
|
|
||||||
|
|
||||||
auto json = new Json(TRI_UNKNOWN_MEM_ZONE, _buffer.c_str(), _buffer.length());
|
|
||||||
|
|
||||||
return AqlValue(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _id attribute from a ShapedJson marker
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue AttributeAccessor::extractId(
|
|
||||||
AqlValue const& src, arangodb::AqlTransaction* trx,
|
|
||||||
TRI_document_collection_t const* document) {
|
|
||||||
if (_nameCache.value.empty()) {
|
|
||||||
_nameCache.value = trx->resolver()->getCollectionName(document->_info.id());
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer.reset();
|
|
||||||
_buffer.appendText(_nameCache.value);
|
|
||||||
_buffer.appendChar('/');
|
|
||||||
_buffer.appendText(TRI_EXTRACT_MARKER_KEY(src._marker));
|
|
||||||
|
|
||||||
auto json = new Json(TRI_UNKNOWN_MEM_ZONE, _buffer.c_str(), _buffer.length());
|
|
||||||
|
|
||||||
return AqlValue(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _from attribute from a ShapedJson marker
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue AttributeAccessor::extractFrom(AqlValue const& src,
|
|
||||||
arangodb::AqlTransaction* trx) {
|
|
||||||
// TODO vpack
|
|
||||||
if (src._marker->getType() != TRI_DOC_MARKER_KEY_EDGE) {
|
|
||||||
return AqlValue(new Json(Json::Null));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cid = TRI_EXTRACT_MARKER_FROM_CID(src._marker);
|
|
||||||
|
|
||||||
if (_nameCache.value.empty() || _nameCache.cid != cid) {
|
|
||||||
_nameCache.cid = cid;
|
|
||||||
_nameCache.value = trx->resolver()->getCollectionNameCluster(cid);
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer.reset();
|
|
||||||
_buffer.appendText(_nameCache.value);
|
|
||||||
_buffer.appendChar('/');
|
|
||||||
_buffer.appendText(TRI_EXTRACT_MARKER_FROM_KEY(src._marker));
|
|
||||||
|
|
||||||
auto json = new Json(TRI_UNKNOWN_MEM_ZONE, _buffer.c_str(), _buffer.length());
|
|
||||||
|
|
||||||
return AqlValue(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _to attribute from a ShapedJson marker
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue AttributeAccessor::extractTo(AqlValue const& src,
|
|
||||||
arangodb::AqlTransaction* trx) {
|
|
||||||
// TODO vpack
|
|
||||||
if (src._marker->getType() != TRI_DOC_MARKER_KEY_EDGE) {
|
|
||||||
return AqlValue(new Json(Json::Null));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cid = TRI_EXTRACT_MARKER_TO_CID(src._marker);
|
|
||||||
|
|
||||||
if (_nameCache.value.empty() || _nameCache.cid != cid) {
|
|
||||||
_nameCache.cid = cid;
|
|
||||||
_nameCache.value = trx->resolver()->getCollectionNameCluster(cid);
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer.reset();
|
|
||||||
_buffer.appendText(_nameCache.value);
|
|
||||||
_buffer.appendChar('/');
|
|
||||||
_buffer.appendText(TRI_EXTRACT_MARKER_TO_KEY(src._marker));
|
|
||||||
|
|
||||||
auto json = new Json(TRI_UNKNOWN_MEM_ZONE, _buffer.c_str(), _buffer.length());
|
|
||||||
|
|
||||||
return AqlValue(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract any other attribute from a ShapedJson marker
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue AttributeAccessor::extractRegular(
|
|
||||||
AqlValue const& src, arangodb::AqlTransaction* trx,
|
|
||||||
TRI_document_collection_t const* document) {
|
|
||||||
if (_shaper == nullptr) {
|
|
||||||
_shaper = document->getShaper();
|
|
||||||
_pid = _shaper->lookupAttributePathByName(_combinedName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pid != 0) {
|
|
||||||
// attribute exists
|
|
||||||
TRI_ASSERT(_shaper != nullptr);
|
|
||||||
|
|
||||||
TRI_shaped_json_t shapedJson;
|
|
||||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, src._marker);
|
|
||||||
|
|
||||||
TRI_shaped_json_t json;
|
|
||||||
TRI_shape_t const* shape;
|
|
||||||
|
|
||||||
bool ok = _shaper->extractShapedJson(&shapedJson, 0, _pid, &json, &shape);
|
|
||||||
|
|
||||||
if (ok && shape != nullptr) {
|
|
||||||
std::unique_ptr<TRI_json_t> extracted(TRI_JsonShapedJson(_shaper, &json));
|
|
||||||
|
|
||||||
if (extracted == nullptr) {
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto j = new Json(TRI_UNKNOWN_MEM_ZONE, extracted.get());
|
|
||||||
extracted.release();
|
|
||||||
return AqlValue(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return AqlValue(new Json(Json::Null));
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,17 +27,12 @@
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
#include "Aql/AqlValue.h"
|
#include "Aql/AqlValue.h"
|
||||||
#include "Aql/types.h"
|
#include "Aql/types.h"
|
||||||
#include "Basics/StringBuffer.h"
|
|
||||||
#include "Utils/AqlTransaction.h"
|
|
||||||
#include "VocBase/shaped-json.h"
|
|
||||||
|
|
||||||
struct TRI_document_collection_t;
|
|
||||||
class VocShaper;
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace aql {
|
namespace aql {
|
||||||
|
|
||||||
class AqlItemBlock;
|
class AqlItemBlock;
|
||||||
|
class AqlTransaction;
|
||||||
struct Variable;
|
struct Variable;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -45,15 +40,6 @@ struct Variable;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class AttributeAccessor {
|
class AttributeAccessor {
|
||||||
enum AttributeType {
|
|
||||||
ATTRIBUTE_TYPE_KEY,
|
|
||||||
ATTRIBUTE_TYPE_REV,
|
|
||||||
ATTRIBUTE_TYPE_ID,
|
|
||||||
ATTRIBUTE_TYPE_FROM,
|
|
||||||
ATTRIBUTE_TYPE_TO,
|
|
||||||
ATTRIBUTE_TYPE_REGULAR
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AttributeAccessor(std::vector<char const*> const&, Variable const*);
|
AttributeAccessor(std::vector<char const*> const&, Variable const*);
|
||||||
|
|
||||||
|
@ -67,39 +53,6 @@ class AttributeAccessor {
|
||||||
std::vector<Variable const*> const&,
|
std::vector<Variable const*> const&,
|
||||||
std::vector<RegisterId> const&);
|
std::vector<RegisterId> const&);
|
||||||
|
|
||||||
private:
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _rev attribute from a ShapedJson marker
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue extractRev(AqlValue const&);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _id attribute from a ShapedJson marker
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue extractId(AqlValue const&, arangodb::AqlTransaction*,
|
|
||||||
struct TRI_document_collection_t const*);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _from attribute from a ShapedJson marker
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue extractFrom(AqlValue const&, arangodb::AqlTransaction*);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract the _to attribute from a ShapedJson marker
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue extractTo(AqlValue const&, arangodb::AqlTransaction*);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extract any other attribute from a ShapedJson marker
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AqlValue extractRegular(AqlValue const&, arangodb::AqlTransaction*,
|
|
||||||
struct TRI_document_collection_t const*);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief the attribute names vector (e.g. [ "a", "b", "c" ] for a.b.c)
|
/// @brief the attribute names vector (e.g. [ "a", "b", "c" ] for a.b.c)
|
||||||
|
@ -119,38 +72,6 @@ class AttributeAccessor {
|
||||||
|
|
||||||
Variable const* _variable;
|
Variable const* _variable;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief buffer for temporary strings
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
arangodb::basics::StringBuffer _buffer;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief shaper
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
VocShaper* _shaper;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief attribute path id cache for shapes
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
TRI_shape_pid_t _pid;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief collection name lookup cache
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct {
|
|
||||||
std::string value;
|
|
||||||
TRI_voc_cid_t cid;
|
|
||||||
} _nameCache;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief attribute type (to save repeated strcmp calls)
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AttributeType _attributeType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace arangodb::aql
|
} // namespace arangodb::aql
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Utils/StandaloneTransactionContext.h"
|
#include "Utils/StandaloneTransactionContext.h"
|
||||||
#include "Utils/V8TransactionContext.h"
|
#include "Utils/V8TransactionContext.h"
|
||||||
#include "V8/v8-conv.h"
|
#include "V8/v8-conv.h"
|
||||||
|
#include "V8/v8-vpack.h"
|
||||||
#include "V8Server/ApplicationV8.h"
|
#include "V8Server/ApplicationV8.h"
|
||||||
#include "VocBase/vocbase.h"
|
#include "VocBase/vocbase.h"
|
||||||
#include "VocBase/Graphs.h"
|
#include "VocBase/Graphs.h"
|
||||||
|
@ -617,7 +618,7 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
||||||
warningsToVelocyPack(tmp);
|
warningsToVelocyPack(tmp);
|
||||||
tmp.close();
|
tmp.close();
|
||||||
res.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
|
res.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
|
||||||
res.json = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, cacheEntry->_queryResult);
|
res.json = arangodb::basics::VelocyPackHelper::velocyPackToJson(cacheEntry->_queryResult->slice());
|
||||||
res.cached = true;
|
res.cached = true;
|
||||||
|
|
||||||
if (res.json == nullptr) {
|
if (res.json == nullptr) {
|
||||||
|
@ -680,20 +681,18 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
||||||
|
|
||||||
if (_warnings.empty()) {
|
if (_warnings.empty()) {
|
||||||
// finally store the generated result in the query cache
|
// finally store the generated result in the query cache
|
||||||
std::unique_ptr<TRI_json_t> copy(
|
std::shared_ptr<VPackBuilder> copy(arangodb::basics::JsonHelper::toVelocyPack(jsonResult.json()));
|
||||||
TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, jsonResult.json()));
|
|
||||||
|
|
||||||
if (copy == nullptr) {
|
if (copy == nullptr) {
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = QueryCache::instance()->store(
|
auto result = QueryCache::instance()->store(
|
||||||
_vocbase, queryStringHash, _queryString, _queryLength, copy.get(),
|
_vocbase, queryStringHash, _queryString, _queryLength, copy,
|
||||||
_trx->collectionNames());
|
_trx->collectionNames());
|
||||||
|
|
||||||
if (result != nullptr) {
|
if (result == nullptr) {
|
||||||
// result now belongs to cache
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||||
copy.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -789,8 +788,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
||||||
if (cacheEntry != nullptr) {
|
if (cacheEntry != nullptr) {
|
||||||
// got a result from the query cache
|
// got a result from the query cache
|
||||||
QueryResultV8 res(TRI_ERROR_NO_ERROR);
|
QueryResultV8 res(TRI_ERROR_NO_ERROR);
|
||||||
res.result = v8::Handle<v8::Array>::Cast(
|
res.result = v8::Handle<v8::Array>::Cast(TRI_VPackToV8(isolate, cacheEntry->_queryResult->slice()));
|
||||||
TRI_ObjectJson(isolate, cacheEntry->_queryResult));
|
|
||||||
res.cached = true;
|
res.cached = true;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -821,12 +819,8 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
||||||
try {
|
try {
|
||||||
if (useQueryCache) {
|
if (useQueryCache) {
|
||||||
// iterate over result, return it and store it in query cache
|
// iterate over result, return it and store it in query cache
|
||||||
std::unique_ptr<TRI_json_t> cacheResult(
|
auto builder = std::make_shared<VPackBuilder>();
|
||||||
TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE));
|
builder->openArray();
|
||||||
|
|
||||||
if (cacheResult == nullptr) {
|
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t j = 0;
|
uint32_t j = 0;
|
||||||
while (nullptr != (value = _engine->getSome(
|
while (nullptr != (value = _engine->getSome(
|
||||||
|
@ -842,20 +836,24 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
||||||
result.result->Set(j++, val.toV8(isolate, _trx, doc));
|
result.result->Set(j++, val.toV8(isolate, _trx, doc));
|
||||||
|
|
||||||
auto json = val.toJson(_trx, doc, true);
|
auto json = val.toJson(_trx, doc, true);
|
||||||
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, cacheResult.get(),
|
int res = arangodb::basics::JsonHelper::toVelocyPack(json.json(), *(builder.get()));
|
||||||
json.steal());
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
delete value;
|
||||||
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete value;
|
delete value;
|
||||||
value = nullptr;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder->close();
|
||||||
|
|
||||||
if (_warnings.empty()) {
|
if (_warnings.empty()) {
|
||||||
// finally store the generated result in the query cache
|
// finally store the generated result in the query cache
|
||||||
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString,
|
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString,
|
||||||
_queryLength, cacheResult.get(),
|
_queryLength, builder, _trx->collectionNames());
|
||||||
_trx->collectionNames());
|
|
||||||
cacheResult.release();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// iterate over result and return it
|
// iterate over result and return it
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include "Aql/QueryCache.h"
|
#include "Aql/QueryCache.h"
|
||||||
#include "Basics/fasthash.h"
|
#include "Basics/fasthash.h"
|
||||||
#include "Basics/json.h"
|
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/MutexLocker.h"
|
#include "Basics/MutexLocker.h"
|
||||||
#include "Basics/ReadLocker.h"
|
#include "Basics/ReadLocker.h"
|
||||||
|
@ -60,7 +59,7 @@ static std::atomic<arangodb::aql::QueryCacheMode> Mode(CACHE_ON_DEMAND);
|
||||||
|
|
||||||
QueryCacheResultEntry::QueryCacheResultEntry(
|
QueryCacheResultEntry::QueryCacheResultEntry(
|
||||||
uint64_t hash, char const* queryString, size_t queryStringLength,
|
uint64_t hash, char const* queryString, size_t queryStringLength,
|
||||||
TRI_json_t* queryResult, std::vector<std::string> const& collections)
|
std::shared_ptr<VPackBuilder> queryResult, std::vector<std::string> const& collections)
|
||||||
: _hash(hash),
|
: _hash(hash),
|
||||||
_queryString(nullptr),
|
_queryString(nullptr),
|
||||||
_queryStringLength(queryStringLength),
|
_queryStringLength(queryStringLength),
|
||||||
|
@ -83,7 +82,6 @@ QueryCacheResultEntry::QueryCacheResultEntry(
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QueryCacheResultEntry::~QueryCacheResultEntry() {
|
QueryCacheResultEntry::~QueryCacheResultEntry() {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _queryResult);
|
|
||||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, _queryString);
|
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, _queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,12 +391,13 @@ QueryCache::~QueryCache() {
|
||||||
VPackBuilder QueryCache::properties() {
|
VPackBuilder QueryCache::properties() {
|
||||||
MUTEX_LOCKER(mutexLocker, _propertiesLock);
|
MUTEX_LOCKER(mutexLocker, _propertiesLock);
|
||||||
|
|
||||||
VPackBuilder json;
|
VPackBuilder builder;
|
||||||
json.add(VPackValue(VPackValueType::Object));
|
builder.openObject();
|
||||||
json.add("mode", VPackValue(modeString(mode())));
|
builder.add("mode", VPackValue(modeString(mode())));
|
||||||
json.add("maxResults", VPackValue(MaxResults));
|
builder.add("maxResults", VPackValue(MaxResults));
|
||||||
json.close();
|
builder.close();
|
||||||
return json;
|
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -486,9 +485,9 @@ QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
|
||||||
|
|
||||||
QueryCacheResultEntry* QueryCache::store(
|
QueryCacheResultEntry* QueryCache::store(
|
||||||
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString,
|
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString,
|
||||||
size_t queryStringLength, TRI_json_t* result,
|
size_t queryStringLength, std::shared_ptr<VPackBuilder> result,
|
||||||
std::vector<std::string> const& collections) {
|
std::vector<std::string> const& collections) {
|
||||||
if (!TRI_IsArrayJson(result)) {
|
if (!result->slice().isArray()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,9 @@
|
||||||
#define ARANGOD_AQL_QUERY_CACHE_H 1
|
#define ARANGOD_AQL_QUERY_CACHE_H 1
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
#include "Basics/JsonHelper.h"
|
|
||||||
#include "Basics/Mutex.h"
|
#include "Basics/Mutex.h"
|
||||||
#include "Basics/ReadWriteLock.h"
|
#include "Basics/ReadWriteLock.h"
|
||||||
|
|
||||||
struct TRI_json_t;
|
|
||||||
struct TRI_vocbase_t;
|
struct TRI_vocbase_t;
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
@ -47,7 +45,7 @@ enum QueryCacheMode { CACHE_ALWAYS_OFF, CACHE_ALWAYS_ON, CACHE_ON_DEMAND };
|
||||||
struct QueryCacheResultEntry {
|
struct QueryCacheResultEntry {
|
||||||
QueryCacheResultEntry() = delete;
|
QueryCacheResultEntry() = delete;
|
||||||
|
|
||||||
QueryCacheResultEntry(uint64_t, char const*, size_t, struct TRI_json_t*,
|
QueryCacheResultEntry(uint64_t, char const*, size_t, std::shared_ptr<arangodb::velocypack::Builder>,
|
||||||
std::vector<std::string> const&);
|
std::vector<std::string> const&);
|
||||||
|
|
||||||
~QueryCacheResultEntry();
|
~QueryCacheResultEntry();
|
||||||
|
@ -73,7 +71,7 @@ struct QueryCacheResultEntry {
|
||||||
uint64_t const _hash;
|
uint64_t const _hash;
|
||||||
char* _queryString;
|
char* _queryString;
|
||||||
size_t const _queryStringLength;
|
size_t const _queryStringLength;
|
||||||
struct TRI_json_t* _queryResult;
|
std::shared_ptr<arangodb::velocypack::Builder> _queryResult;
|
||||||
std::vector<std::string> const _collections;
|
std::vector<std::string> const _collections;
|
||||||
QueryCacheResultEntry* _prev;
|
QueryCacheResultEntry* _prev;
|
||||||
QueryCacheResultEntry* _next;
|
QueryCacheResultEntry* _next;
|
||||||
|
@ -273,7 +271,7 @@ class QueryCache {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, char const*, size_t,
|
QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, char const*, size_t,
|
||||||
struct TRI_json_t*,
|
std::shared_ptr<arangodb::velocypack::Builder>,
|
||||||
std::vector<std::string> const&);
|
std::vector<std::string> const&);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -24,11 +24,8 @@
|
||||||
#include "v8-query.h"
|
#include "v8-query.h"
|
||||||
#include "Aql/Query.h"
|
#include "Aql/Query.h"
|
||||||
#include "Aql/QueryResultV8.h"
|
#include "Aql/QueryResultV8.h"
|
||||||
#include "Basics/StringBuffer.h"
|
|
||||||
#include "Basics/VelocyPackHelper.h"
|
#include "Basics/VelocyPackHelper.h"
|
||||||
#include "Indexes/GeoIndex2.h"
|
#include "Indexes/GeoIndex2.h"
|
||||||
#include "Indexes/HashIndex.h"
|
|
||||||
#include "Indexes/SkiplistIndex.h"
|
|
||||||
#include "Utils/OperationCursor.h"
|
#include "Utils/OperationCursor.h"
|
||||||
#include "Utils/SingleCollectionTransaction.h"
|
#include "Utils/SingleCollectionTransaction.h"
|
||||||
#include "Utils/V8TransactionContext.h"
|
#include "Utils/V8TransactionContext.h"
|
||||||
|
@ -36,16 +33,12 @@
|
||||||
#include "V8/v8-conv.h"
|
#include "V8/v8-conv.h"
|
||||||
#include "V8/v8-utils.h"
|
#include "V8/v8-utils.h"
|
||||||
#include "V8/v8-vpack.h"
|
#include "V8/v8-vpack.h"
|
||||||
#include "V8Server/v8-shape-conv.h"
|
|
||||||
#include "V8Server/v8-vocbase.h"
|
#include "V8Server/v8-vocbase.h"
|
||||||
#include "V8Server/v8-vocindex.h"
|
#include "V8Server/v8-vocindex.h"
|
||||||
#include "V8Server/v8-wrapshapedjson.h"
|
|
||||||
#include "V8Server/V8VPackWrapper.h"
|
#include "V8Server/V8VPackWrapper.h"
|
||||||
#include "VocBase/document-collection.h"
|
#include "VocBase/document-collection.h"
|
||||||
#include "VocBase/edge-collection.h"
|
#include "VocBase/edge-collection.h"
|
||||||
#include "VocBase/ExampleMatcher.h"
|
|
||||||
#include "VocBase/vocbase.h"
|
#include "VocBase/vocbase.h"
|
||||||
#include "VocBase/VocShaper.h"
|
|
||||||
|
|
||||||
#include <velocypack/Builder.h>
|
#include <velocypack/Builder.h>
|
||||||
#include <velocypack/Iterator.h>
|
#include <velocypack/Iterator.h>
|
||||||
|
|
|
@ -3205,28 +3205,6 @@ arangodb::Index* TRI_EnsureFulltextIndexDocumentCollection(
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief executes a select-by-example query
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::vector<TRI_doc_mptr_t> TRI_SelectByExample(
|
|
||||||
TRI_transaction_collection_t* trxCollection,
|
|
||||||
ExampleMatcher const& matcher) {
|
|
||||||
TRI_document_collection_t* document = trxCollection->_collection->_collection;
|
|
||||||
|
|
||||||
// use filtered to hold copies of the master pointer
|
|
||||||
std::vector<TRI_doc_mptr_t> filtered;
|
|
||||||
|
|
||||||
auto work = [&matcher, &filtered](TRI_doc_mptr_t const* ptr) {
|
|
||||||
if (matcher.matches(0, ptr)) {
|
|
||||||
filtered.emplace_back(*ptr);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
document->primaryIndex()->invokeOnAllElements(work);
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief rotate the current journal of the collection
|
/// @brief rotate the current journal of the collection
|
||||||
/// use this for testing only
|
/// use this for testing only
|
||||||
|
|
|
@ -682,41 +682,6 @@ arangodb::Index* TRI_EnsureFulltextIndexDocumentCollection(
|
||||||
arangodb::Transaction* trx, TRI_document_collection_t*, TRI_idx_iid_t,
|
arangodb::Transaction* trx, TRI_document_collection_t*, TRI_idx_iid_t,
|
||||||
std::string const&, int, bool&);
|
std::string const&, int, bool&);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief executes a select-by-example query
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::vector<TRI_doc_mptr_t> TRI_SelectByExample(
|
|
||||||
struct TRI_transaction_collection_t*,
|
|
||||||
arangodb::ExampleMatcher const& matcher);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief executes a select-by-example query
|
|
||||||
/// TODO remove
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct ShapedJsonHash {
|
|
||||||
size_t operator()(TRI_shaped_json_t const& shap) const {
|
|
||||||
uint64_t hash = 0x12345678;
|
|
||||||
hash = fasthash64(&shap._sid, sizeof(shap._sid), hash);
|
|
||||||
return static_cast<size_t>(
|
|
||||||
fasthash64(shap._data.data, shap._data.length, hash));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ShapedJsonEq {
|
|
||||||
bool operator()(TRI_shaped_json_t const& left,
|
|
||||||
TRI_shaped_json_t const& right) const {
|
|
||||||
if (left._sid != right._sid) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (left._data.length != right._data.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (memcmp(left._data.data, right._data.data, left._data.length) == 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief rotate the current journal of the collection
|
/// @brief rotate the current journal of the collection
|
||||||
/// use this for testing only
|
/// use this for testing only
|
||||||
|
|
Loading…
Reference in New Issue