1
0
Fork 0

less json

This commit is contained in:
Jan Steemann 2016-03-09 10:32:08 +01:00
parent 329b3d623f
commit c21d7fc2f4
6 changed files with 58 additions and 105 deletions

View File

@ -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);
}
}

View File

@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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());
}
}

View File

@ -490,7 +490,7 @@ class Expression {
union {
V8Expression* _func;
struct TRI_json_t* _data;
uint8_t* _data;
AttributeAccessor* _accessor;
};

View File

@ -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;