mirror of https://gitee.com/bigwinds/arangodb
less json
This commit is contained in:
parent
329b3d623f
commit
c21d7fc2f4
|
@ -33,6 +33,7 @@
|
|||
#include "VocBase/collection.h"
|
||||
|
||||
#include <velocypack/Iterator.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
using namespace arangodb::aql;
|
||||
|
@ -1046,25 +1047,22 @@ AstNode* Ast::createNodeIntersectedArray(AstNode const* lhs,
|
|||
size_t const nl = lhs->numMembers();
|
||||
size_t const nr = rhs->numMembers();
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(nl + nr, arangodb::basics::JsonHash(),
|
||||
arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
|
||||
|
||||
for (size_t i = 0; i < nl; ++i) {
|
||||
auto member = lhs->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
cache.emplace(json, member);
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
|
||||
auto node = createNodeArray();
|
||||
|
||||
for (size_t i = 0; i < nr; ++i) {
|
||||
auto member = rhs->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
auto it = cache.find(json);
|
||||
auto it = cache.find(slice);
|
||||
|
||||
if (it != cache.end()) {
|
||||
node->addMember((*it).second);
|
||||
|
@ -1085,10 +1083,7 @@ AstNode* Ast::createNodeUnionizedArray(AstNode const* lhs, AstNode const* rhs) {
|
|||
size_t const nl = lhs->numMembers();
|
||||
size_t const nr = rhs->numMembers();
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(nl + nr, arangodb::basics::JsonHash(),
|
||||
arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
|
||||
|
||||
for (size_t i = 0; i < nl + nr; ++i) {
|
||||
AstNode* member;
|
||||
|
@ -1097,9 +1092,9 @@ AstNode* Ast::createNodeUnionizedArray(AstNode const* lhs, AstNode const* rhs) {
|
|||
} else {
|
||||
member = rhs->getMemberUnchecked(i - nl);
|
||||
}
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
cache.emplace(json, member);
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
|
||||
auto node = createNodeArray();
|
||||
|
@ -2039,16 +2034,14 @@ AstNode const* Ast::deduplicateArray(AstNode const* node) {
|
|||
|
||||
// TODO: sort values in place first and compare two adjacent members each
|
||||
|
||||
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash,
|
||||
arangodb::basics::JsonEqual>
|
||||
cache(n, arangodb::basics::JsonHash(), arangodb::basics::JsonEqual());
|
||||
std::unordered_map<VPackSlice, AstNode const*> cache(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto member = node->getMemberUnchecked(i);
|
||||
auto json = member->computeJson();
|
||||
VPackSlice slice = member->computeValue();
|
||||
|
||||
if (cache.find(json) == cache.end()) {
|
||||
cache.emplace(json, member);
|
||||
if (cache.find(slice) == cache.end()) {
|
||||
cache.emplace(slice, member);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#endif
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
#include <array>
|
||||
|
||||
|
@ -432,7 +433,7 @@ static bool IsEmptyString(char const* p, size_t length) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode::AstNode(AstNodeType type)
|
||||
: type(type), flags(0), computedJson(nullptr) {}
|
||||
: type(type), flags(0), computedValue(nullptr) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a node, with defining a value type
|
||||
|
@ -441,7 +442,7 @@ AstNode::AstNode(AstNodeType type)
|
|||
AstNode::AstNode(AstNodeType type, AstNodeValueType valueType) : AstNode(type) {
|
||||
value.type = valueType;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -453,7 +454,7 @@ AstNode::AstNode(bool v, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_BOOL);
|
||||
value.value._bool = v;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -465,7 +466,7 @@ AstNode::AstNode(int64_t v, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_INT);
|
||||
value.value._int = v;
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -477,7 +478,7 @@ AstNode::AstNode(char const* v, size_t length, AstNodeValueType valueType)
|
|||
TRI_ASSERT(valueType == VALUE_TYPE_STRING);
|
||||
setStringValue(v, length);
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -487,7 +488,7 @@ AstNode::AstNode(char const* v, size_t length, AstNodeValueType valueType)
|
|||
AstNode::AstNode(Ast* ast, arangodb::basics::Json const& json)
|
||||
: AstNode(getNodeTypeFromJson(json)) {
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
|
||||
auto query = ast->query();
|
||||
|
||||
|
@ -676,7 +677,7 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
|
|||
arangodb::basics::Json const& json)
|
||||
: AstNode(getNodeTypeFromJson(json)) {
|
||||
TRI_ASSERT(flags == 0);
|
||||
TRI_ASSERT(computedJson == nullptr);
|
||||
TRI_ASSERT(computedValue == nullptr);
|
||||
|
||||
switch (type) {
|
||||
case NODE_TYPE_ATTRIBUTE_ACCESS: {
|
||||
|
@ -830,9 +831,8 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode::~AstNode() {
|
||||
if (computedJson != nullptr) {
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, computedJson);
|
||||
computedJson = nullptr;
|
||||
if (computedValue != nullptr) {
|
||||
delete[] computedValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,21 +936,23 @@ void AstNode::dump(int level) const {
|
|||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compute the JSON for a constant value node
|
||||
/// the JSON is owned by the node and must not be freed by the caller
|
||||
/// @brief compute the value for a constant value node
|
||||
/// the value is owned by the node and must not be freed by the caller
|
||||
/// note that the return value might be NULL in case of OOM
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* AstNode::computeJson() const {
|
||||
VPackSlice AstNode::computeValue() const {
|
||||
TRI_ASSERT(isConstant());
|
||||
|
||||
if (computedJson == nullptr) {
|
||||
// note: the following may fail but we do not need to
|
||||
// check that here
|
||||
computedJson = toJsonValue(TRI_UNKNOWN_MEM_ZONE);
|
||||
if (computedValue == nullptr) {
|
||||
VPackBuilder builder;
|
||||
toVelocyPackValue(builder);
|
||||
|
||||
computedValue = new uint8_t[builder.size()];
|
||||
memcpy(computedValue, builder.data(), builder.size());
|
||||
}
|
||||
|
||||
return computedJson;
|
||||
return VPackSlice(computedValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "Basics/json.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
#include <velocypack/Slice.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
|
||||
|
@ -291,12 +293,12 @@ struct AstNode {
|
|||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compute the JSON for a constant value node
|
||||
/// the JSON is owned by the node and must not be freed by the caller
|
||||
/// @brief compute the value for a constant value node
|
||||
/// the value is owned by the node and must not be freed by the caller
|
||||
/// note that the return value might be NULL in case of OOM
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* computeJson() const;
|
||||
arangodb::velocypack::Slice computeValue() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sort the members of an (array) node
|
||||
|
@ -932,10 +934,10 @@ struct AstNode {
|
|||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief precomputed JSON value (used when executing expressions)
|
||||
/// @brief precomputed VPack value (used when executing expressions)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t mutable* computedJson;
|
||||
uint8_t mutable* computedValue;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the node's sub nodes
|
||||
|
|
|
@ -104,7 +104,7 @@ Expression::~Expression() {
|
|||
switch (_type) {
|
||||
case JSON:
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
||||
delete[] _data;
|
||||
break;
|
||||
|
||||
case ATTRIBUTE: {
|
||||
|
@ -154,9 +154,7 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
|
|||
case JSON: {
|
||||
// TODO
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(_data, builder);
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(VPackSlice(_data), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
case SIMPLE: {
|
||||
|
@ -171,22 +169,8 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
|
|||
|
||||
case V8: {
|
||||
TRI_ASSERT(_func != nullptr);
|
||||
try {
|
||||
ISOLATE;
|
||||
return _func->execute(isolate, _ast->query(), trx, argv, startPos, vars,
|
||||
regs);
|
||||
} catch (arangodb::basics::Exception& ex) {
|
||||
if (_ast->query()->verboseErrors()) {
|
||||
ex.addToMessage(" while evaluating expression ");
|
||||
auto json = _node->toJson(TRI_UNKNOWN_MEM_ZONE, false);
|
||||
|
||||
if (json != nullptr) {
|
||||
ex.addToMessage(arangodb::basics::JsonHelper::toString(json));
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
ISOLATE;
|
||||
return _func->execute(isolate, _ast->query(), trx, argv, startPos, vars, regs);
|
||||
}
|
||||
|
||||
case UNPROCESSED: {
|
||||
|
@ -408,12 +392,11 @@ void Expression::buildExpression() {
|
|||
if (_type == JSON) {
|
||||
TRI_ASSERT(_data == nullptr);
|
||||
// generate a constant value
|
||||
_data = _node->toJsonValue(TRI_UNKNOWN_MEM_ZONE);
|
||||
VPackBuilder builder;
|
||||
_node->toVelocyPackValue(builder);
|
||||
|
||||
if (_data == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||
"invalid json in simple expression");
|
||||
}
|
||||
_data = new uint8_t[builder.size()];
|
||||
memcpy(_data, builder.data(), builder.size());
|
||||
} else if (_type == V8) {
|
||||
// generate a V8 expression
|
||||
_func = _executor->generateExpression(_node);
|
||||
|
@ -651,16 +634,7 @@ AqlValue$ Expression::executeSimpleExpressionArray(
|
|||
std::vector<Variable const*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
if (node->isConstant()) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
size_t const n = node->numMembers();
|
||||
|
@ -689,16 +663,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
|
|||
std::vector<Variable const*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
if (node->isConstant()) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
|
@ -725,15 +690,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue$ Expression::executeSimpleExpressionValue(AstNode const* node) {
|
||||
auto json = node->computeJson();
|
||||
|
||||
if (json == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
JsonHelper::toVelocyPack(json, builder);
|
||||
return AqlValue$(builder);
|
||||
return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1270,14 +1227,14 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
|
|||
trx, argv, startPos, vars, regs, true);
|
||||
|
||||
if (lhs.isObject()) {
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
AqlValue$ rhs = executeSimpleExpression(node->getMember(1),
|
||||
trx, argv, startPos, vars, regs, true);
|
||||
|
||||
if (rhs.isObject()) {
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
double const l = lhs.toDouble();
|
||||
|
@ -1298,17 +1255,17 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
|
|||
case NODE_TYPE_OPERATOR_BINARY_DIV:
|
||||
if (r == 0.0) {
|
||||
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO);
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
return AqlValue$(builder);
|
||||
case NODE_TYPE_OPERATOR_BINARY_MOD:
|
||||
if (r == 0.0) {
|
||||
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO);
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
builder.add(VPackValue(fmod(l, r)));
|
||||
return AqlValue$(builder);
|
||||
default:
|
||||
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
|
||||
return AqlValue$(VelocyPackHelper::NullValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -490,7 +490,7 @@ class Expression {
|
|||
union {
|
||||
V8Expression* _func;
|
||||
|
||||
struct TRI_json_t* _data;
|
||||
uint8_t* _data;
|
||||
|
||||
AttributeAccessor* _accessor;
|
||||
};
|
||||
|
|
|
@ -668,8 +668,7 @@ class PropagateConstantAttributesHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
if (TRI_CompareValuesJson(value->computeJson(), previous->computeJson(),
|
||||
true) != 0) {
|
||||
if (!value->computeValue().equals(previous->computeValue())) {
|
||||
// different value found for an already tracked attribute. better not
|
||||
// use this attribute
|
||||
(*it2).second = nullptr;
|
||||
|
|
Loading…
Reference in New Issue