1
0
Fork 0

Merge branch 'spdvpk' of github.com:arangodb/arangodb into spdvpk

This commit is contained in:
Michael Hackstein 2016-03-09 12:43:40 +01:00
commit 0294fd403b
6 changed files with 58 additions and 105 deletions

View File

@ -33,6 +33,7 @@
#include "VocBase/collection.h" #include "VocBase/collection.h"
#include <velocypack/Iterator.h> #include <velocypack/Iterator.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h> #include <velocypack/velocypack-aliases.h>
using namespace arangodb::aql; using namespace arangodb::aql;
@ -1046,25 +1047,22 @@ AstNode* Ast::createNodeIntersectedArray(AstNode const* lhs,
size_t const nl = lhs->numMembers(); size_t const nl = lhs->numMembers();
size_t const nr = rhs->numMembers(); size_t const nr = rhs->numMembers();
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash, std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
arangodb::basics::JsonEqual>
cache(nl + nr, arangodb::basics::JsonHash(),
arangodb::basics::JsonEqual());
for (size_t i = 0; i < nl; ++i) { for (size_t i = 0; i < nl; ++i) {
auto member = lhs->getMemberUnchecked(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(); auto node = createNodeArray();
for (size_t i = 0; i < nr; ++i) { for (size_t i = 0; i < nr; ++i) {
auto member = rhs->getMemberUnchecked(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()) { if (it != cache.end()) {
node->addMember((*it).second); 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 nl = lhs->numMembers();
size_t const nr = rhs->numMembers(); size_t const nr = rhs->numMembers();
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash, std::unordered_map<VPackSlice, AstNode const*> cache(nl + nr);
arangodb::basics::JsonEqual>
cache(nl + nr, arangodb::basics::JsonHash(),
arangodb::basics::JsonEqual());
for (size_t i = 0; i < nl + nr; ++i) { for (size_t i = 0; i < nl + nr; ++i) {
AstNode* member; AstNode* member;
@ -1097,9 +1092,9 @@ AstNode* Ast::createNodeUnionizedArray(AstNode const* lhs, AstNode const* rhs) {
} else { } else {
member = rhs->getMemberUnchecked(i - nl); member = rhs->getMemberUnchecked(i - nl);
} }
auto json = member->computeJson(); VPackSlice slice = member->computeValue();
cache.emplace(json, member); cache.emplace(slice, member);
} }
auto node = createNodeArray(); 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 // TODO: sort values in place first and compare two adjacent members each
std::unordered_map<TRI_json_t*, AstNode const*, arangodb::basics::JsonHash, std::unordered_map<VPackSlice, AstNode const*> cache(n);
arangodb::basics::JsonEqual>
cache(n, arangodb::basics::JsonHash(), arangodb::basics::JsonEqual());
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
auto member = node->getMemberUnchecked(i); auto member = node->getMemberUnchecked(i);
auto json = member->computeJson(); VPackSlice slice = member->computeValue();
if (cache.find(json) == cache.end()) { if (cache.find(slice) == cache.end()) {
cache.emplace(json, member); cache.emplace(slice, member);
} }
} }

View File

@ -40,6 +40,7 @@
#endif #endif
#include <velocypack/Builder.h> #include <velocypack/Builder.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h> #include <velocypack/velocypack-aliases.h>
#include <array> #include <array>
@ -432,7 +433,7 @@ static bool IsEmptyString(char const* p, size_t length) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AstNode::AstNode(AstNodeType type) 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 /// @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) { AstNode::AstNode(AstNodeType type, AstNodeValueType valueType) : AstNode(type) {
value.type = valueType; value.type = valueType;
TRI_ASSERT(flags == 0); 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); TRI_ASSERT(valueType == VALUE_TYPE_BOOL);
value.value._bool = v; value.value._bool = v;
TRI_ASSERT(flags == 0); 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); TRI_ASSERT(valueType == VALUE_TYPE_INT);
value.value._int = v; value.value._int = v;
TRI_ASSERT(flags == 0); 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); TRI_ASSERT(valueType == VALUE_TYPE_STRING);
setStringValue(v, length); setStringValue(v, length);
TRI_ASSERT(flags == 0); 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::AstNode(Ast* ast, arangodb::basics::Json const& json)
: AstNode(getNodeTypeFromJson(json)) { : AstNode(getNodeTypeFromJson(json)) {
TRI_ASSERT(flags == 0); TRI_ASSERT(flags == 0);
TRI_ASSERT(computedJson == nullptr); TRI_ASSERT(computedValue == nullptr);
auto query = ast->query(); auto query = ast->query();
@ -676,7 +677,7 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
arangodb::basics::Json const& json) arangodb::basics::Json const& json)
: AstNode(getNodeTypeFromJson(json)) { : AstNode(getNodeTypeFromJson(json)) {
TRI_ASSERT(flags == 0); TRI_ASSERT(flags == 0);
TRI_ASSERT(computedJson == nullptr); TRI_ASSERT(computedValue == nullptr);
switch (type) { switch (type) {
case NODE_TYPE_ATTRIBUTE_ACCESS: { case NODE_TYPE_ATTRIBUTE_ACCESS: {
@ -830,9 +831,8 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AstNode::~AstNode() { AstNode::~AstNode() {
if (computedJson != nullptr) { if (computedValue != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, computedJson); delete[] computedValue;
computedJson = nullptr;
} }
} }
@ -936,21 +936,23 @@ void AstNode::dump(int level) const {
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief compute the JSON for a constant value node /// @brief compute the value for a constant value node
/// the JSON is owned by the node and must not be freed by the caller /// 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 /// 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()); TRI_ASSERT(isConstant());
if (computedJson == nullptr) { if (computedValue == nullptr) {
// note: the following may fail but we do not need to VPackBuilder builder;
// check that here toVelocyPackValue(builder);
computedJson = toJsonValue(TRI_UNKNOWN_MEM_ZONE);
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/json.h"
#include "Basics/JsonHelper.h" #include "Basics/JsonHelper.h"
#include <velocypack/Slice.h>
#include <functional> #include <functional>
#include <iosfwd> #include <iosfwd>
@ -291,12 +293,12 @@ struct AstNode {
#endif #endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief compute the JSON for a constant value node /// @brief compute the value for a constant value node
/// the JSON is owned by the node and must not be freed by the caller /// 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 /// 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 /// @brief sort the members of an (array) node
@ -932,10 +934,10 @@ struct AstNode {
private: 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 /// @brief the node's sub nodes

View File

@ -104,7 +104,7 @@ Expression::~Expression() {
switch (_type) { switch (_type) {
case JSON: case JSON:
TRI_ASSERT(_data != nullptr); TRI_ASSERT(_data != nullptr);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data); delete[] _data;
break; break;
case ATTRIBUTE: { case ATTRIBUTE: {
@ -154,9 +154,7 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
case JSON: { case JSON: {
// TODO // TODO
TRI_ASSERT(_data != nullptr); TRI_ASSERT(_data != nullptr);
VPackBuilder builder; return AqlValue$(VPackSlice(_data), AqlValue$::AqlValueType::REFERENCE_STICKY);
JsonHelper::toVelocyPack(_data, builder);
return AqlValue$(builder);
} }
case SIMPLE: { case SIMPLE: {
@ -171,22 +169,8 @@ AqlValue$ Expression::execute(arangodb::AqlTransaction* trx,
case V8: { case V8: {
TRI_ASSERT(_func != nullptr); TRI_ASSERT(_func != nullptr);
try { ISOLATE;
ISOLATE; return _func->execute(isolate, _ast->query(), trx, argv, startPos, vars, regs);
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;
}
} }
case UNPROCESSED: { case UNPROCESSED: {
@ -408,12 +392,11 @@ void Expression::buildExpression() {
if (_type == JSON) { if (_type == JSON) {
TRI_ASSERT(_data == nullptr); TRI_ASSERT(_data == nullptr);
// generate a constant value // generate a constant value
_data = _node->toJsonValue(TRI_UNKNOWN_MEM_ZONE); VPackBuilder builder;
_node->toVelocyPackValue(builder);
if (_data == nullptr) { _data = new uint8_t[builder.size()];
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, memcpy(_data, builder.data(), builder.size());
"invalid json in simple expression");
}
} else if (_type == V8) { } else if (_type == V8) {
// generate a V8 expression // generate a V8 expression
_func = _executor->generateExpression(_node); _func = _executor->generateExpression(_node);
@ -651,16 +634,7 @@ AqlValue$ Expression::executeSimpleExpressionArray(
std::vector<Variable const*> const& vars, std::vector<Variable const*> const& vars,
std::vector<RegisterId> const& regs) { std::vector<RegisterId> const& regs) {
if (node->isConstant()) { if (node->isConstant()) {
auto json = node->computeJson(); return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
if (json == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
VPackBuilder builder;
JsonHelper::toVelocyPack(json, builder);
return AqlValue$(builder);
} }
size_t const n = node->numMembers(); size_t const n = node->numMembers();
@ -689,16 +663,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
std::vector<Variable const*> const& vars, std::vector<Variable const*> const& vars,
std::vector<RegisterId> const& regs) { std::vector<RegisterId> const& regs) {
if (node->isConstant()) { if (node->isConstant()) {
auto json = node->computeJson(); return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
if (json == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
VPackBuilder builder;
JsonHelper::toVelocyPack(json, builder);
return AqlValue$(builder);
} }
VPackBuilder builder; VPackBuilder builder;
@ -725,15 +690,7 @@ AqlValue$ Expression::executeSimpleExpressionObject(
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AqlValue$ Expression::executeSimpleExpressionValue(AstNode const* node) { AqlValue$ Expression::executeSimpleExpressionValue(AstNode const* node) {
auto json = node->computeJson(); return AqlValue$(node->computeValue(), AqlValue$::AqlValueType::REFERENCE_STICKY);
if (json == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
VPackBuilder builder;
JsonHelper::toVelocyPack(json, builder);
return AqlValue$(builder);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1270,14 +1227,14 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
trx, argv, startPos, vars, regs, true); trx, argv, startPos, vars, regs, true);
if (lhs.isObject()) { if (lhs.isObject()) {
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY); return AqlValue$(VelocyPackHelper::NullValue());
} }
AqlValue$ rhs = executeSimpleExpression(node->getMember(1), AqlValue$ rhs = executeSimpleExpression(node->getMember(1),
trx, argv, startPos, vars, regs, true); trx, argv, startPos, vars, regs, true);
if (rhs.isObject()) { if (rhs.isObject()) {
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY); return AqlValue$(VelocyPackHelper::NullValue());
} }
double const l = lhs.toDouble(); double const l = lhs.toDouble();
@ -1298,17 +1255,17 @@ AqlValue$ Expression::executeSimpleExpressionArithmetic(
case NODE_TYPE_OPERATOR_BINARY_DIV: case NODE_TYPE_OPERATOR_BINARY_DIV:
if (r == 0.0) { if (r == 0.0) {
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO); RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO);
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY); return AqlValue$(VelocyPackHelper::NullValue());
} }
return AqlValue$(builder); return AqlValue$(builder);
case NODE_TYPE_OPERATOR_BINARY_MOD: case NODE_TYPE_OPERATOR_BINARY_MOD:
if (r == 0.0) { if (r == 0.0) {
RegisterWarning(_ast, "/", TRI_ERROR_QUERY_DIVISION_BY_ZERO); 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))); builder.add(VPackValue(fmod(l, r)));
return AqlValue$(builder); return AqlValue$(builder);
default: default:
return AqlValue$(VelocyPackHelper::NullValue(), AqlValue$::AqlValueType::REFERENCE_STICKY); return AqlValue$(VelocyPackHelper::NullValue());
} }
} }

View File

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

View File

@ -668,8 +668,7 @@ class PropagateConstantAttributesHelper {
return; return;
} }
if (TRI_CompareValuesJson(value->computeJson(), previous->computeJson(), if (!value->computeValue().equals(previous->computeValue())) {
true) != 0) {
// different value found for an already tracked attribute. better not // different value found for an already tracked attribute. better not
// use this attribute // use this attribute
(*it2).second = nullptr; (*it2).second = nullptr;