Skip to content

Commit

Permalink
Merge branch 'aql-argv-optimization' of https://github.com/arangodb/a…
Browse files Browse the repository at this point in the history
…rangodb into devel
  • Loading branch information
jsteemann committed Jun 18, 2015
2 parents 7f33d23 + c28ab58 commit 471b56d
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 180 deletions.
2 changes: 1 addition & 1 deletion arangod/Aql/AqlItemBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ Json AqlItemBlock::toJson (triagens::arango::AqlTransaction* trx) const {
else {
auto it = table.find(a);
if (it == table.end()) {
raw(a.toJson(trx, _docColls[column]));
raw(a.toJson(trx, _docColls[column], true));
data(Json(1.0));
table.emplace(std::make_pair(a, pos++));
}
Expand Down
36 changes: 20 additions & 16 deletions arangod/Aql/AqlValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ triagens::basics::Json AqlValue::at (triagens::arango::AqlTransaction* trx,
size_t const n = current->size();
if (offset + i < n) {
auto vecCollection = current->getDocumentCollection(0);
return current->getValue(i - offset, 0).toJson(trx, vecCollection);
return current->getValue(i - offset, 0).toJson(trx, vecCollection, true);
}
offset += (*it)->size();
}
Expand Down Expand Up @@ -587,7 +587,7 @@ v8::Handle<v8::Value> AqlValue::toV8 (v8::Isolate* isolate,
size_t const n = current->size();
auto vecCollection = current->getDocumentCollection(0);
for (size_t i = 0; i < n; ++i) {
result->Set(j++, current->getValue(i, 0).toV8(isolate, trx, vecCollection));
result->Set(j++, current->getValueReference(i, 0).toV8(isolate, trx, vecCollection));
}
}
return result;
Expand Down Expand Up @@ -622,10 +622,14 @@ v8::Handle<v8::Value> AqlValue::toV8 (v8::Isolate* isolate,
////////////////////////////////////////////////////////////////////////////////

Json AqlValue::toJson (triagens::arango::AqlTransaction* trx,
TRI_document_collection_t const* document) const {
TRI_document_collection_t const* document,
bool copy) const {
switch (_type) {
case JSON: {
return _json->copy();
if (copy) {
return _json->copy();
}
return Json(_json->zone(), _json->json(), Json::NOFREE);
}

case SHAPED: {
Expand Down Expand Up @@ -682,7 +686,7 @@ Json AqlValue::toJson (triagens::arango::AqlTransaction* trx,
size_t const n = current->size();
auto vecCollection = current->getDocumentCollection(0);
for (size_t i = 0; i < n; ++i) {
json.add(current->getValue(i, 0).toJson(trx, vecCollection));
json.add(current->getValueReference(i, 0).toJson(trx, vecCollection, true));
}
}

Expand Down Expand Up @@ -777,7 +781,7 @@ uint64_t AqlValue::hash (triagens::arango::AqlTransaction* trx,
size_t const n = current->size();
auto vecCollection = current->getDocumentCollection(0);
for (size_t i = 0; i < n; ++i) {
json.add(current->getValue(i, 0).toJson(trx, vecCollection));
json.add(current->getValue(i, 0).toJson(trx, vecCollection, false));
}
}

Expand Down Expand Up @@ -989,7 +993,7 @@ Json AqlValue::extractArrayMember (triagens::arango::AqlTransaction* trx,
if (p < totalSize + (*it)->size()) {
// found the correct vector
auto vecCollection = (*it)->getDocumentCollection(0);
return (*it)->getValue(p - totalSize, 0).toJson(trx, vecCollection);
return (*it)->getValue(p - totalSize, 0).toJson(trx, vecCollection, copy);
}
totalSize += (*it)->size();
}
Expand Down Expand Up @@ -1037,7 +1041,7 @@ AqlValue AqlValue::CreateFromBlocks (triagens::arango::AqlTransaction* trx,

// only enumerate the registers that are left
for (auto const& reg : registers) {
values.set(variableNames[reg.first], current->getValueReference(i, reg.first).toJson(trx, reg.second));
values.set(variableNames[reg.first], current->getValueReference(i, reg.first).toJson(trx, reg.second, true));
}

json->add(values);
Expand Down Expand Up @@ -1067,7 +1071,7 @@ AqlValue AqlValue::CreateFromBlocks (triagens::arango::AqlTransaction* trx,
auto document = current->getDocumentCollection(expressionRegister);

for (size_t i = 0; i < current->size(); ++i) {
json->add(current->getValueReference(i, expressionRegister).toJson(trx, document));
json->add(current->getValueReference(i, expressionRegister).toJson(trx, document, true));
}
}

Expand Down Expand Up @@ -1098,48 +1102,48 @@ int AqlValue::Compare (triagens::arango::AqlTransaction* trx,
(right._type == AqlValue::SHAPED ||
right._type == AqlValue::RANGE ||
right._type == AqlValue::DOCVEC)) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
triagens::basics::Json rjson = right.toJson(trx, rightcoll, false);
return TRI_CompareValuesJson(left._json->json(), rjson.json(), compareUtf8);
}

// SHAPED against x
if (left._type == AqlValue::SHAPED) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
triagens::basics::Json ljson = left.toJson(trx, leftcoll, false);

if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), compareUtf8);
}
else if (right._type == AqlValue::RANGE ||
right._type == AqlValue::DOCVEC) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
triagens::basics::Json rjson = right.toJson(trx, rightcoll, false);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), compareUtf8);
}
}

// RANGE against x
if (left._type == AqlValue::RANGE) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
triagens::basics::Json ljson = left.toJson(trx, leftcoll, false);

if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), compareUtf8);
}
else if (right._type == AqlValue::SHAPED ||
right._type == AqlValue::DOCVEC) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
triagens::basics::Json rjson = right.toJson(trx, rightcoll, false);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), compareUtf8);
}
}

// DOCVEC against x
if (left._type == AqlValue::DOCVEC) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
triagens::basics::Json ljson = left.toJson(trx, leftcoll, false);

if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), compareUtf8);
}
else if (right._type == AqlValue::SHAPED ||
right._type == AqlValue::RANGE) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
triagens::basics::Json rjson = right.toJson(trx, rightcoll, false);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), compareUtf8);
}
}
Expand Down
3 changes: 2 additions & 1 deletion arangod/Aql/AqlValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////

triagens::basics::Json toJson (triagens::arango::AqlTransaction*,
TRI_document_collection_t const*) const;
TRI_document_collection_t const*,
bool) const;

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a hash value for the AqlValue
Expand Down
18 changes: 9 additions & 9 deletions arangod/Aql/ExecutionBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ void IndexRangeBlock::buildExpressions () {
a.destroy(); // the TRI_json_t* of a._json has been stolen
}
else if (a._type == AqlValue::SHAPED || a._type == AqlValue::DOCVEC) {
bound = a.toJson(_trx, myCollection);
bound = a.toJson(_trx, myCollection, true);
a.destroy(); // the TRI_json_t* of a._json has been stolen
}
else {
Expand Down Expand Up @@ -1253,7 +1253,7 @@ void IndexRangeBlock::buildExpressions () {
a.destroy(); // the TRI_json_t* of a._json has been stolen
}
else if (a._type == AqlValue::SHAPED || a._type == AqlValue::DOCVEC) {
bound = a.toJson(_trx, myCollection);
bound = a.toJson(_trx, myCollection, true);
a.destroy(); // the TRI_json_t* of a._json has been stolen
}
else {
Expand Down Expand Up @@ -3620,7 +3620,7 @@ void SortedAggregateBlock::emitGroup (AqlItemBlock const* cur,
// that a group might theoretically consist of multiple documents, from different collections. but there
// is only one collection pointer per output register
auto document = cur->getDocumentCollection((*it).second);
res->setValue(row, (*it).first, AqlValue(new Json(_currentGroup.groupValues[i].toJson(_trx, document))));
res->setValue(row, (*it).first, AqlValue(new Json(_currentGroup.groupValues[i].toJson(_trx, document, true))));
}
else {
res->setValue(row, (*it).first, _currentGroup.groupValues[i]);
Expand Down Expand Up @@ -4806,7 +4806,7 @@ AqlItemBlock* InsertBlock::work (std::vector<AqlItemBlock*>& blocks) {

if (errorCode == TRI_ERROR_NO_ERROR) {
TRI_doc_mptr_copy_t mptr;
auto json = a.toJson(_trx, document);
auto json = a.toJson(_trx, document, false);

if (isEdgeCollection) {
// edge
Expand Down Expand Up @@ -4937,7 +4937,7 @@ AqlItemBlock* UpdateBlock::work (std::vector<AqlItemBlock*>& blocks) {

if (errorCode == TRI_ERROR_NO_ERROR) {
TRI_doc_mptr_copy_t mptr;
auto json = a.toJson(_trx, document);
auto json = a.toJson(_trx, document, true);

// read old document
TRI_doc_mptr_copy_t oldDocument;
Expand Down Expand Up @@ -5116,8 +5116,8 @@ AqlItemBlock* UpsertBlock::work (std::vector<AqlItemBlock*>& blocks) {
AqlValue updateDoc = res->getValue(i, updateRegisterId);

if (updateDoc.isObject()) {
auto updateJson = updateDoc.toJson(_trx, updateDocument);
auto searchJson = a.toJson(_trx, keyDocument);
auto const updateJson = updateDoc.toJson(_trx, updateDocument, false);
auto searchJson = a.toJson(_trx, keyDocument, true);

if (! searchJson.isObject()) {
errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
Expand Down Expand Up @@ -5212,7 +5212,7 @@ AqlItemBlock* UpsertBlock::work (std::vector<AqlItemBlock*>& blocks) {
}

if (errorCode == TRI_ERROR_NO_ERROR) {
auto insertJson = insertDoc.toJson(_trx, insertDocument);
auto const insertJson = insertDoc.toJson(_trx, insertDocument, true);

// use default value
errorCode = TRI_ERROR_OUT_OF_MEMORY;
Expand Down Expand Up @@ -5369,7 +5369,7 @@ AqlItemBlock* ReplaceBlock::work (std::vector<AqlItemBlock*>& blocks) {

if (errorCode == TRI_ERROR_NO_ERROR) {
TRI_doc_mptr_copy_t mptr;
auto json = a.toJson(_trx, document);
auto const json = a.toJson(_trx, document, true);

// all exceptions are caught in _trx->update()
errorCode = _trx->update(trxCollection, key, 0, &mptr, json.json(), TRI_DOC_UPDATE_LAST_WRITE, 0, nullptr, ep->_options.waitForSync);
Expand Down
28 changes: 20 additions & 8 deletions arangod/Aql/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
TRI_document_collection_t const* myCollection = nullptr;

AqlValue result = executeSimpleExpression(member, &myCollection, trx, argv, startPos, vars, regs, false);
array->add(result.toJson(trx, myCollection));
array->add(result.toJson(trx, myCollection, true));
result.destroy();
}

Expand Down Expand Up @@ -599,7 +599,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
member = member->getMember(0);

AqlValue result = executeSimpleExpression(member, &myCollection, trx, argv, startPos, vars, regs, false);
object->set(key, result.toJson(trx, myCollection));
object->set(key, result.toJson(trx, myCollection, true));
result.destroy();
}
return AqlValue(object.release());
Expand Down Expand Up @@ -644,20 +644,32 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
auto func = static_cast<Function*>(node->getData());
TRI_ASSERT(func->implementation != nullptr);

TRI_document_collection_t const* myCollection = nullptr;
auto member = node->getMemberUnchecked(0);
TRI_ASSERT(member->type == NODE_TYPE_ARRAY);

AqlValue result = executeSimpleExpression(member, &myCollection, trx, argv, startPos, vars, regs, false);

size_t const n = member->numMembers();
FunctionParameters parameters;
parameters.reserve(n);

try {
auto res2 = func->implementation(_ast->query(), trx, myCollection, result);
result.destroy();
for (size_t i = 0; i < n; ++i) {
TRI_document_collection_t const* myCollection = nullptr;
auto value = executeSimpleExpression(member->getMemberUnchecked(i), &myCollection, trx, argv, startPos, vars, regs, false);
parameters.emplace_back(std::make_pair(value, myCollection));
}

auto res2 = func->implementation(_ast->query(), trx, parameters);

for (auto& it : parameters) {
it.first.destroy();
}
return res2;
}
catch (...) {
// prevent leak and rethrow error
result.destroy();
for (auto& it : parameters) {
it.first.destroy();
}
throw;
}
}
Expand Down
Loading

0 comments on commit 471b56d

Please sign in to comment.